mirror of
https://github.com/MacPaw/XADMaster.git
synced 2025-08-28 19:13:49 +02:00
523 lines
18 KiB
Objective-C
523 lines
18 KiB
Objective-C
/*
|
|
* XADArchiveParserDescriptions.m
|
|
*
|
|
* Copyright (c) 2017-present, MacPaw Inc. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301 USA
|
|
*/
|
|
#import "XADArchiveParserDescriptions.h"
|
|
#import "XADRegex.h"
|
|
|
|
@implementation XADArchiveParser (Descriptions)
|
|
|
|
-(NSString *)descriptionOfValueInDictionary:(NSDictionary *)dict key:(NSString *)key
|
|
{
|
|
id object=[dict objectForKey:key];
|
|
if(!object) return nil;
|
|
|
|
if([key matchedByPattern:@"CRC32$"])
|
|
{
|
|
if(![object isKindOfClass:[NSNumber class]]) return [object description];
|
|
return [NSString stringWithFormat:@"0x%08x",[object unsignedIntValue]];
|
|
}
|
|
else if([key matchedByPattern:@"CRC16$"])
|
|
{
|
|
if(![object isKindOfClass:[NSNumber class]]) return [object description];
|
|
return [NSString stringWithFormat:@"0x%04x",[object unsignedIntValue]];
|
|
}
|
|
else if([key matchedByPattern:@"Is[A-Z0-9]"])
|
|
{
|
|
if(![object isKindOfClass:[NSNumber class]]) return [object description];
|
|
return XADHumanReadableBoolean([object longLongValue]);
|
|
}
|
|
else if([key isEqual:XADFileSizeKey]||[key isEqual:XADCompressedSizeKey])
|
|
{
|
|
if(![object isKindOfClass:[NSNumber class]]) return [object description];
|
|
return XADHumanReadableFileSize([object longLongValue]);
|
|
}
|
|
else if([key isEqual:XADPosixPermissionsKey])
|
|
{
|
|
if(![object isKindOfClass:[NSNumber class]]) return [object description];
|
|
return XADHumanReadablePOSIXPermissions([object longLongValue]);
|
|
}
|
|
else if([key isEqual:XADAmigaProtectionBitsKey])
|
|
{
|
|
if(![object isKindOfClass:[NSNumber class]]) return [object description];
|
|
return XADHumanReadableAmigaProtectionBits([object longLongValue]);
|
|
}
|
|
else if([key isEqual:XADDOSFileAttributesKey])
|
|
{
|
|
if(![object isKindOfClass:[NSNumber class]]) return [object description];
|
|
return XADHumanReadableDOSFileAttributes([object longLongValue]);
|
|
}
|
|
else if([key isEqual:XADWindowsFileAttributesKey])
|
|
{
|
|
if(![object isKindOfClass:[NSNumber class]]) return [object description];
|
|
return XADHumanReadableWindowsFileAttributes([object longLongValue]);
|
|
}
|
|
else if([key isEqual:XADFileTypeKey]||[key isEqual:XADFileCreatorKey])
|
|
{
|
|
if(![object isKindOfClass:[NSNumber class]]) return [object description];
|
|
return XADHumanReadableOSType([object longLongValue]);
|
|
}
|
|
else if([key isEqual:XADFinderFlagsKey])
|
|
{
|
|
if(![object isKindOfClass:[NSNumber class]]) return [object description];
|
|
return [NSString stringWithFormat:@"0x%04llx",[object longLongValue]];
|
|
}
|
|
else
|
|
{
|
|
return XADHumanReadableObject(object);
|
|
}
|
|
}
|
|
|
|
-(NSString *)descriptionOfKey:(NSString *)key
|
|
{
|
|
static NSDictionary *descriptions=nil;
|
|
if(!descriptions) descriptions=[[NSDictionary alloc] initWithObjectsAndKeys:
|
|
NSLocalizedString(@"Comment",@""),XADCommentKey,
|
|
NSLocalizedString(@"Name",@""),XADFileNameKey,
|
|
NSLocalizedString(@"Size",@""),XADFileSizeKey,
|
|
NSLocalizedString(@"Compressed size",@""),XADCompressedSizeKey,
|
|
NSLocalizedString(@"Compression type",@""),XADCompressionNameKey,
|
|
|
|
NSLocalizedString(@"Is a directory",@""),XADIsDirectoryKey,
|
|
NSLocalizedString(@"Is a Mac OS resource fork",@""),XADIsResourceForkKey,
|
|
NSLocalizedString(@"Is an archive",@""),XADIsArchiveKey,
|
|
NSLocalizedString(@"Is hidden",@""),XADIsHiddenKey,
|
|
NSLocalizedString(@"Is a link",@""),XADIsLinkKey,
|
|
NSLocalizedString(@"Is a hard link",@""),XADIsHardLinkKey,
|
|
NSLocalizedString(@"Link destination",@""),XADLinkDestinationKey,
|
|
NSLocalizedString(@"Is a Unix character device",@""),XADIsCharacterDeviceKey,
|
|
NSLocalizedString(@"Is a Unix block device",@""),XADIsBlockDeviceKey,
|
|
NSLocalizedString(@"Unix major device number",@""),XADDeviceMajorKey,
|
|
NSLocalizedString(@"Unix minor device number",@""),XADDeviceMinorKey,
|
|
NSLocalizedString(@"Is a Unix FIFO",@""),XADIsFIFOKey,
|
|
NSLocalizedString(@"Is encrypted",@""),XADIsEncryptedKey,
|
|
NSLocalizedString(@"Is corrupted",@""),XADIsCorruptedKey,
|
|
|
|
NSLocalizedString(@"Last modified",@""),XADLastModificationDateKey,
|
|
NSLocalizedString(@"Last accessed",@""),XADLastAccessDateKey,
|
|
NSLocalizedString(@"Last attribute change",@""),XADLastAttributeChangeDateKey,
|
|
NSLocalizedString(@"Last backup",@""),XADLastBackupDateKey,
|
|
NSLocalizedString(@"Created",@""),XADCreationDateKey,
|
|
|
|
NSLocalizedString(@"Extended attributes",@""),XADExtendedAttributesKey,
|
|
NSLocalizedString(@"Mac OS type code",@""),XADFileTypeKey,
|
|
NSLocalizedString(@"Mac OS creator code",@""),XADFileCreatorKey,
|
|
NSLocalizedString(@"Mac OS Finder flags",@""),XADFinderFlagsKey,
|
|
NSLocalizedString(@"Mac OS Finder info",@""),XADFinderInfoKey,
|
|
NSLocalizedString(@"Unix permissions",@""),XADPosixPermissionsKey,
|
|
NSLocalizedString(@"Unix user number",@""),XADPosixUserKey,
|
|
NSLocalizedString(@"Unix group number",@""),XADPosixGroupKey,
|
|
NSLocalizedString(@"Unix user name",@""),XADPosixUserNameKey,
|
|
NSLocalizedString(@"Unix group name",@""),XADPosixGroupNameKey,
|
|
NSLocalizedString(@"DOS file attributes",@""),XADDOSFileAttributesKey,
|
|
NSLocalizedString(@"Windows file attributes",@""),XADWindowsFileAttributesKey,
|
|
NSLocalizedString(@"Amiga protection bits",@""),XADAmigaProtectionBitsKey,
|
|
|
|
NSLocalizedString(@"Index in file",@""),XADIndexKey,
|
|
NSLocalizedString(@"Start of data",@""),XADDataOffsetKey,
|
|
NSLocalizedString(@"Length of data",@""),XADDataLengthKey,
|
|
NSLocalizedString(@"Start of data (minus skips)",@""),XADSkipOffsetKey,
|
|
NSLocalizedString(@"Length of data (minus skips)",@""),XADSkipLengthKey,
|
|
|
|
NSLocalizedString(@"Is a solid archive file",@""),XADIsSolidKey,
|
|
NSLocalizedString(@"Index of first solid file",@""),XADFirstSolidIndexKey,
|
|
NSLocalizedString(@"Pointer to first solid file",@""),XADFirstSolidEntryKey,
|
|
NSLocalizedString(@"Index of next solid file",@""),XADNextSolidIndexKey,
|
|
NSLocalizedString(@"Pointer to next solid file",@""),XADNextSolidEntryKey,
|
|
NSLocalizedString(@"Internal solid identifier",@""),XADSolidObjectKey,
|
|
NSLocalizedString(@"Start of data in solid stream",@""),XADSolidOffsetKey,
|
|
NSLocalizedString(@"Length of data in solid stream",@""),XADSolidLengthKey,
|
|
|
|
NSLocalizedString(@"Archive name",@""),XADArchiveNameKey,
|
|
NSLocalizedString(@"Archive volumes",@""),XADVolumesKey,
|
|
NSLocalizedString(@"Disk label",@""),XADDiskLabelKey,
|
|
nil];
|
|
|
|
NSString *description=[descriptions objectForKey:key];
|
|
if(description) return description;
|
|
|
|
return key;
|
|
}
|
|
|
|
static NSComparisonResult OrderKeys(id first,id second,void *context);
|
|
|
|
-(NSArray *)descriptiveOrderingOfKeysInDictionary:(NSDictionary *)dict
|
|
{
|
|
static NSDictionary *ordering=nil;
|
|
if(!ordering) ordering=[[NSDictionary alloc] initWithObjectsAndKeys:
|
|
[NSNumber numberWithInt:100],XADFileNameKey,
|
|
[NSNumber numberWithInt:101],XADCommentKey,
|
|
[NSNumber numberWithInt:102],XADFileSizeKey,
|
|
[NSNumber numberWithInt:103],XADCompressedSizeKey,
|
|
[NSNumber numberWithInt:104],XADCompressionNameKey,
|
|
|
|
[NSNumber numberWithInt:200],XADIsDirectoryKey,
|
|
[NSNumber numberWithInt:201],XADIsResourceForkKey,
|
|
[NSNumber numberWithInt:202],XADIsArchiveKey,
|
|
[NSNumber numberWithInt:203],XADIsHiddenKey,
|
|
[NSNumber numberWithInt:204],XADIsLinkKey,
|
|
[NSNumber numberWithInt:205],XADIsHardLinkKey,
|
|
[NSNumber numberWithInt:206],XADLinkDestinationKey,
|
|
[NSNumber numberWithInt:207],XADIsCharacterDeviceKey,
|
|
[NSNumber numberWithInt:208],XADIsBlockDeviceKey,
|
|
[NSNumber numberWithInt:209],XADDeviceMajorKey,
|
|
[NSNumber numberWithInt:210],XADDeviceMinorKey,
|
|
[NSNumber numberWithInt:211],XADIsFIFOKey,
|
|
[NSNumber numberWithInt:212],XADIsEncryptedKey,
|
|
[NSNumber numberWithInt:213],XADIsCorruptedKey,
|
|
|
|
[NSNumber numberWithInt:300],XADLastModificationDateKey,
|
|
[NSNumber numberWithInt:301],XADLastAccessDateKey,
|
|
[NSNumber numberWithInt:302],XADLastAttributeChangeDateKey,
|
|
[NSNumber numberWithInt:303],XADLastBackupDateKey,
|
|
[NSNumber numberWithInt:304],XADCreationDateKey,
|
|
|
|
[NSNumber numberWithInt:400],XADExtendedAttributesKey,
|
|
[NSNumber numberWithInt:401],XADFileTypeKey,
|
|
[NSNumber numberWithInt:402],XADFileCreatorKey,
|
|
[NSNumber numberWithInt:403],XADFinderFlagsKey,
|
|
[NSNumber numberWithInt:404],XADFinderInfoKey,
|
|
[NSNumber numberWithInt:404],XADPosixPermissionsKey,
|
|
[NSNumber numberWithInt:405],XADPosixUserKey,
|
|
[NSNumber numberWithInt:406],XADPosixGroupKey,
|
|
[NSNumber numberWithInt:407],XADPosixUserNameKey,
|
|
[NSNumber numberWithInt:408],XADPosixGroupNameKey,
|
|
[NSNumber numberWithInt:409],XADDOSFileAttributesKey,
|
|
[NSNumber numberWithInt:410],XADWindowsFileAttributesKey,
|
|
[NSNumber numberWithInt:411],XADAmigaProtectionBitsKey,
|
|
|
|
[NSNumber numberWithInt:500],XADIndexKey,
|
|
[NSNumber numberWithInt:501],XADDataOffsetKey,
|
|
[NSNumber numberWithInt:502],XADDataLengthKey,
|
|
[NSNumber numberWithInt:503],XADSkipOffsetKey,
|
|
[NSNumber numberWithInt:504],XADSkipLengthKey,
|
|
|
|
[NSNumber numberWithInt:600],XADIsSolidKey,
|
|
[NSNumber numberWithInt:601],XADFirstSolidIndexKey,
|
|
[NSNumber numberWithInt:602],XADFirstSolidEntryKey,
|
|
[NSNumber numberWithInt:603],XADNextSolidIndexKey,
|
|
[NSNumber numberWithInt:604],XADNextSolidEntryKey,
|
|
[NSNumber numberWithInt:605],XADSolidObjectKey,
|
|
[NSNumber numberWithInt:606],XADSolidOffsetKey,
|
|
[NSNumber numberWithInt:607],XADSolidLengthKey,
|
|
|
|
[NSNumber numberWithInt:700],XADArchiveNameKey,
|
|
[NSNumber numberWithInt:701],XADVolumesKey,
|
|
[NSNumber numberWithInt:702],XADDiskLabelKey,
|
|
nil];
|
|
|
|
return [[dict allKeys] sortedArrayUsingFunction:OrderKeys context:ordering];
|
|
}
|
|
|
|
static NSComparisonResult OrderKeys(id first,id second,void *context)
|
|
{
|
|
NSDictionary *ordering=context;
|
|
NSNumber *firstorder=[ordering objectForKey:first];
|
|
NSNumber *secondorder=[ordering objectForKey:second];
|
|
|
|
if(firstorder&&secondorder) return [firstorder compare:secondorder];
|
|
else if(firstorder) return NSOrderedAscending;
|
|
else if(secondorder) return NSOrderedDescending;
|
|
else return [first compare:second];
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
static NSString *DottedNumber(uint64_t size);
|
|
|
|
NSString *XADHumanReadableFileSize(uint64_t size)
|
|
{
|
|
if(size<1000) return [NSString localizedStringWithFormat:
|
|
NSLocalizedString(@"%lld bytes",@"Format string for human-redable sizes <1000"),
|
|
size];
|
|
else return [NSString localizedStringWithFormat:
|
|
NSLocalizedString(@"%@ (%@ bytes)",@"Format string for human-readable sizes >=1000"),
|
|
XADShortHumanReadableFileSize(size),DottedNumber(size)];
|
|
}
|
|
|
|
NSString *XADShortHumanReadableFileSize(uint64_t size)
|
|
{
|
|
if(size<1000)
|
|
{
|
|
return [NSString stringWithFormat:
|
|
NSLocalizedString(@"%lld B",@"Format string for short sizes expressed in bytes"),
|
|
size];
|
|
}
|
|
|
|
double value;
|
|
NSString *unitformat;
|
|
if(size<1000000)
|
|
{
|
|
value=size/1000.0;
|
|
unitformat=NSLocalizedString(@"%@ KB",@"Format string for short sizes expressed in kilobytes");
|
|
}
|
|
else if(size<1000000000)
|
|
{
|
|
value=size/1000000.0;
|
|
unitformat=NSLocalizedString(@"%@ MB",@"Format string for short sizes expressed in megabytes");
|
|
}
|
|
else
|
|
{
|
|
value=size/1000000000.0;
|
|
unitformat=NSLocalizedString(@"%@ GB",@"Format string for short sizes expressed in gigabytes");
|
|
}
|
|
|
|
NSString *number;
|
|
if(value<10) number=[NSString localizedStringWithFormat:@"%.2f",value];
|
|
else if(value<100) number=[NSString localizedStringWithFormat:@"%.1f",value];
|
|
else number=[NSString localizedStringWithFormat:@"%.0f",value];
|
|
|
|
return [NSString stringWithFormat:unitformat,number];
|
|
}
|
|
|
|
static NSString *DottedNumber(uint64_t size)
|
|
{
|
|
NSNumberFormatter *formatter=[[NSNumberFormatter new] autorelease];
|
|
formatter.formatterBehavior=NSNumberFormatterBehavior10_4;
|
|
formatter.numberStyle=NSNumberFormatterDecimalStyle;
|
|
return [formatter stringFromNumber:[NSNumber numberWithLongLong:size]];
|
|
}
|
|
|
|
NSString *XADHumanReadableBoolean(uint64_t boolean)
|
|
{
|
|
if(boolean==1) return NSLocalizedString(@"Yes",@"String for true values");
|
|
else if (boolean==0) return NSLocalizedString(@"No",@"String for false values");
|
|
else return [NSString stringWithFormat:@"%llx",boolean];
|
|
}
|
|
|
|
NSString *XADHumanReadablePOSIXPermissions(uint64_t permissions)
|
|
{
|
|
char str[10]="rwxrwxrwx";
|
|
for(int i=0;i<9;i++) if(!(permissions&(0400>>i))) str[i]='-';
|
|
return [NSString stringWithFormat:@"%s (%llo)",str,permissions];
|
|
}
|
|
|
|
NSString *XADHumanReadableAmigaProtectionBits(uint64_t protection)
|
|
{
|
|
char str[9]="hsparwed";
|
|
for(int i=0;i<8;i++) if(!((protection^0x0f)&(0x80>>i))) str[i]='-';
|
|
return [NSString stringWithFormat:@"%s (0x%02llx)",str,protection];
|
|
}
|
|
|
|
NSString *XADHumanReadableDOSFileAttributes(uint64_t attributes)
|
|
{
|
|
char str[9]="ADVSHR";
|
|
for(int i=0;i<6;i++) if(!(attributes&(0x20>>i))) str[i]='-';
|
|
return [NSString stringWithFormat:@"%s (0x%02llx)",str,attributes];
|
|
}
|
|
|
|
NSString *XADHumanReadableWindowsFileAttributes(uint64_t attributes)
|
|
{
|
|
char str[16]="EIOCLPTN AD SHR";
|
|
for(int i=0;i<15;i++) if(!(attributes&(0x4000>>i))) str[i]='-';
|
|
return [NSString stringWithFormat:@"%s (0x%04llx)",str,attributes];
|
|
}
|
|
|
|
NSString *XADHumanReadableOSType(uint64_t ostype)
|
|
{
|
|
char str[5]={0};
|
|
for(int i=0;i<4;i++)
|
|
{
|
|
uint8_t c=(ostype>>(24-i*8))&0xff;
|
|
if(c>=32&&c<=127) str[i]=c;
|
|
else str[i]='?';
|
|
}
|
|
return [NSString stringWithFormat:@"%s (0x%08llx)",str,ostype];
|
|
|
|
}
|
|
|
|
NSString *XADHumanReadableEntryWithDictionary(NSDictionary *dict,XADArchiveParser *parser)
|
|
{
|
|
NSArray *keys=[parser descriptiveOrderingOfKeysInDictionary:dict];
|
|
NSMutableArray *labels=[NSMutableArray array];
|
|
NSMutableArray *values=[NSMutableArray array];
|
|
|
|
NSEnumerator *enumerator=[keys objectEnumerator];
|
|
NSString *key;
|
|
while((key=[enumerator nextObject]))
|
|
{
|
|
NSString *label=[parser descriptionOfKey:key];
|
|
NSString *value=[parser descriptionOfValueInDictionary:dict key:key];
|
|
[labels addObject:label];
|
|
[values addObject:value];
|
|
}
|
|
|
|
return XADHumanReadableList(labels,values);
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef GNUSTEP
|
|
static NSString *GNUSTEPKludge_HumanReadableValue(NSValue *value);
|
|
#endif
|
|
|
|
NSString *XADHumanReadableObject(id object)
|
|
{
|
|
if ([object isKindOfClass:[NSDate class]]) return XADHumanReadableDate(object);
|
|
else if([object isKindOfClass:[NSData class]]) return XADHumanReadableData(object);
|
|
else if([object isKindOfClass:[NSArray class]]) return XADHumanReadableArray(object);
|
|
else if([object isKindOfClass:[NSDictionary class]]) return XADHumanReadableDictionary(object);
|
|
#ifdef GNUSTEP
|
|
else if([object isKindOfClass:[NSValue class]]) return GNUSTEPKludge_HumanReadableValue(object);
|
|
#endif
|
|
else return [object description];
|
|
}
|
|
|
|
NSString *XADHumanReadableDate(NSDate *date)
|
|
{
|
|
#ifndef __COCOTRON__
|
|
NSDateFormatter *formatter=[[NSDateFormatter new] autorelease];
|
|
[formatter setFormatterBehavior:NSDateFormatterBehavior10_4];
|
|
[formatter setDateStyle:NSDateFormatterFullStyle];
|
|
[formatter setTimeStyle:NSDateFormatterMediumStyle];
|
|
return [formatter stringForObjectValue:date];
|
|
#else
|
|
return [date description];
|
|
#endif
|
|
}
|
|
|
|
NSString *XADHumanReadableData(NSData *data)
|
|
{
|
|
NSMutableString *string=[NSMutableString string];
|
|
|
|
NSInteger length=[data length];
|
|
const uint8_t *bytes=[data bytes];
|
|
|
|
[string appendFormat:
|
|
NSLocalizedString(@"%llu bytes (",@"Format string for raw data objects"),
|
|
(uint64_t)length];
|
|
|
|
for(int i=0;i<length && i<256;i++)
|
|
{
|
|
if(i!=0 && (i&3)==0) [string appendString:@" "];
|
|
[string appendFormat:@"%02x",bytes[i]];
|
|
}
|
|
|
|
if(length>256) [string appendString:@"..."];
|
|
[string appendString:@")"];
|
|
|
|
return string;
|
|
}
|
|
|
|
NSString *XADHumanReadableArray(NSArray *array)
|
|
{
|
|
NSInteger count=[array count];
|
|
NSMutableArray *labels=[NSMutableArray array];
|
|
NSMutableArray *values=[NSMutableArray array];
|
|
|
|
for(int i=0;i<count;i++)
|
|
{
|
|
id value=[array objectAtIndex:i];
|
|
[labels addObject:[NSString stringWithFormat:@"%d",i]];
|
|
[values addObject:XADHumanReadableObject(value)];
|
|
}
|
|
|
|
return XADHumanReadableList(labels,values);
|
|
}
|
|
|
|
NSString *XADHumanReadableDictionary(NSDictionary *dict)
|
|
{
|
|
NSArray *keys=[[dict allKeys] sortedArrayUsingSelector:@selector(compare:)];
|
|
NSMutableArray *labels=[NSMutableArray array];
|
|
NSMutableArray *values=[NSMutableArray array];
|
|
|
|
NSEnumerator *enumerator=[keys objectEnumerator];
|
|
NSString *key;
|
|
while((key=[enumerator nextObject]))
|
|
{
|
|
id value=[dict objectForKey:key];
|
|
[labels addObject:key];
|
|
[values addObject:XADHumanReadableObject(value)];
|
|
}
|
|
|
|
return XADHumanReadableList(labels,values);
|
|
}
|
|
|
|
NSString *XADHumanReadableList(NSArray *labels,NSArray *values)
|
|
{
|
|
int maxlen=0;
|
|
NSInteger count=[labels count];
|
|
for(int i=0;i<count;i++)
|
|
{
|
|
NSString *label=[labels objectAtIndex:i];
|
|
int len=[label length];
|
|
|
|
if(len>maxlen) maxlen=len;
|
|
}
|
|
|
|
NSMutableString *string=[NSMutableString string];
|
|
for(int i=0;i<count;i++)
|
|
{
|
|
NSString *label=[labels objectAtIndex:i];
|
|
NSString *value=[values objectAtIndex:i];
|
|
int len=[label length];
|
|
|
|
[string appendString:label];
|
|
[string appendString:@": "];
|
|
|
|
for(int i=len;i<maxlen;i++) [string appendString:@" "];
|
|
|
|
[string appendString:XADIndentTextWithSpaces(value,maxlen+2)];
|
|
|
|
if(i!=count-1) [string appendString:@"\n"];
|
|
}
|
|
|
|
return string;
|
|
}
|
|
|
|
NSString *XADIndentTextWithSpaces(NSString *text,int spaces)
|
|
{
|
|
if([text rangeOfString:@"\n"].location==NSNotFound) return text;
|
|
|
|
NSMutableString *res=[NSMutableString string];
|
|
int length=[text length];
|
|
for(int i=0;i<length;i++)
|
|
{
|
|
unichar c=[text characterAtIndex:i];
|
|
[res appendFormat:@"%C",c];
|
|
if(c=='\n')
|
|
{
|
|
for(int j=0;j<spaces;j++) [res appendString:@" "];
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
#ifdef GNUSTEP
|
|
// GNUstep will dereference non-retained objects in NSValues. This is not safe, so avoid it.
|
|
static NSString *GNUSTEPKludge_HumanReadableValue(NSValue *value)
|
|
{
|
|
if(strcmp([value objCType],@encode(id))==0)
|
|
{
|
|
return [NSString stringWithFormat:@"<%p>",[value nonretainedObjectValue]];
|
|
}
|
|
else
|
|
{
|
|
return [value description];
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|