├── Chapter-01 ├── Makefile ├── objcbench.m ├── sumint-self-timing.ps ├── sumintcorefoundation.m ├── sumintfoundation.m ├── sumintobjc.m ├── sumints-nsn.m ├── sumints-ps.m ├── sumints.c ├── sumints.m ├── sumints.ps ├── sumints.py ├── sumints.rb ├── sumints.s ├── sumints.stsh ├── sumints_c.m ├── sumints_objc-self-timing.m ├── sumints_objc.m ├── sumintsc.m └── suminttagged.m ├── Chapter-04 ├── xmlparse-max.m ├── xmlparse-max.stsh ├── xmlparse-mpwsax.m ├── xmlparse-nssax.m └── xmlparse-nsxmldocument.stsh ├── Chapter-05 ├── malloc-size.m ├── mallocbench.m ├── memaccessbench-book.m ├── memaccessbench-indexed.m ├── memaccessbench-word.m ├── memaccessbench.m └── page-size.c ├── Chapter-06 └── leaks-cycles.swift ├── Chapter-07 ├── descriptionstream-case-analysis.m ├── descriptionstream-double-dispatch.m ├── nested-nsarrays-measure.swift ├── nested-nsarrays.swift ├── nsarray-description-infinite-stream.m ├── nsarray-description-infinite.m ├── nsarray-description-stream.m ├── nsarraydesc-accumulative.m ├── nsarraydesc-recursive.m ├── nsarraydesc.m └── stack-object.m ├── Chapter-08 └── upcase.c ├── Chapter-10 ├── upcase-single-char-buffered.c └── upcase-single-char.c ├── Chapter-11 ├── datamap-multiple.m ├── datamapping-complex.m ├── datamapping-simple.m └── datamapping.m ├── Chapter-12 ├── archiving-hierarchical.m ├── archiving.m ├── purge-file.m ├── unixread-full.m └── unixread.m ├── Chapter-13 └── DictTest │ ├── Classes │ ├── AccessorMacros.h │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── MPWBinaryPlist.h │ ├── MPWBinaryPlist.m │ ├── MPWIntArray.h │ ├── MPWIntArray.m │ ├── ViewController.h │ ├── ViewController.m │ ├── nspl │ └── nspl.m │ ├── DictTest.xcodeproj │ ├── marcel.mode1v3 │ ├── marcel.pbxuser │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── marcel.xcuserdatad │ │ │ ├── UserInterfaceState.xcuserstate │ │ │ └── WorkspaceSettings.xcsettings │ ├── wlt.mode2v3 │ ├── wlt.pbxuser │ └── xcuserdata │ │ └── marcel.xcuserdatad │ │ └── xcschemes │ │ ├── DictTest.xcscheme │ │ └── xcschememanagement.plist │ ├── DictTest_Prefix.pch │ ├── Info.plist │ ├── MainWindow.xib │ ├── Picture 1.png │ ├── SimpleStdioStringDict.h │ ├── SimpleStdioStringDict.m │ ├── StringTable.h │ ├── StringTable.m │ ├── ViewController.xib │ ├── dictionary.txt │ ├── dictionary_bin.plist │ ├── dictionary_xml.plist │ └── main.m ├── Chapter-14 ├── GLBench │ ├── GLBench.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ ├── xcshareddata │ │ │ │ └── GLBench.xccheckout │ │ │ └── xcuserdata │ │ │ │ └── marcel.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcuserdata │ │ │ └── marcel.xcuserdatad │ │ │ └── xcschemes │ │ │ ├── GLBench.xcscheme │ │ │ └── xcschememanagement.plist │ ├── GLBench │ │ ├── Base.lproj │ │ │ └── MainMenu.xib │ │ ├── GLBench-Info.plist │ │ ├── GLBench-Prefix.pch │ │ ├── GLBenchView.h │ │ ├── GLBenchView.m │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── MPWAppDelegate.h │ │ ├── MPWAppDelegate.m │ │ ├── en.lproj │ │ │ ├── Credits.rtf │ │ │ └── InfoPlist.strings │ │ └── main.m │ └── GLBenchTests │ │ ├── GLBenchTests-Info.plist │ │ ├── GLBenchTests.m │ │ └── en.lproj │ │ └── InfoPlist.strings └── letter-a-with-control-points.eps ├── Chapter-16 └── screen-refresh.swift └── Readme.md /Chapter-01/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all : objcbench sumintsc 3 | 4 | 5 | objcbench : objcbench.m 6 | cc -F/Library/Frameworks/ -Wall -Wnoshadow-ivar -arch x86_64 -Os -o objcbench objcbench.m -framework Cocoa -framework MPWFoundation 7 | 8 | sumintsc : sumintsc.m 9 | cc -Wall -Wnoshadow-ivar -Os -o sumintsc sumintsc.m -framework Foundation 10 | 11 | -------------------------------------------------------------------------------- /Chapter-01/sumint-self-timing.ps: -------------------------------------------------------------------------------- 1 | %! 2 | /Helvetica 25 selectfont 100 100 moveto 3 | /intshow { 20 string cvs show } bind def 4 | usertime 5 | 6 | 0 10000 { 0 0 1 1000 { add } for exch pop } bind repeat 7 | exch usertime exch sub intshow ( ms result: ) show intshow 8 | 9 | showpage 10 | 11 | -------------------------------------------------------------------------------- /Chapter-01/sumintcorefoundation.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | // tagged integers: 4 | // http://objectivistc.tumblr.com/post/7872364181/tagged-pointers-and-fast-pathed-cfnumber-integers-in 5 | // 6 | /* 7 | 6 5 4 3 2 1 0 8 | 3210987654321098765432109876543210987654321098765432109876543210 9 | ........................................................xxxx0011 10 | | | | +-- (1 bit) always 1 for tagged pointers 11 | | | +----- (3 bits) 001 is the tagged object class for integers 12 | | +--------- (4 bits) for integers, xxxx is either: 13 | | 0000 for 8-bit integers, 14 | | 0100 for 16-bit integers, 15 | | 1000 for 32-bit integers, 16 | | 1100 for 64-bit integers 17 | +------------------------------------------------------------------ (56 bits) payload with the actual integer value 18 | 19 | _objc_tagged_isa_table[]) 20 | 21 | 22 | The next 3 bits (from lowest to highest) define the tagged object class. At the moment, there are classes for 23 | integers, managed objects, and dates; 24 | 25 | */ 26 | 27 | #define TAGGED_INTS 1 28 | 29 | 30 | static inline int getInt( NSNumber *o ) { 31 | long long n=(long long)o; 32 | if ( n & 1 ) { 33 | return n >> 8; 34 | } else { 35 | return [o intValue]; 36 | } 37 | } 38 | 39 | static inline NSNumber *makeInt( int i ) { 40 | 41 | long long o=i; 42 | o=(o << 8) | 0x83; 43 | return (NSNumber*)o; 44 | } 45 | 46 | int main( int argc , char *argv[] ) 47 | { 48 | int i,k; 49 | id pool=[NSAutoreleasePool new]; 50 | NSNumber* sum = nil; 51 | #if 0 52 | for (i=0;i<100;i++) { 53 | NSNumber *n=[NSNumber numberWithInt:i]; 54 | NSLog(@"%d: %p -> %d",i,n,((long long)n)>>8); 55 | } 56 | #endif 57 | for (k=0;k<100000; k++ ) { 58 | id inner=[NSAutoreleasePool new]; 59 | #if TAGGED_INTS 60 | sum =makeInt(0); 61 | #else 62 | sum =[NSNumber numberWithInt:0]; 63 | #endif 64 | for (i=1;i<=1000;i++) { 65 | #if TAGGED_INTS 66 | sum =makeInt(getInt(sum)+i); 67 | #else 68 | sum =[NSNumber numberWithInt:[sum intValue]+1]; 69 | #endif 70 | } 71 | [sum retain]; 72 | [inner drain]; 73 | [sum autorelease]; 74 | } 75 | NSLog(@"%@/%@ -> '%@'",sum,[sum class],[sum stringValue]); 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /Chapter-01/sumintfoundation.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | // tagged integers: 4 | // http://objectivistc.tumblr.com/post/7872364181/tagged-pointers-and-fast-pathed-cfnumber-integers-in 5 | // 6 | /* 7 | 6 5 4 3 2 1 0 8 | 3210987654321098765432109876543210987654321098765432109876543210 9 | ........................................................xxxx0011 10 | | | | +-- (1 bit) always 1 for tagged pointers 11 | | | +----- (3 bits) 001 is the tagged object class for integers 12 | | +--------- (4 bits) for integers, xxxx is either: 13 | | 0000 for 8-bit integers, 14 | | 0100 for 16-bit integers, 15 | | 1000 for 32-bit integers, 16 | | 1100 for 64-bit integers 17 | +------------------------------------------------------------------ (56 bits) payload with the actual integer value 18 | 19 | _objc_tagged_isa_table[]) 20 | 21 | 22 | The next 3 bits (from lowest to highest) define the tagged object class. At the moment, there are classes for 23 | integers, managed objects, and dates; 24 | 25 | */ 26 | 27 | #define TAGGED_INTS 1 28 | 29 | 30 | static inline int getInt( NSNumber *o ) { 31 | long long n=(long long)o; 32 | if ( n & 1 ) { 33 | return n >> 8; 34 | } else { 35 | return [o intValue]; 36 | } 37 | } 38 | 39 | static inline NSNumber *makeInt( int i ) { 40 | 41 | long long o=i; 42 | o=(o << 8) | 0x83; 43 | return (NSNumber*)o; 44 | } 45 | 46 | int main( int argc , char *argv[] ) 47 | { 48 | int i,k; 49 | id pool=[NSAutoreleasePool new]; 50 | NSNumber* sum = nil; 51 | #if 0 52 | for (i=0;i<100;i++) { 53 | NSNumber *n=[NSNumber numberWithInt:i]; 54 | NSLog(@"%d: %p -> %d",i,n,((long long)n)>>8); 55 | } 56 | #endif 57 | for (k=0;k<100000; k++ ) { 58 | id inner=[NSAutoreleasePool new]; 59 | #if TAGGED_INTS 60 | sum =makeInt(0); 61 | #else 62 | sum =[NSNumber numberWithInt:0]; 63 | #endif 64 | for (i=1;i<=1000;i++) { 65 | #if TAGGED_INTS 66 | sum =makeInt(getInt(sum)+i); 67 | #else 68 | sum =[NSNumber numberWithInt:[sum intValue]+1]; 69 | #endif 70 | } 71 | [sum retain]; 72 | [inner drain]; 73 | [sum autorelease]; 74 | } 75 | NSLog(@"%@/%@ -> '%@'",sum,[sum class],[sum stringValue]); 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /Chapter-01/sumintobjc.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface Summer : NSObject 4 | { 5 | long long sum; 6 | } 7 | 8 | -(void)add:(int)i; 9 | @end 10 | 11 | @implementation Summer 12 | 13 | -(void)add:(int)newVal { sum+=newVal; } 14 | -description { return [[NSNumber numberWithLongLong:sum] description]; } 15 | 16 | @end 17 | 18 | int main( int argc , char *argv[] ) 19 | { 20 | id pool=[NSAutoreleasePool new]; 21 | int i; 22 | int k; 23 | id summer=nil; 24 | summer=[Summer new]; 25 | IMP f_add=[summer methodForSelector:@selector(add:)]; 26 | for (k=0;k<1000000; k++ ){ 27 | for (i=1;i<=1000;i++) { 28 | // f_add( summer, @selector(add:), i); 29 | [summer add:i]; 30 | } 31 | } 32 | NSLog(@"%@",summer); 33 | } 34 | -------------------------------------------------------------------------------- /Chapter-01/sumints-nsn.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface Summer : NSObject 4 | { 5 | NSNumber *sum; 6 | } 7 | 8 | -(NSNumber*)sum; 9 | -(void)add:(NSNumber*)newNumber; 10 | @end 11 | 12 | @implementation Summer 13 | 14 | -(NSNumber*)sum { return sum; } 15 | -(void)add:(NSNumber*)newValue { sum= [NSNumber numberWithInt:[sum intValue]+[newValue intValue]]; } 16 | 17 | @end 18 | 19 | int main( int argc , char *argv[] ) 20 | { 21 | id pool=[NSAutoreleasePool new]; 22 | id summer=[Summer new]; 23 | char buffer[80]; 24 | while ( fgets( buffer, 70, stdin )) { 25 | [summer add:[NSNumber numberWithInt:atoi( buffer )]]; 26 | } 27 | NSLog(@"%@",[summer sum]); 28 | } 29 | -------------------------------------------------------------------------------- /Chapter-01/sumints-ps.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | int main( int argc , char *argv[] ) 5 | { 6 | int j; 7 | int i,max=atoi(argv[1]); 8 | id pool=[NSAutoreleasePool new]; 9 | MPWPSInterpreter* interpreter=[MPWPSInterpreter stream]; 10 | [interpreter push:[interpreter makeInt:0]]; 11 | // id stack=[interpreter operandStack]; 12 | for (j=0;j<10;j++) { 13 | for (i=1;i<= max;i++ ) { 14 | // interpreter->push( stack, 0, interpreter->self_makeInt( interpreter, 0 ,i )); 15 | [interpreter pushInt:i]; 16 | // [interpreter push:[interpreter makeInt:i]]; 17 | [interpreter add]; 18 | } 19 | } 20 | NSLog(@"sum: %@",[interpreter tos]); 21 | exit(0) ; 22 | [pool release]; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /Chapter-01/sumints.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main( int argc , char *argv[] ) 5 | { 6 | long k; 7 | long i,sum,totalSum,max=1000,numIter=1000; 8 | 9 | if ( argc > 1 ) { 10 | numIter=atol(argv[1]); 11 | } 12 | if ( argc > 2 ) { 13 | max=atol(argv[2]); 14 | } 15 | totalSum=0; 16 | for (k=0;k 2 | 3 | 4 | int main( int argc , char *argv[] ) 5 | { 6 | int i,max=atoi(argv[1]); 7 | id pool=[NSAutoreleasePool new]; 8 | NSNumber *sum=[NSNumber numberWithInt:0]; 9 | for (i=1;i<= max;i++ ) { 10 | NSNumber *cur=[NSNumber numberWithInt:i]; 11 | sum=[NSNumber numberWithLongLong:[sum longLongValue]+[cur intValue]]; 12 | } 13 | NSLog(@"sum: %@",sum); 14 | exit(0) ; 15 | [pool release]; 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /Chapter-01/sumints.ps: -------------------------------------------------------------------------------- 1 | %! 2 | /numIters 1 def 3 | 4 | numIters 100000 mul { 0 0 1 1000 { add } for } bind repeat == 5 | -------------------------------------------------------------------------------- /Chapter-01/sumints.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | for i in range(int(sys.argv[1])): 4 | sum=0 5 | for k in range(1,10000+1): 6 | sum=sum+k 7 | print sum 8 | -------------------------------------------------------------------------------- /Chapter-01/sumints.rb: -------------------------------------------------------------------------------- 1 | total=0; 2 | for k in 1..ARGV[0].to_i * 1000 3 | sum=0; 4 | for i in 1..1000 5 | sum+=i; 6 | end 7 | total+=sum; 8 | end 9 | print sum; 10 | print "\n"; 11 | print total; 12 | print "\n"; 13 | -------------------------------------------------------------------------------- /Chapter-01/sumints.stsh: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/stsh 2 | #-sumint:n 3 | #1 to: 100 do: [ :k | sum := 0. 1 to: n do: [ :i | sum:=sum+i. ]]. 4 | 1 to: 100 do: [ :k | sum := (n*n+n)/2. ]]. 5 | -------------------------------------------------------------------------------- /Chapter-01/sumints_c.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main( int argc , char *argv[] ) 5 | { 6 | int i,k,sum; 7 | int limit=argc > 1 ? atoi(argv[1]) : 1; 8 | limit *= 1000; 9 | for (k=0;k 2 | 3 | long long usermicros() 4 | { 5 | struct rusage usage; 6 | getrusage( RUSAGE_SELF, &usage ); 7 | return usage.ru_utime.tv_sec * 1000000 + usage.ru_utime.tv_usec; 8 | } 9 | 10 | int main( int argc , char *argv[] ) 11 | { 12 | int i,k; 13 | long long start = usermicros(); 14 | NSNumber* sum = nil; 15 | for (k=0;k<100000; k++ ) { 16 | sum =@(0); 17 | for (i=1;i<= 1000;i++ ) { 18 | sum =@([sum intValue]+i); 19 | } 20 | } 21 | NSLog(@"result: %@ user: %lld microseconds",sum,usermicros() - start); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /Chapter-01/sumints_objc.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | NSNumber *increment( NSNumber *value ) 4 | { 5 | return @([value intValue]+1); 6 | } 7 | 8 | int main( int argc , char *argv[] ) 9 | { 10 | int i,k; 11 | id pool=[NSAutoreleasePool new]; 12 | NSNumber* sum = nil; 13 | for (k=0;k<100000; k++ ) { 14 | sum =@(0); 15 | for (i=1;i<= 1000;i++ ) { 16 | sum =@([sum intValue]+i); 17 | sum =increment( sum ); 18 | } 19 | } 20 | NSLog(@"%@",sum); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /Chapter-01/sumintsc.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | 5 | @interface SumBench : NSObject 6 | { 7 | long long totalSum; 8 | long additional; 9 | } 10 | @end 11 | 12 | static long intermediate[256]; 13 | 14 | @implementation SumBench 15 | 16 | -(long)sumUpTo:(long)max 17 | { 18 | long sum=0; 19 | for (long i=1;i<=max;i++ ) { 20 | sum+=i; 21 | intermediate[i&3]=sum; 22 | } 23 | return sum; 24 | } 25 | 26 | 27 | @end 28 | 29 | int main( int argc , char *argv[] ) 30 | { 31 | long k; 32 | long i,sum,totalSum,max=10000,numIter=1000; 33 | SumBench *summer=[SumBench new]; 34 | 35 | if ( argc > 1 ) { 36 | numIter=atol(argv[1]) * 1000; 37 | } 38 | if ( argc > 2 ) { 39 | max=atol(argv[2]); 40 | } 41 | totalSum=0; 42 | for (k=0;k 2 | 3 | #define kCFTaggedObjectID_Integer ((3 << 1) + 1) 4 | #define kCFNumberSInt32Type 3 5 | #define kCFTaggedIntTypeOffset 6 6 | #define kCFTaggedOffset 2 7 | #define kCFTaggedIntValueOffset (kCFTaggedIntTypeOffset+kCFTaggedOffset) 8 | 9 | static inline int getInt( NSNumber *o ) { 10 | long long n=(long long)o; 11 | if ( n & 1 ) { 12 | return n >> kCFTaggedIntValueOffset; 13 | } else { 14 | return [o intValue]; 15 | } 16 | } 17 | 18 | 19 | static inline NSNumber *makeInt( int i ) { 20 | long long o=i; 21 | o=(o << kCFTaggedIntValueOffset) | (kCFTaggedObjectID_Integer | (kCFNumberSInt32Type< '%@'",sum,[sum class],[sum stringValue]); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /Chapter-04/xmlparse-max.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface MedParser:NSObject 4 | { 5 | NSMutableArray *abstracts; 6 | } 7 | 8 | @property (retain,nonatomic) NSMutableArray *abstracts; 9 | 10 | @end 11 | 12 | @implementation MedParser 13 | 14 | @synthesize abstracts; 15 | 16 | -defaultElement:elements attributes:attrs parser:parser 17 | { 18 | return nil; 19 | } 20 | 21 | -AbstractTextElement:elements attributes:attrs parser:parser 22 | { 23 | id text = [elements combinedText]; 24 | [abstracts addObject:text ? text : @""]; 25 | return nil; 26 | } 27 | 28 | @end 29 | 30 | static NSString *attrs[]={ 31 | 32 | @"CitedMedium", 33 | @"CompleteYN", 34 | @"DateType", 35 | @"EIdType", 36 | @"IssnType", 37 | @"Label", 38 | @"MajorTopicYN", 39 | @"Owner", 40 | @"PubModel", 41 | @"RefType", 42 | @"Source", 43 | @"Type", 44 | @"ValidYN", 45 | @"Version", 46 | @"version", 47 | nil 48 | }; 49 | 50 | static NSString *tags[]={ 51 | @"Abstract", 52 | @"AbstractText", 53 | @"Acronym", 54 | @"Affiliation", 55 | @"Agency", 56 | @"Article", 57 | @"ArticleTitle", 58 | @"Author", 59 | @"AuthorList", 60 | @"Chemical", 61 | @"ChemicalList", 62 | @"CitationSubset", 63 | @"CommentsCorrections", 64 | @"CommentsCorrectionsList", 65 | @"CopyrightInformation", 66 | @"Country", 67 | @"DateCompleted", 68 | @"DateCreated", 69 | @"DateRevised", 70 | @"Day", 71 | @"DescriptorName", 72 | @"ForeName", 73 | @"Grant", 74 | @"GrantID", 75 | @"GrantList", 76 | @"ISOAbbreviation", 77 | @"ISSN", 78 | @"ISSNLinking", 79 | @"Initials", 80 | @"Issue", 81 | @"Journal", 82 | @"JournalIssue", 83 | @"Language", 84 | @"LastName", 85 | @"MedlineCitation", 86 | @"MedlineJournalInfo", 87 | @"MedlinePgn", 88 | @"MedlineTA", 89 | @"MeshHeading", 90 | @"MeshHeadingList", 91 | @"Month", 92 | @"NameOfSubstance", 93 | @"NlmUniqueID", 94 | @"NumberOfReferences", 95 | @"PMID", 96 | @"Pagination", 97 | @"PubDate", 98 | @"PublicationType", 99 | @"PublicationTypeList", 100 | @"QualifierName", 101 | @"RefSource", 102 | @"RegistryNumber", 103 | @"Suffix", 104 | @"Title", 105 | @"Volume", 106 | @"Year", 107 | nil}; 108 | 109 | 110 | 111 | 112 | int main(int argc, char *argv[] ) { 113 | id data,parser,medparser; 114 | [NSAutoreleasePool new]; 115 | data = [NSData dataWithContentsOfMappedFile:[NSString stringWithUTF8String:argv[1]]]; 116 | parser = [MPWMAXParser parser]; 117 | medparser=[MedParser new]; 118 | [medparser setAbstracts:[NSMutableArray array]]; 119 | [parser setUndefinedTagAction:MAX_ACTION_NONE]; 120 | [parser setHandler:medparser forElements:[NSArray arrayWithObjects:tags count:56] inNamespace:nil prefix:@"" map:nil]; 121 | [parser declareAttributes:[NSArray arrayWithObjects:attrs count:13] inNamespace:nil]; 122 | [parser setAutotranslateUTF8:NO]; 123 | printf(" to start parsing:"); getchar(); 124 | for (int i=0;i<1;i++) { 125 | [parser parse:data]; 126 | } 127 | NSLog(@"%d abstracts",[[medparser abstracts] count]); 128 | 129 | return 0; 130 | } 131 | 132 | -------------------------------------------------------------------------------- /Chapter-04/xmlparse-max.stsh: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/stsh 2 | #-parse:file 3 | context loadFramework:'MPWXmlKit'. 4 | #data := file:iTunesMusic.xml rawData. 5 | data := NSData dataWithContentsOfMappedFile:file. 6 | parser := MPWMAXParser parser. 7 | parser setUndefinedTagAction:0. 8 | 9 | 1 to:1 do:[ :i | parser parse:data. ]. 10 | 11 | -------------------------------------------------------------------------------- /Chapter-04/xmlparse-mpwsax.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface MedParser:NSObject 5 | { 6 | NSMutableString *content; 7 | NSMutableDictionary *dict; 8 | NSMutableArray *abstracts; 9 | } 10 | 11 | @property (retain,nonatomic) NSMutableString *content; 12 | @property (retain,nonatomic) NSMutableDictionary *dict; 13 | @property (retain,nonatomic) NSMutableArray *abstracts; 14 | 15 | @end 16 | 17 | @implementation MedParser 18 | 19 | @synthesize content,dict,abstracts; 20 | 21 | - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 22 | { 23 | #if 0 24 | if ( [elementName isEqual:@"AbstractText"] ) { 25 | [self setContent:[NSMutableString string]]; 26 | } else { 27 | [self setContent:nil]; 28 | } 29 | #endif 30 | } 31 | 32 | 33 | 34 | - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 35 | { 36 | #if 0 37 | if ( [elementName isEqual:@"Abstract"] ) { 38 | } else if ( [elementName isEqual:@"AbstractText"] ) { 39 | [abstracts addObject:content]; 40 | [self setContent:nil]; 41 | } else if ( [elementName isEqual:@"Acronym"] ) { 42 | } else if ( [elementName isEqual:@"Affiliation"] ) { 43 | } else if ( [elementName isEqual:@"Agency"] ) { 44 | } else if ( [elementName isEqual:@"Article"] ) { 45 | } else if ( [elementName isEqual:@"ArticleTitle"] ) { 46 | } else if ( [elementName isEqual:@"Author"] ) { 47 | } else if ( [elementName isEqual:@"AuthorList"] ) { 48 | } else if ( [elementName isEqual:@"Chemical"] ) { 49 | } 50 | #endif 51 | } 52 | 53 | - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 54 | { 55 | #if 0 56 | [content appendString:string]; 57 | #endif 58 | } 59 | 60 | @end 61 | 62 | 63 | 64 | int main(int argc, char *argv[] ) { 65 | id data,parser,medparser; 66 | [NSAutoreleasePool new]; 67 | data = [NSData dataWithContentsOfMappedFile:[NSString stringWithUTF8String:argv[1]]]; 68 | for (int i=0;i<1; i++) { 69 | parser = [[MPWSAXParser alloc] initWithData:data]; 70 | // parser = [[NSXMLParser alloc] initWithData:data]; 71 | medparser=[MedParser new]; 72 | [medparser setDict:[NSMutableDictionary dictionary]]; 73 | [medparser setAbstracts:[NSMutableArray array]]; 74 | [parser setDelegate:medparser]; 75 | printf(" to start parsing:"); fflush(stdout); getchar(); 76 | // printf("starting to parse...\n"); 77 | [parser parse]; 78 | // printf("finished to release"); fflush(stdout); getchar(); 79 | // [parser release]; 80 | NSLog(@"%d abstracts",[[medparser abstracts] count]); 81 | } 82 | printf("finished to quit"); fflush(stdout); getchar(); 83 | return 0; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /Chapter-04/xmlparse-nssax.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface MedParser:NSObject 5 | { 6 | NSMutableString *content; 7 | NSMutableDictionary *dict; 8 | NSMutableArray *abstracts; 9 | } 10 | 11 | @property (retain,nonatomic) NSMutableString *content; 12 | @property (retain,nonatomic) NSMutableDictionary *dict; 13 | @property (retain,nonatomic) NSMutableArray *abstracts; 14 | 15 | @end 16 | 17 | @implementation MedParser 18 | 19 | @synthesize content,dict,abstracts; 20 | 21 | - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 22 | { 23 | if ( [elementName isEqual:@"AbstractText"] ) { 24 | [self setContent:[NSMutableString string]]; 25 | } else { 26 | [self setContent:nil]; 27 | } 28 | } 29 | 30 | 31 | 32 | - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 33 | { 34 | if ( [elementName isEqual:@"Abstract"] ) { 35 | } else if ( [elementName isEqual:@"AbstractText"] ) { 36 | [abstracts addObject:content]; 37 | [self setContent:nil]; 38 | } else if ( [elementName isEqual:@"Acronym"] ) { 39 | } else if ( [elementName isEqual:@"Affiliation"] ) { 40 | } else if ( [elementName isEqual:@"Agency"] ) { 41 | } else if ( [elementName isEqual:@"Article"] ) { 42 | } else if ( [elementName isEqual:@"ArticleTitle"] ) { 43 | } else if ( [elementName isEqual:@"Author"] ) { 44 | } else if ( [elementName isEqual:@"AuthorList"] ) { 45 | } else if ( [elementName isEqual:@"Chemical"] ) { 46 | } 47 | } 48 | 49 | - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 50 | { 51 | [content appendString:string]; 52 | } 53 | 54 | @end 55 | 56 | 57 | 58 | int main(int argc, char *argv[] ) { 59 | id data,parser,medparser; 60 | [NSAutoreleasePool new]; 61 | data = [NSData dataWithContentsOfMappedFile:[NSString stringWithUTF8String:argv[1]]]; 62 | for (int i=0;i<1; i++) { 63 | // parser = [[MPWXmlParser alloc] initWithData:data]; 64 | parser = [[NSXMLParser alloc] initWithData:data]; 65 | medparser=[MedParser new]; 66 | [medparser setDict:[NSMutableDictionary dictionary]]; 67 | [medparser setAbstracts:[NSMutableArray array]]; 68 | [parser setDelegate:medparser]; 69 | printf(" to start parsing:"); fflush(stdout); getchar(); 70 | // printf("starting to parse...\n"); 71 | [parser parse]; 72 | // printf("finished to release"); fflush(stdout); getchar(); 73 | // [parser release]; 74 | NSLog(@"%d abstracts",[[medparser abstracts] count]); 75 | } 76 | printf("finished to quit"); fflush(stdout); getchar(); 77 | return 0; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /Chapter-04/xmlparse-nsxmldocument.stsh: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/stsh 2 | #-parse:file 3 | #data := file:iTunesMusic.xml rawData. 4 | data := NSData dataWithContentsOfMappedFile:file. 5 | document := NSXMLDocument alloc initWithData:data options:0 error:nil. 6 | 7 | -------------------------------------------------------------------------------- /Chapter-05/malloc-size.m: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | #include 4 | 5 | 6 | NSTimeInterval mallocTest( long size ) 7 | { 8 | long actual=0; 9 | void *ptr=malloc( size ); 10 | actual=malloc_size(ptr); 11 | free(ptr); 12 | return actual; 13 | } 14 | 15 | int main() 16 | { int increment=1; 17 | int lastchange=0; 18 | for (long size=1; size<1024*1024; size+=increment ) { 19 | long actual =mallocTest( size ); 20 | if ( actual != lastchange ) { 21 | int diff = actual - lastchange; 22 | lastchange=actual; 23 | if ( diff > increment ) { 24 | increment=diff; 25 | printf("requested: %7ld actual: %7ld bucket size: %5d\n",size,actual,increment); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter-05/mallocbench.m: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | #import 4 | 5 | 6 | NSTimeInterval vm_allocTest( long size, long iterations ) 7 | { 8 | NSTimeInterval start=[NSDate timeIntervalSinceReferenceDate]; 9 | vm_map_t self_task = mach_task_self(); 10 | for (long i=0;i 2 | #include 3 | #include 4 | 5 | #define MBSIZE 16 6 | #define SIZE (MBSIZE * 1024 * 1024) 7 | 8 | #define UNROLL 4 9 | #define COUNT ( 1000 * 1000) 10 | 11 | int main(int argc, char *argv[] ) { 12 | if (argc > 2) { 13 | long stride=atol(argv[2]); 14 | char *ptr=malloc( SIZE + 20*stride ); 15 | memset( ptr, 55, SIZE + 10*stride ); 16 | char *cur=ptr; 17 | long curCount=atol(argv[1])* COUNT/UNROLL; 18 | long result=0; 19 | long headroom=UNROLL * stride; 20 | while ( curCount-- > 0 ) { 21 | result+=*cur; cur+=stride; 22 | result+=*cur; cur+=stride; 23 | result+=*cur; cur+=stride; 24 | result+=*cur; cur+=stride; 25 | if ( ((cur-ptr)+headroom) > SIZE ) { 26 | cur-=(SIZE-headroom); 27 | } 28 | } 29 | printf("result: %ld\n",result); 30 | } else { 31 | printf("usage: %s \n",argv[0]); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Chapter-05/memaccessbench-indexed.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #if 0 6 | #define MBSIZE 2UL 7 | #define KBSIZE (MBSIZE * 1024UL) 8 | #else 9 | #define KBSIZE 32UL 10 | #endif 11 | #define SIZE (KBSIZE * 1024UL) 12 | #define MASK (SIZE-1UL) 13 | 14 | //#define SIZE 8192 * 32 15 | 16 | // #define RANDOMSTRIDE (9) 17 | #define UNROLL 4 18 | 19 | #define COUNT ( 1000 * 1000) 20 | 21 | 22 | int main(int argc, char *argv[] ) { 23 | unsigned long stride=atol(argv[2]); 24 | char *ptr=malloc( SIZE + 20*stride ); 25 | memset( ptr, 55, SIZE + 10*stride ); 26 | long curCount=atol(argv[1])* COUNT/UNROLL; 27 | long result=0; 28 | long headroom=UNROLL * stride; 29 | unsigned long offset=0; 30 | while ( curCount-- > 0 ) { 31 | result+=ptr[offset&MASK]; offset+=stride; 32 | result+=ptr[offset&MASK]; offset+=stride; 33 | result+=ptr[offset&MASK]; offset+=stride; 34 | result+=ptr[offset&MASK]; offset+=stride; 35 | } 36 | printf("result: %ld\n",result); 37 | } 38 | -------------------------------------------------------------------------------- /Chapter-05/memaccessbench-word.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MBSIZE 4 6 | #define SIZE (MBSIZE * 1024 * 1024) 7 | 8 | //#define SIZE (256*1024) 9 | 10 | //#define SIZE 8192 * 32 11 | 12 | // #define RANDOMSTRIDE (9) 13 | #define UNROLL 4 14 | 15 | #define COUNT ( 1000 * 1000) 16 | 17 | int main(int argc, char *argv[] ) { 18 | long stride=atol(argv[2]); 19 | stride = stride > 4 ? stride/4: (stride==0 ? 0 :1); 20 | char *ptr=malloc( SIZE + 20*stride ); 21 | 22 | memset( ptr, 55, SIZE + 10*stride ); 23 | int *cur=(int*)ptr; 24 | long curCount=atol(argv[1])* COUNT/UNROLL; 25 | long long result=0; 26 | long headroom=UNROLL * stride; 27 | while ( curCount-- > 0 ) { 28 | result+=*cur; cur+=stride; 29 | result+=*cur; cur+=stride; 30 | result+=*cur; cur+=stride; 31 | result+=*cur; cur+=stride; 32 | if ( (((char*)cur-(char*)ptr)+headroom) > SIZE ) { 33 | cur-=((SIZE-headroom)/4); 34 | } 35 | } 36 | printf("result: %lld",result); 37 | } 38 | -------------------------------------------------------------------------------- /Chapter-05/memaccessbench.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #if 1 6 | #define MBSIZE 2048L 7 | #define SIZE (MBSIZE * 1024L * 1024L) 8 | #else 9 | #define SIZE (256*1024) 10 | #endif 11 | 12 | //#define SIZE 8192 * 32 13 | 14 | // #define RANDOMSTRIDE (9) 15 | #define UNROLL 4 16 | 17 | #define COUNT ( 1000 * 1000) 18 | 19 | int main(int argc, char *argv[] ) { 20 | long stride=atol(argv[2]); 21 | printf("total size: %ld\n",SIZE+20*stride); 22 | char *ptr=malloc( SIZE + 20L*stride ); 23 | memset( ptr, 55, SIZE + 10*stride ); 24 | char *cur=ptr; 25 | long curCount=atol(argv[1])* COUNT/UNROLL; 26 | long result=0; 27 | long headroom=UNROLL * stride; 28 | printf("stride: %ld count = %ld, headroom=%ld\n",stride,curCount,headroom); 29 | while ( curCount-- > 0 ) { 30 | result+=*cur; cur+=stride; 31 | #if 1 32 | result+=*cur; cur+=stride; 33 | result+=*cur; cur+=stride; 34 | result+=*cur; cur+=stride; 35 | #endif 36 | if ( ((cur-ptr)+headroom) > SIZE ) { 37 | cur-=(SIZE-headroom); 38 | } 39 | } 40 | printf("result: %ld\n",result); 41 | } 42 | -------------------------------------------------------------------------------- /Chapter-05/page-size.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int main() { 6 | return printf("page-size: %ld mask: %lx shift: %d\n",vm_kernel_page_size,vm_kernel_page_mask,vm_kernel_page_shift); 7 | } 8 | -------------------------------------------------------------------------------- /Chapter-06/leaks-cycles.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | func fn() 4 | { 5 | let a1=NSMutableArray() 6 | let a2=NSMutableArray() 7 | a1.addObject(a2) 8 | a2.addObject(a1) 9 | } 10 | 11 | autoreleasepool { 12 | fn() 13 | } 14 | sleep(20); 15 | -------------------------------------------------------------------------------- /Chapter-07/descriptionstream-case-analysis.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import 4 | 5 | @interface DescriptionStream : MPWStream {} @end @implementation DescriptionStream 6 | 7 | 8 | -(void)writeObject:anObject 9 | { 10 | if ( [anObject isKindOfClass:[NSArray class]] ) { 11 | BOOL first=YES; 12 | [target writeObject:@"( "]; 13 | for ( id content in anObject ) { 14 | if ( !first) { 15 | [target writeObject:@", "]; 16 | } else { 17 | first=NO; 18 | } 19 | [self writeObject:content]; 20 | } 21 | [target writeObject:@") "]; 22 | } else { 23 | [target writeObject:[anObject description]]; 24 | } 25 | } 26 | 27 | @end 28 | 29 | int main( int argc, char *argv[] ) { 30 | [NSAutoreleasePool new]; 31 | id s=[DescriptionStream streamWithTarget:[MPWByteStream Stdout]]; 32 | [s writeObject:@[ @[ @"a", @"d" ], @"b", @"c" ]]; 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /Chapter-07/descriptionstream-double-dispatch.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import 4 | 5 | @interface DescriptionStream : MPWStream {} @end @implementation DescriptionStream 6 | 7 | 8 | -(void)writeObject:anObject 9 | { 10 | [anObject describeOn:self]; 11 | } 12 | -(void)writeDescription:(NSString*)partialDescription 13 | { 14 | [target writeObject:partialDescription]; 15 | } 16 | 17 | @end 18 | 19 | @implementation NSArray(describe) 20 | 21 | -(void)describeOn:(DescriptionStream*)aStream 22 | { 23 | [aStream writeDescription:@"( "]; 24 | BOOL first=YES; 25 | for (id obj in self ) { 26 | if (first) { 27 | first=NO; 28 | } else { 29 | [aStream writeDescription:@", "]; 30 | } 31 | @autoreleasepool { 32 | [aStream writeObject:obj]; 33 | } 34 | } 35 | [aStream writeDescription:@")"]; 36 | } 37 | @end 38 | 39 | @implementation NSObject(describe) 40 | -(void)describeOn:aStream 41 | { 42 | [aStream writeDescription:[self description]]; 43 | } 44 | @end 45 | 46 | int main( int argc, char *argv[] ) { 47 | [NSAutoreleasePool new]; 48 | id s=[DescriptionStream streamWithTarget:[MPWByteStream Stdout]]; 49 | [s writeObject:@[ @[ @"a", @"d" ], @"b", @"c" ]]; 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /Chapter-07/nested-nsarrays-measure.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | var a=NSMutableArray() 4 | var b=NSMutableArray() 5 | a.add(b) 6 | b.add(a) 7 | print(a.description) 8 | 9 | -------------------------------------------------------------------------------- /Chapter-07/nested-nsarrays.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | let numArrays=Int(CommandLine.arguments[1])! 4 | let before=mstats(); 5 | var base:NSMutableArray=["Hello World"] 6 | for i in 1...numArrays { 7 | base=[base] 8 | } 9 | let b=base.description 10 | let after=mstats(); 11 | print("memory used: \( after.bytes_used - before.bytes_used)") 12 | 13 | -------------------------------------------------------------------------------- /Chapter-07/nsarray-description-infinite-stream.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface MPWDescriptionStream : NSObject 4 | { 5 | NSMapTable *alreadySeen; 6 | NSMutableString *target; 7 | } 8 | @property (nonatomic,retain) NSMapTable *alreadySeen; 9 | @property (nonatomic,retain) NSMutableString *target; 10 | -(void)writeObject:anObject; 11 | -(void)describeArray:anArray; 12 | -(void)describeObject:anObject; 13 | @end 14 | 15 | 16 | @implementation NSObject(describeOn) 17 | -(void)describeOn:aStream { [aStream describeObject:self]; } 18 | -(NSString*)fastDescription { 19 | MPWDescriptionStream *s=[[MPWDescriptionStream new] autorelease]; 20 | [s writeObject:self]; 21 | return [s target]; 22 | } 23 | @end 24 | @implementation MPWDescriptionStream 25 | 26 | @synthesize alreadySeen,target; 27 | 28 | -init 29 | { 30 | self=[super init]; 31 | [self setTarget:[NSMutableString string]]; 32 | [self setAlreadySeen:[NSMapTable mapTableWithKeyOptions:NSPointerFunctionsOpaquePersonality valueOptions:NSPointerFunctionsOpaquePersonality]]; 33 | return self; 34 | } 35 | 36 | -(void)writeObject:anObject 37 | { 38 | if ( [alreadySeen objectForKey:anObject] ) { 39 | [target appendFormat:@"",anObject]; 40 | } else { 41 | [alreadySeen setObject:anObject forKey:anObject]; 42 | [anObject describeOn:self]; 43 | [alreadySeen removeObjectForKey:anObject]; 44 | } 45 | } 46 | -(void)describeObject:anObject 47 | { 48 | [target appendString:[anObject description]]; 49 | } 50 | 51 | -(void)describeArray:(NSArray*)array 52 | { 53 | BOOL first=YES; 54 | [target appendString:@"( "]; 55 | for ( id obj in array ) { 56 | if (first) { 57 | first=NO; 58 | } else { 59 | [target appendString:@", "]; 60 | } 61 | [self writeObject:obj]; 62 | } 63 | [target appendString:@" )"]; 64 | } 65 | 66 | @end 67 | 68 | @implementation NSArray(describeOn) 69 | -(void)describeOn:aStream { [aStream describeArray:self]; } 70 | @end 71 | 72 | int main(int argc, char *argv[] ) { 73 | [NSAutoreleasePool new]; 74 | id a1=[NSMutableArray array]; 75 | id a2=[NSMutableArray array]; 76 | [a1 addObject:@"a string"]; 77 | [a1 addObject:a2]; 78 | [a2 addObject:a1]; 79 | [a2 addObject:@"another string"]; 80 | NSLog(@"a1: %@",[a1 fastDescription]); 81 | } 82 | -------------------------------------------------------------------------------- /Chapter-07/nsarray-description-infinite.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | int main(int argc, char *argv[] ) { 4 | [NSAutoreleasePool new]; 5 | id a1=[NSMutableArray array]; 6 | id a2=[NSMutableArray array]; 7 | [a1 addObject:a2]; 8 | [a2 addObject:a1]; 9 | NSLog(@"a1: %@",[a1 description); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter-07/nsarray-description-stream.m: -------------------------------------------------------------------------------- 1 | #import 2 | #include 3 | 4 | @interface StdoutTarget:NSObject 5 | { 6 | int length; 7 | } 8 | @end 9 | 10 | @implementation StdoutTarget 11 | 12 | -(void)appendString:(NSString*)aTarget 13 | { 14 | const int maxlen=8192; 15 | char buffer[ maxlen ]; 16 | NSUInteger used=0; 17 | NSRange r={0,[aTarget length] }; 18 | BOOL done=NO; 19 | do { 20 | NSRange leftover; 21 | [aTarget getBytes:buffer maxLength:maxlen usedLength:&used encoding:NSUTF8StringEncoding options:0 range:r remainingRange:&leftover]; 22 | if ( used > 0 ) { 23 | // write(1, buffer, used ); 24 | length+=used; 25 | r=leftover; 26 | } else { 27 | done=YES; 28 | } 29 | } while (!done); 30 | } 31 | -(int)length { return length; } 32 | @end 33 | 34 | 35 | @interface MPWDescriptionStream : NSObject 36 | { 37 | NSMapTable *alreadySeen; 38 | NSMutableString *target; 39 | } 40 | @property (nonatomic,retain) NSMapTable *alreadySeen; 41 | @property (nonatomic,retain) NSMutableString *target; 42 | -(void)writeObject:anObject; 43 | -(void)describeArray:anArray; 44 | -(void)describeObject:anObject; 45 | @end 46 | 47 | 48 | @implementation NSObject(describeOn) 49 | -(void)describeOn:aStream { [aStream describeObject:self]; } 50 | -(NSString*)fastDescription { 51 | MPWDescriptionStream *s=[[MPWDescriptionStream new] autorelease]; 52 | [s writeObject:self]; 53 | return [s target]; 54 | } 55 | @end 56 | @implementation MPWDescriptionStream 57 | 58 | @synthesize alreadySeen,target; 59 | 60 | -init 61 | { 62 | self=[super init]; 63 | [self setTarget:(id)[StdoutTarget new]]; 64 | // [self setAlreadySeen:[NSMapTable mapTableWithKeyOptions:NSPointerFunctionsOpaquePersonality valueOptions:NSPointerFunctionsOpaquePersonality]]; 65 | return self; 66 | } 67 | 68 | -(void)writeObject:anObject 69 | { 70 | if ( [alreadySeen objectForKey:anObject] ) { 71 | [target appendString:[NSString stringWithFormat:@"",anObject]]; 72 | } else { 73 | [alreadySeen setObject:anObject forKey:anObject]; 74 | [anObject describeOn:self]; 75 | [alreadySeen removeObjectForKey:anObject]; 76 | } 77 | } 78 | -(void)describeObject:anObject 79 | { 80 | [target appendString:[anObject description]]; 81 | } 82 | 83 | -(void)describeArray:(NSArray*)array 84 | { 85 | BOOL first=YES; 86 | [target appendString:@"( "]; 87 | for ( id obj in array ) { 88 | if (first) { 89 | first=NO; 90 | } else { 91 | [target appendString:@", "]; 92 | } 93 | [self writeObject:obj]; 94 | } 95 | [target appendString:@" )"]; 96 | } 97 | 98 | @end 99 | 100 | @implementation NSArray(describeOn) 101 | -(void)describeOn:aStream { [aStream describeArray:self]; } 102 | @end 103 | 104 | 105 | int main(int argc, char *argv[] ) 106 | { 107 | [NSAutoreleasePool new]; 108 | int count=argc>1 ? atoi(argv[1]) : 1000; 109 | id base=@"Hello World!"; 110 | int i; 111 | [[NSArray arrayWithObject:base] description]; 112 | for ( i=0;i 2 | #include 3 | 4 | @implementation NSArray(describe) 5 | 6 | -(void)describeOn:(NSMutableString*)description 7 | { 8 | [description appendString:@"( "]; 9 | BOOL first=YES; 10 | for (id obj in self ) { 11 | if (first) { 12 | first=NO; 13 | } else { 14 | [obj appendString:@", "]; 15 | } 16 | @autoreleasepool { 17 | [obj describeOn:description]; 18 | } 19 | } 20 | [description appendString:@")"]; 21 | } 22 | @end 23 | 24 | @implementation NSObject(describe) 25 | -(void)describeOn:(NSMutableString*)description 26 | { 27 | [description appendString:[self description]]; 28 | } 29 | -(NSString*)myDescription { 30 | NSMutableString *s=[NSMutableString string]; 31 | [self describeOn:s]; 32 | return s; 33 | } 34 | @end 35 | 36 | int main(int argc, char *argv[] ) 37 | { 38 | [NSAutoreleasePool new]; 39 | int count=argc>1 ? atoi(argv[1]) : 1000; 40 | id base=@"Hello World!"; 41 | int i; 42 | [[NSArray arrayWithObject:base] description]; 43 | for ( i=0;i 2 | #include 3 | 4 | int main(int argc, char *argv[] ) 5 | { 6 | [NSAutoreleasePool new]; 7 | int count=argc>1 ? atoi(argv[1]) : 1000; 8 | id base=@"Hello World!"; 9 | int i; 10 | [[NSArray arrayWithObject:base] description]; 11 | for ( i=0;i 2 | #include 3 | 4 | int main(int argc, char *argv[] ) 5 | { 6 | id pool=[NSAutoreleasePool new]; 7 | int count=argc>1 ? atoi(argv[1]) : 1000; 8 | NSLog(@"%d entries",count); 9 | id base=@"Hello World!"; 10 | int i; 11 | for ( i=0;i 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | int main(int argc, char *argv[]) { 9 | Class mpwint=[MPWInteger class]; 10 | int instance_size=class_getInstanceSize( mpwint ); 11 | id a=alloca( instance_size ); 12 | bzero(a, instance_size ); 13 | object_setClass(a, mpwint); 14 | [a setIntValue:43]; 15 | NSLog(@"a=%@",a); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /Chapter-08/upcase.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAXLENGTH 8192 5 | 6 | int main(int argc, char *argv[] ) { 7 | char buf[MAXLENGTH]; 8 | while (fgets(buf,MAXLENGTH,stdin)) { 9 | buf[0]=toupper(buf[0]); 10 | fputs(buf,stdout); 11 | } 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter-10/upcase-single-char-buffered.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int main(int argc, char *argv[] ) { 6 | int first=1; 7 | int ch; 8 | while ( (ch=getchar()) != EOF ) { 9 | if ( first ) { 10 | ch=toupper(ch); 11 | first=0; 12 | } 13 | putchar(ch); 14 | if ( ch=='\n' ) { 15 | first=1; 16 | } 17 | } 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /Chapter-10/upcase-single-char.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int main(int argc, char *argv[] ) { 6 | int first=1; 7 | int eof=0; 8 | do { 9 | char buffer; 10 | if ( read(0,&buffer,1)==1) { 11 | if ( first ) { 12 | buffer=toupper(buffer); 13 | first=0; 14 | } 15 | write(1,&buffer,1); 16 | if ( buffer=='\n' ) { 17 | first=1; 18 | } 19 | } else { 20 | eof=1; 21 | } 22 | } while (!eof); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /Chapter-11/datamap-multiple.m: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | int main(int argc, char *argv[] ) { 5 | [NSAutoreleasePool new]; 6 | int options=0; 7 | printf("start\n"); 8 | if ( argv[2] ) { 9 | options=(atoi(argv[2])==1) ? NSDataReadingMappedAlways : atoi(argv[2])==2 ? NSDataReadingUncached : 0; 10 | } 11 | NSString *basePath = [NSString stringWithUTF8String:argv[1]]; 12 | NSFileManager *fm=[NSFileManager defaultManager]; 13 | NSArray *files=[fm contentsOfDirectoryAtPath:basePath error:nil]; 14 | unsigned char result=0; 15 | NSLog(@"%ld files option: %d",[files count],options); 16 | for ( NSString *file in files ) { 17 | @autoreleasepool { 18 | NSString *relpath=[basePath stringByAppendingPathComponent: file]; 19 | NSURL *url=[NSURL fileURLWithPath:relpath isDirectory:NO]; 20 | NSData *data=[NSData dataWithContentsOfURL:url options:options error:nil]; 21 | unsigned stride=4096; 22 | const char *bytes,*cur,*end; 23 | for (bytes=[data bytes],end=bytes+[data length],cur=bytes; cur < end-stride; cur+=stride ) { 24 | result ^= *cur; 25 | } 26 | } 27 | } 28 | NSLog(@"result: %x",result); 29 | } 30 | -------------------------------------------------------------------------------- /Chapter-11/datamapping-complex.m: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | const char *readFileNSData( char *filename, int shouldMap, int uncached, long *size, int stride ) { 5 | NSData *data; 6 | NSURL *url=[NSURL fileURLWithPath:[NSString stringWithUTF8String:filename]]; 7 | int mapping = shouldMap ? NSDataReadingMappedAlways : uncached ? NSDataReadingUncached : 0 ; 8 | // NSLog(@"file: %@, mapped: %d uncached: %d options:%d",url,shouldMap,uncached,mapping); 9 | data=[NSData dataWithContentsOfURL:url options:mapping error:nil]; 10 | if ( shouldMap && stride <= 4096 ) { 11 | madvise( (void*)[data bytes], [data length], MADV_SEQUENTIAL | MADV_WILLNEED ); 12 | } 13 | if ( size ) { 14 | *size=[data length]; 15 | } 16 | return [data bytes]; 17 | } 18 | 19 | const char *readFileUnix( char *filename, int shouldMap, int uncached, long *size ) { 20 | int fd=open( filename, O_RDONLY); 21 | off_t length=lseek(fd,0 , SEEK_END); 22 | char *result=NULL; 23 | NSLog(@"got fd: %d length: %lld",fd,length); 24 | if ( size ) { *size=length; } 25 | if ( shouldMap ) { 26 | // MAP_PRIVATE, MAP_NOCACHE 27 | result=mmap( NULL, length, PROT_READ , MAP_SHARED , fd, 0 ); 28 | #if 1 29 | madvise( (void*)result, length, MADV_SEQUENTIAL | MADV_WILLNEED ); 30 | #endif 31 | } else { 32 | lseek(fd,0 , SEEK_SET); 33 | result=malloc( length ); 34 | NSLog(@"got result buf: %p",result); 35 | long long int numRead=read( fd, result, length ); 36 | NSLog(@"read %lld bytes",numRead); 37 | if ( numRead <0 ) { 38 | perror("couldn't read"); 39 | } 40 | } 41 | close(fd); 42 | return result; 43 | } 44 | 45 | 46 | int main(int argc, char *argv[] ) { 47 | [NSAutoreleasePool new]; 48 | char *filename=argv[1]; 49 | BOOL shouldMap=argv[2] && atoi(argv[2])==1; 50 | BOOL uncached=argv[2] && atoi(argv[2])==2; 51 | int pageStride=argv[3] ? atoi(argv[3]) : 1; 52 | int stride = pageStride * 4096 + 1; 53 | char result=0; 54 | long length=0; 55 | const char *bytes=readFileNSData( filename, shouldMap, uncached, &length, stride ); 56 | // const char *bytes=readFileUnix( filename, shouldMap, uncached, &length ); 57 | const char *end=bytes+length; 58 | const char *cur=bytes; 59 | // NSLog(@"length: %ld stride=%d",length,stride); 60 | while ( cur >= bytes && cur < end ) { 61 | result ^= *cur; 62 | cur+=stride; 63 | } 64 | NSLog(@"result: %x",result); 65 | } 66 | -------------------------------------------------------------------------------- /Chapter-11/datamapping-simple.m: -------------------------------------------------------------------------------- 1 | #import 2 | int main(int argc, char *argv[] ) { 3 | NSURL *url=[NSURL fileURLWithPath:@(argv[1])]; 4 | NSData *d=[NSData dataWithContentsOfURL:url options:0 error:nil]; 5 | char result=0; 6 | const char *bytes=[d bytes]; 7 | const char *end=bytes+[d length]; 8 | for (const char *cur=bytes; cur < end; cur++ ) { 9 | result ^= *cur; 10 | } 11 | printf("result: \%x\n",result); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter-11/datamapping.m: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | int main(int argc, char *argv[] ) { 5 | const unsigned char *bytes,*end,*cur; 6 | int pageStride=argv[3] ? atoi(argv[3]) : 0; 7 | int pageOffset=argv[4] ? atoi(argv[4]) : 0; 8 | int stride = pageStride * 4096 + pageOffset; 9 | printf("pageStride: %d pageOffset: %d -> stride: %d\n",pageStride,pageOffset,stride); 10 | int options = 0; 11 | [NSAutoreleasePool new]; 12 | printf("start\n"); 13 | if ( argv[2] ) { 14 | options=(atoi(argv[2])==1) ? NSDataReadingMappedAlways : atoi(argv[2])==2 ? NSDataReadingUncached : 0; 15 | } 16 | NSURL *url=[NSURL fileURLWithPath:[NSString stringWithUTF8String:argv[1]] isDirectory:NO]; 17 | NSData *data=[NSData dataWithContentsOfURL:url options:options error:nil]; 18 | if ( 0 && options == NSDataReadingMappedAlways ) { 19 | madvise( [data bytes],[data length], MADV_SEQUENTIAL | MADV_WILLNEED ); 20 | printf("madvise\n"); 21 | } 22 | unsigned char result=0; 23 | for (bytes=[data bytes],end=bytes+[data length],cur=bytes; cur < end-stride; cur+=stride ) { 24 | result ^= *cur; 25 | } 26 | printf("stride: %d result: %x\n",stride,result); 27 | [data writeToFile:@"out" atomically:NO]; 28 | } 29 | -------------------------------------------------------------------------------- /Chapter-12/archiving-hierarchical.m: -------------------------------------------------------------------------------- 1 | #import 2 | #include 3 | #import 4 | #import 5 | #import 6 | #import 7 | #import 8 | #import 9 | #import 10 | #import 11 | #include 12 | 13 | 14 | #define UNARCHIVE 0 15 | #define XMLARCHIVE 0 16 | #define XMLARCHIVE_DIRECT 0 17 | #define PLISTONLY 0 18 | #define MPWBPLIST 0 19 | #define MPWBPLIST_VIAPLIST 0 20 | #define PLISTBINARY 0 21 | #define BPLISTCF 0 22 | #define PLISTXML 0 23 | #define PLISTSTREAM 0 24 | #define KEYED 0 25 | #define OLDSTYLE 0 26 | #define JSON 0 27 | #define SUMB 1 28 | 29 | 30 | #define SAVEARCHIVE 0 31 | 32 | @interface NSArray(asPlist) 33 | 34 | -(id)asPlist; 35 | @end 36 | 37 | 38 | @interface SampleObject:NSObject 39 | { 40 | int retainCount; 41 | int a; 42 | float b; 43 | NSString *name; 44 | NSArray *children; 45 | } 46 | 47 | 48 | @end 49 | 50 | 51 | @implementation NSOutputStream(appendBytes) 52 | 53 | -(void)appendBytes:(void*)bytes length:(unsigned)len 54 | { 55 | [self write:bytes maxLength:len]; 56 | } 57 | 58 | @end 59 | 60 | 61 | @implementation SampleObject 62 | 63 | 64 | -(NSUInteger)count 65 | { 66 | int count=2; 67 | for ( SampleObject *s in children ) { 68 | count+=[s count]; 69 | } 70 | return count; 71 | } 72 | 73 | -processCArrayFromPlist:someC { 74 | NSMutableArray *r=[NSMutableArray arrayWithCapacity:[someC count]]; 75 | for ( NSDictionary *d in someC ){ 76 | [r addObject:[[[[self class] alloc] initWithPlist:d] autorelease]]; 77 | } 78 | return r; 79 | } 80 | 81 | -initWithBinaryPlist:(MPWBinaryPlist*)aPlist 82 | { 83 | self=[super init]; 84 | #if 0 85 | [aPlist parseDictUsingBlock:^(MPWBinaryPlist *plist, long keyIndex,long valueIndex, long anIndex) { 86 | #if 0 87 | NSString *key=[plist objectAtIndex:keyIndex]; 88 | if ( [key isEqual:@"a"] ) { 89 | a=[plist currentInt]; 90 | } else if ( [key isEqual:@"b"] ) { 91 | 92 | } else if ( [key isEqual:@"name"] ) { 93 | c=[[aPlist currentObject] retain]; 94 | } else if ( [key isEqual:@"children"] ) { 95 | NSMutableArray *array=[NSMutableArray array]; 96 | [plist parseArrayUsingBlock:^(MPWBinaryPlist *plist, long arrayIndex, long anIndex) { 97 | [array addObject:[[[[self class] alloc] initWithBinaryPlist:plist] autorelease]]; 98 | }]; 99 | children=[array retain]; 100 | } 101 | #else 102 | switch ( anIndex ) { 103 | case 0: 104 | 105 | a=[plist currentInt]; 106 | break; 107 | case 1: 108 | b=[plist readFloat]; 109 | break; 110 | case 2: 111 | c=[[aPlist currentObject] retain]; 112 | break; 113 | case 3: 114 | NSMutableArray *array=[NSMutableArray array]; 115 | [plist parseArrayUsingBlock:^(MPWBinaryPlist *plist, long arrayIndex, long anIndex) { 116 | [array addObject:[[[[self class] alloc] initWithBinaryPlist:plist] autorelease]]; 117 | }]; 118 | c=[array retain]; 119 | break; 120 | 121 | } 122 | #endif 123 | } ]; 124 | #else 125 | // NSLog(@"parseUsingContentBlock"); 126 | [aPlist parseDictUsingContentBlock:^(MPWBinaryPlist *plist, long keyIndex,long valueIndex, long anIndex) { 127 | a=[plist readIntegerForKey:@"a"]; 128 | b=[plist readRealForKey:@"b"]; 129 | name=[plist readObjectForKey:@"name"]; 130 | NSMutableArray *array=[NSMutableArray array]; 131 | [plist parseArrayAtKey:@"children" usingBlock:^(MPWBinaryPlist *plist, long arrayIndex, long anIndex) { 132 | [array addObject:[[[[self class] alloc] initWithBinaryPlist:plist] autorelease]]; 133 | }]; 134 | children=[array retain]; 135 | } ]; 136 | #endif 137 | 138 | return self; 139 | } 140 | 141 | -initWithBinaryPlistData:(NSData*)aPlist 142 | { 143 | MPWBinaryPlist *pl=[MPWBinaryPlist bplistWithData:aPlist]; 144 | return [self initWithBinaryPlist:pl]; 145 | } 146 | 147 | #if !__has_feature(objc_arc) 148 | 149 | -(id)retain 150 | { 151 | // __sync_fetch_and_add(&retainCount,1); 152 | OSAtomicIncrement32(&retainCount); 153 | // retainCount++; 154 | return self; 155 | } 156 | 157 | -(oneway void)release 158 | { 159 | // __sync_fetch_and_add(&retainCount,-1); 160 | OSAtomicDecrement32(&retainCount); 161 | // retainCount--; 162 | if ( retainCount < 0 ) { 163 | [self dealloc]; 164 | } 165 | } 166 | 167 | -(void)dealloc 168 | { 169 | [name release]; 170 | [children release]; 171 | [super dealloc]; 172 | } 173 | 174 | #endif 175 | 176 | -(float)b { return b; } 177 | 178 | -(double)sumB 179 | { 180 | double result=0; 181 | for (int i=0;i<10;i++) { 182 | result+=[self b]; 183 | } 184 | for ( SampleObject *s in children ) { 185 | result+=[s sumB]; 186 | } 187 | return result; 188 | } 189 | 190 | 191 | static NSString* uniqueString( NSString *aString ) 192 | { 193 | static NSMutableSet *strings=nil; 194 | if ( ! strings ) { 195 | strings=[NSMutableSet new]; 196 | } 197 | id result=[strings member:aString]; 198 | if ( !result ) { 199 | if ( [strings count] > 20 ) { 200 | [strings removeObject:[strings anyObject]]; 201 | } 202 | [strings addObject:aString]; 203 | result=aString; 204 | } 205 | return result; 206 | } 207 | 208 | 209 | +parseFromXML:(NSData*)xmlData 210 | { 211 | static MPWMAXParser *parser=nil; 212 | if (!parser ) { 213 | ASSIGN_ID(parser, [MPWMAXParser parser]); 214 | [parser setHandler:self forElements:[NSArray arrayWithObject:@"S"] 215 | inNamespace:nil prefix:@"" map:nil]; 216 | [parser declareAttributes:@[ @"a", @"b" ] inNamespace:nil]; 217 | [parser handleElement:@"S" withBlock:^(id elements,id attributes ,id parser){ 218 | id children; 219 | if ( [elements count] == 1 ) { 220 | children=uniqueString( [elements lastObject] ); 221 | // children=@"Hello World!"; 222 | } else { 223 | children=[elements allValues]; 224 | } 225 | return [[self alloc] initWithA:[[attributes objectForUniqueKey:@"a"] intValue] 226 | b:[[attributes objectForUniqueKey:@"b"] floatValue] 227 | name:[[attributes objectForUniqueKey:@"name"] stringValue] 228 | children:children]; 229 | }]; 230 | } 231 | id obj=[parser parsedData:xmlData]; 232 | return obj; 233 | } 234 | 235 | -initWithA:(int)newA b:(float)newB name:(id)newC children:(id)newChildren 236 | { 237 | self=[super init]; 238 | if ( self ) { 239 | a=newA; 240 | b=newB; 241 | name=RETAIN(newC); 242 | children=RETAIN(newChildren); 243 | } 244 | return self; 245 | } 246 | 247 | CONVENIENCE( sampleWithA:(int)newA b:(float)newB name:(id)newC children:(id)newChildren, initWithA:newA b:newB name:newC children:newChildren ) 248 | 249 | -(void)generateXMLOn:(MPWXmlGeneratorStream*)stream 250 | { 251 | [stream writeElementName:"S" 252 | attributeBlock:^(MPWXmlGeneratorStream *s){ 253 | [s writeCStrAttribute:"a" intValue:a]; 254 | [s writeCStrAttribute:"b" doubleValue:b]; 255 | [s writeCStrAttribute:"name" value:name]; 256 | } contentBlock:^(MPWXmlGeneratorStream *s){ 257 | for ( SampleObject *o in children ) { 258 | [o generateXMLOn:s]; 259 | } 260 | }]; 261 | } 262 | 263 | -(void)writeOnPropertyList:aWriter 264 | { 265 | [aWriter writeDictionaryLikeObject:self withContentBlock:^(id writer,id anObject){ 266 | [writer writeInt:a forKey:@"a"]; 267 | [writer writeFloat:b forKey:@"b"]; 268 | [writer writeObject:name forKey:@"name"]; 269 | [writer writeObject:children forKey:@"children"]; 270 | }]; 271 | } 272 | 273 | -asXML 274 | { 275 | // MPWXmlGeneratorStream *s=[MPWXmlGeneratorStream streamWithTarget:[MPWByteStream streamWithTarget:[NSMutableData dataWithCapacity:46 * 1024 * 1024]]]; 276 | // NSOutputStream *stream=[NSOutputStream outputStreamToFileAtPath:@"archive.xmlstream" append:NO]; 277 | // [stream open]; 278 | MPWXmlGeneratorStream *s=[MPWXmlGeneratorStream streamWithTarget:[MPWByteStream streamWithTarget:[NSMutableData dataWithCapacity:50 ]]]; 279 | // MPWXmlGeneratorStream *s=[MPWXmlGeneratorStream streamWithTarget:[MPWByteStream streamWithTarget:stream]]; 280 | // MPWXmlGeneratorStream *s=[MPWXmlGeneratorStream streamWithTarget:[MPWByteStream fileName:@"archive-direct.rawxml"]]; 281 | [self generateXMLOn:s]; 282 | [s close]; 283 | // [stream close]; 284 | return [[s target] target]; 285 | // return nil; 286 | } 287 | 288 | -initWithPlist:(NSDictionary*)aPlist 289 | { 290 | return [self initWithA:[[aPlist objectForKey:@"a"] intValue] b:[[aPlist objectForKey:@"b"] floatValue] 291 | name:[aPlist objectForKey:@"name"] children:[self processCArrayFromPlist:[aPlist objectForKey:@"children"]]]; 292 | } 293 | 294 | 295 | -asPlist 296 | { 297 | #if 1 298 | static id keyset=nil; 299 | #if 1 300 | if ( !keyset ) { 301 | keyset=[[NSDictionary sharedKeySetForKeys:@[@"a",@"b",@"name", @"children"]] retain]; 302 | } 303 | NSMutableDictionary *dict=[NSMutableDictionary dictionaryWithSharedKeySet:keyset]; 304 | #else 305 | NSMutableDictionary *dict=[NSMutableDictionary dictionary]; 306 | #endif 307 | [dict setObject:[NSNumber numberWithInt:a] forKey:@"a"]; 308 | [dict setObject:[NSNumber numberWithFloat:b] forKey:@"b"]; 309 | [dict setObject:name forKey:@"name"]; 310 | [dict setObject:[children asPlist] forKey:@"children"]; 311 | return dict; 312 | #else 313 | return @{ @"a": @(a), @"b": @(b), @"name": name, @"children": [children asPlist], }; 314 | return [NSDictionary dictionaryWithObjectsAndKeys: 315 | @(a),@"a", 316 | @(b),@"b", 317 | name,@"name",nil, 318 | [children asPlist],@"children",nil]; 319 | 320 | #endif 321 | } 322 | 323 | -(void)encodeWithCoder:(NSCoder*)aCoder 324 | { 325 | #if 1 326 | encodeVar( aCoder, a ); 327 | encodeVar( aCoder, b ); 328 | encodeVar( aCoder, name ); 329 | encodeVar( aCoder, children ); 330 | #else 331 | [aCoder encodeInt:a forKey:@"a"]; 332 | [aCoder encodeFloat:b forKey:@"b"]; 333 | [aCoder encodeObject:name forKey:@"name"]; 334 | [aCoder encodeObject:children forKey:@"children"]; 335 | #endif 336 | } 337 | 338 | 339 | - (id)initWithCoder:(NSKeyedUnarchiver *)aCoder { 340 | self = [super init]; 341 | if (self) { 342 | #if 1 343 | decodeVar( aCoder, a ); 344 | decodeVar( aCoder, b ); 345 | decodeVar( aCoder, name ); 346 | decodeVar( aCoder, children ); 347 | #else 348 | a=[aCoder decodeIntForKey:@"a"]; 349 | b=[aCoder decodeFloatForKey:@"b"]; 350 | name=[[aCoder decodeObjectForKey:@"name"] retain]; 351 | children=[[aCoder decodeObjectForKey:@"children"] retain]; 352 | #endif 353 | } 354 | return self; 355 | } 356 | 357 | -description { return [NSString stringWithFormat:@"<%@:%p: a=%d b=%g name=%@ children=%@>",[self class],self,a,b,name,children]; } 358 | 359 | @end 360 | 361 | 362 | int main(int argc, char *argv[] ) { 363 | NSData *archive=nil; 364 | @autoreleasepool { 365 | [NSUserDefaults standardUserDefaults]; 366 | NSMutableArray *objs=[NSMutableArray array]; 367 | int count=argc>1 ? atoi(argv[1]) : 31; 368 | int i; 369 | NSString *s=@"hello world!"; 370 | 371 | for ( i=0;i 2 | #include 3 | #import 4 | #import 5 | #import 6 | 7 | @interface SampleObject:NSObject 8 | { 9 | int a; 10 | float b; 11 | id c; 12 | } 13 | 14 | @end 15 | @implementation SampleObject 16 | 17 | -initWithA:(int)newA b:(float)newB c:(id)newC 18 | { 19 | self=[super init]; 20 | if ( self ) { 21 | a=newA; 22 | b=newB; 23 | c=[newC retain]; 24 | } 25 | return self; 26 | } 27 | 28 | -asPlist 29 | { 30 | NSMutableDictionary *dict=[NSMutableDictionary dictionary]; 31 | [dict setObject:[NSNumber numberWithInt:a] forKey:@"a"]; 32 | [dict setObject:[NSNumber numberWithFloat:b] forKey:@"b"]; 33 | [dict setObject:c forKey:@"c"]; 34 | return dict; 35 | } 36 | 37 | -(void)encodeWithCoder:(NSCoder*)aCoder 38 | { 39 | encodeVar( aCoder, a ); 40 | encodeVar( aCoder, b ); 41 | encodeVar( aCoder, c ); 42 | } 43 | 44 | 45 | - (id)initWithCoder:(NSCoder *)aCoder { 46 | self = [super init]; 47 | if (self) { 48 | decodeVar( aCoder, a ); 49 | decodeVar( aCoder, b ); 50 | decodeVar( aCoder, c ); 51 | } 52 | return self; 53 | } 54 | 55 | -(void)dealloc 56 | { 57 | [c release]; 58 | [super dealloc]; 59 | } 60 | @end 61 | 62 | //#define KEYED 1 63 | 64 | NSArray *toPlist( NSArray *sampleObjects ) { 65 | NSMutableArray *p=[NSMutableArray arrayWithCapacity:[sampleObjects count]]; 66 | for ( SampleObject *s in sampleObjects ) { 67 | [p addObject:[s asPlist]]; 68 | } 69 | return p; 70 | } 71 | 72 | int main(int argc, char *argv[] ) { 73 | [NSAutoreleasePool new]; 74 | NSMutableArray *objs=[NSMutableArray array]; 75 | int count=argc>1 ? atoi(argv[1]) : 1000; 76 | id base=@"Hello World!"; 77 | int i; 78 | int size=class_getInstanceSize ([SampleObject class])+16; // size of NSString 79 | 80 | for ( i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void purgeFile( char *filename ) { 8 | int fd=open( filename, O_RDONLY); 9 | struct stat st; 10 | fstat( fd, &st ); 11 | off_t length=st.st_size; 12 | // MAP_PRIVATE, MAP_NOCACHE 13 | const char *result=mmap( NULL, length, PROT_READ , MAP_SHARED , fd, 0 ); 14 | madvise( (void*)result, length, MADV_FREE ); 15 | close(fd); 16 | } 17 | 18 | 19 | int main(int argc, char *argv[] ) { 20 | char *filename=argv[1]; 21 | purgeFile( filename ); 22 | } 23 | -------------------------------------------------------------------------------- /Chapter-12/unixread-full.m: -------------------------------------------------------------------------------- 1 | #import 2 | #include 3 | 4 | int main( int argc, char *argv[] ) { 5 | char *filename=argv[1]; 6 | int fd=open( filename, O_RDONLY ); 7 | struct stat statbuf; 8 | fstat(fd, &statbuf); 9 | char *buffer=malloc( statbuf.st_size ); 10 | read( fd, buffer, statbuf.st_size ); 11 | // while ( size ) { 12 | // size=read(fd,buffer,size); 13 | // } 14 | close(fd); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter-12/unixread.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main( int argc, char *argv[] ) { 6 | char *filename=argv[1]; 7 | int kbsize = argv[2]? atoi(argv[2]) : 8; 8 | size_t size=kbsize*1024; 9 | char *buffer=malloc(size); 10 | int fd=open( filename, O_RDONLY ); 11 | while ( size ) { 12 | size=read(fd,buffer,size); 13 | } 14 | close(fd); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/Classes/AccessorMacros.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2001-2012 by Marcel Weiher. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in 13 | the documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name Marcel Weiher nor the names of contributors may 16 | be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef ACCESSOR_MACROS 34 | #define ACCESSOR_MACROS 35 | 36 | 37 | 38 | //--- This file expands the accessor macros 39 | 40 | #define newBool(x) (x ? [[NSNumber numberWithBool:x] retain] : nil) 41 | #define newInt(x) [[NSNumber numberWithInt:x] retain] 42 | #define newChar(x) [[NSNumber numberWithChar:x] retain] 43 | #define makeBool(x) (x ? [NSNumber numberWithBool:x] : nil) 44 | #define makeInt(x) [NSNumber numberWithInt:x] 45 | #define makeChar(x) [NSNumber numberWithChar:x] 46 | #define toInt(x) [x intValue] 47 | #define toBool(x) [x boolValue] 48 | //#define toString(x) [x stringValue] 49 | 50 | #if !__has_feature(objc_arc) 51 | #define ASSIGN_ID(var,value)\ 52 | {\ 53 | id tempValue=(value);\ 54 | if ( tempValue!=var) { \ 55 | if ( tempValue!=(id)self ) \ 56 | [tempValue retain]; \ 57 | if ( var && var!=(id)self) \ 58 | [var release]; \ 59 | var = tempValue; \ 60 | } \ 61 | } 62 | #else 63 | #define ASSIGN_ID(var,value) var=value 64 | #endif 65 | 66 | #ifndef AUTORELEASE 67 | #if !__has_feature(objc_arc) 68 | #define AUTORELEASE(x) ([(x) autorelease]) 69 | #else 70 | #define AUTORELEASE(x) (x) 71 | #endif 72 | #endif 73 | 74 | 75 | #define setAccessor( type, var,setVar ) \ 76 | -(void)setVar:(type)newVar { \ 77 | ASSIGN_ID(var,newVar)\ 78 | } \ 79 | 80 | #define readAccessorName( type, var , name )\ 81 | -(type)name { return var; } 82 | 83 | #define readAccessor( type, var ) readAccessorName( type, var, var ) 84 | 85 | #define relayReadAccessor( var, delegate ) \ 86 | -var\ 87 | {\ 88 | if ( var ) {\ 89 | return var;\ 90 | } else {\ 91 | return [delegate var];\ 92 | }\ 93 | }\ 94 | 95 | #define objectAccessor( objectType, var, setVar ) \ 96 | readAccessor( objectType*, var )\ 97 | setAccessor( objectType*, var,setVar ) 98 | 99 | #define idAccessor( var, setVar )\ 100 | readAccessor( id, var )\ 101 | setAccessor( id, var,setVar ) 102 | 103 | 104 | #define relayAccessor( var, setVar, delegate )\ 105 | relayReadAccessor( var , delegate )\ 106 | setAccessor( id, var, setVar ) 107 | 108 | #define idAccessor_h( var,setVar ) -(void)setVar:newVar; \ 109 | -var; 110 | 111 | #define scalarAccessor( scalarType, var, setVar ) \ 112 | -(void)setVar:(scalarType)newVar { var=newVar; } \ 113 | -(scalarType)var { return var; } 114 | #define scalarAccessor_h( scalarType, var, setVar ) \ 115 | -(void)setVar:(scalarType)newVar; \ 116 | -(scalarType)var; 117 | 118 | #define objectAccessor_h( objectType, var, setVar ) scalarAccessor_h( objectType*, var, setVar ) 119 | 120 | #define intAccessor( var, setVar ) scalarAccessor( int, var, setVar ) 121 | #define intAccessor_h( var, setVar ) scalarAccessor_h( int, var, setVar ) 122 | #define floatAccessor(var,setVar ) scalarAccessor( float, var, setVar ) 123 | #define floatAccessor_h(var,setVar ) scalarAccessor_h( float, var, setVar ) 124 | #define boolAccessor(var,setVar ) scalarAccessor( BOOL, var, setVar ) 125 | #define boolAccessor_h(var,setVar ) scalarAccessor_h( BOOL, var, setVar ) 126 | 127 | #define lazyAccessor( ltype, lvar ,setLVar, computeVar ) \ 128 | readAccessorName( ltype*, lvar, _##lvar ) \ 129 | setAccessor( ltype*, lvar, setLVar ) \ 130 | \ 131 | -(ltype*)lvar { \ 132 | if ( ![self _##lvar] ) { \ 133 | [self setLVar:[self computeVar]]; \ 134 | } \ 135 | return [self _##lvar]; \ 136 | } \ 137 | 138 | #define slazyAccessor( ltype, lvar ,setLVar, computeVar ) \ 139 | readAccessorName( ltype*, lvar, _##lvar ) \ 140 | setAccessor( ltype*, lvar, setLVar ) \ 141 | \ 142 | -(ltype*)lvar { \ 143 | @synchronized( self ) { \ 144 | if ( ![self _##lvar] ) { \ 145 | [self setLVar:[self computeVar]]; \ 146 | } \ 147 | } \ 148 | return [self _##lvar]; \ 149 | } \ 150 | 151 | 152 | 153 | #define dictAccessor( objectType, var, setVar, someDict ) \ 154 | -(objectType*)var { return [someDict objectForKey:@""#var]; } \ 155 | -(void)setVar:(objectType*)newValue { [someDict setObject:newValue forKey:@""#var]; } \ 156 | 157 | #define scalarDictAccessor( scalarType, var, setVar, someDict ) \ 158 | -(scalarType)var { scalarType temp=0; [[someDict objectForKey:@""#var] getValue:&temp]; return temp; }\ 159 | -(void)setVar:(scalarType)newValue { NSValue *temp=[NSValue valueWithBytes:&newValue objCType:@encode(scalarType)]; [someDict setObject:temp forKey:@""#var]; } \ 160 | 161 | #ifndef CONVENIENCE 162 | #define CONVENIENCE( sel, initsel ) \ 163 | +(instancetype)sel { \ 164 | return AUTORELEASE([[self alloc] initsel]); \ 165 | } 166 | 167 | #define SHORTCONVENIENCE( name, initsel ) CONVENIENCE( name##initsel , init##initsel ) 168 | #endif 169 | 170 | 171 | //--- compatibility: 172 | 173 | //#define accessor idAccessor 174 | //#define accessor_h idAccessor_h 175 | 176 | 177 | //---- RETAIN/RELEASE Macros for GNUStep compatibility 178 | 179 | #if __has_feature(objc_arc) 180 | #define DEALLOC( x) \ 181 | -(void)dealloc { \ 182 | x; \ 183 | } 184 | #else 185 | #define DEALLOC( x) \ 186 | -(oneway void)dealloc { \ 187 | x; \ 188 | [super dealloc]; \ 189 | } 190 | #endif 191 | 192 | #ifndef RETAIN 193 | #if !__has_feature(objc_arc) 194 | #define RETAIN(x) ([(x) retain]) 195 | #else 196 | #define RETAIN(x) (x) 197 | #endif 198 | #endif 199 | 200 | #ifndef RELEASE 201 | #if !__has_feature(objc_arc) 202 | #define RELEASE(x) ([(x) release]) 203 | #else 204 | #define RELEASE(x) 205 | #endif 206 | #endif 207 | 208 | 209 | #ifndef DESTROY 210 | #define DESTROY(x) RELEASE(x) 211 | #endif 212 | 213 | #ifndef ASSIGN 214 | #define ASSIGN(var,value) ASSIGN_ID(var,value) 215 | #endif 216 | 217 | #ifndef ASSIGNCOPY 218 | #define ASSIGNCOPY(var,value) ASSIGN(var,[(value) copy]) 219 | #endif 220 | 221 | 222 | #endif 223 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/Classes/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // DictTest 4 | // 5 | // Created by Wagner Truppel on 4/14/09. 6 | // Copyright Wagner Truppel 2009. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ViewController; 12 | 13 | @interface AppDelegate: NSObject 14 | { 15 | @private 16 | 17 | IBOutlet UIWindow* window; 18 | IBOutlet ViewController* viewController; 19 | } 20 | 21 | @property (nonatomic, retain) UIWindow* window; 22 | @property (nonatomic, retain) ViewController* viewController; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/Classes/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // DictTest 4 | // 5 | // Created by Wagner Truppel on 4/14/09. 6 | // Copyright Wagner Truppel 2009. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import "ViewController.h" 12 | 13 | @implementation AppDelegate 14 | 15 | @synthesize window; 16 | @synthesize viewController; 17 | 18 | // ========================================================================= // 19 | 20 | - (void) applicationDidFinishLaunching: (UIApplication*) application 21 | { 22 | // NSLog(@"AppDelegate: -applicationDidFinishLaunching"); 23 | 24 | NSLog(@"sizeof long: %lu",sizeof(long)); 25 | [window addSubview: viewController.view]; 26 | [window makeKeyAndVisible]; 27 | } 28 | 29 | // ========================================================================= // 30 | 31 | - (void) dealloc 32 | { 33 | // NSLog(@"AppDelegate: -dealloc"); 34 | 35 | [viewController release]; 36 | [window release]; 37 | [super dealloc]; 38 | } 39 | 40 | // ========================================================================= // 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/Classes/MPWBinaryPlist.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPWBinaryPlist.h 3 | // MPWFoundation 4 | // 5 | // Created by Marcel Weiher on 9/27/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @class MPWIntArray; 12 | 13 | @interface MPWBinaryPlist : NSObject 14 | { 15 | NSData *data; 16 | const unsigned char *bytes; 17 | long dataLen; 18 | long rootIndex; 19 | long numObjects; 20 | long offsetTableLocation; 21 | long *offsets; 22 | id *objects; 23 | int offsetIntegerSizeInBytes; 24 | int offsetReferenceSizeInBytes; 25 | BOOL lazyArray; 26 | long currentObjectNo; 27 | long currentKeyNo; 28 | MPWIntArray *objectNoStack; 29 | MPWIntArray *keyNoStack; 30 | 31 | long currentDictOffset,currentDictLength,currentDictIndex; 32 | } 33 | 34 | typedef void (^ArrayElementBlock)(MPWBinaryPlist* plist,long offset,long anIndex); 35 | 36 | typedef void (^DictElementBlock)(MPWBinaryPlist* plist,long keyOffset,long valueOffset,long anIndex); 37 | 38 | 39 | 40 | -initWithData:(NSData*)newPlistData; 41 | +bplistWithData:(NSData*)newPlistData; 42 | -(long)parseIntegerAtOffset:(long)offset; 43 | -(long)offsetOfObjectNo:(long)offsetNo; 44 | -(long)_rootOffset; 45 | 46 | -(long)parseArrayAtIndex:(long)anIndex usingBlock:(ArrayElementBlock)block; 47 | -(long)currentInt; 48 | 49 | -(NSArray*)readArrayAtIndex:(long)anIndex; 50 | -(long)parseDictAtIndex:(long)anIndex usingBlock:(DictElementBlock)block; 51 | -(NSDictionary*)readDictAtIndex:(long)anIndex; 52 | -(BOOL)isArrayAtIndex:(long)anIndex; 53 | -(BOOL)isArray; 54 | -objectAtIndex:(NSUInteger)anIndex; 55 | -(long)rootIndex; 56 | -(float)readFloat; 57 | -(double)readDouble; 58 | -(BOOL)verifyKey:keyToCheck forIndex:(long)keyOffset; 59 | 60 | -(long)decodeIntForKey:(NSString*)aKey; 61 | -(double)decodeDoubleForKey:(NSString*)aKey; 62 | -(id)decodeObjectForKey:(NSString*)aKey; 63 | -(BOOL)isArrayAtKey:(NSString*)aKey; 64 | 65 | -(long)parseDictAtIndex:(long)anIndex usingContentBlock:(DictElementBlock)block; 66 | -(long)parseDictUsingContentBlock:(DictElementBlock)block; 67 | 68 | -(long)parseArrayAtKey:(NSString*)aKey usingBlock:(ArrayElementBlock)block; 69 | 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/Classes/MPWIntArray.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPWIntArray.h 3 | // MPWFoundation 4 | // 5 | // Created by Marcel Weiher on Sat Dec 27 2003. 6 | /* 7 | Copyright (c) 2003-2012 by Marcel Weiher. All rights reserved. 8 | 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions 12 | are met: 13 | 14 | Redistributions of source code must retain the above copyright 15 | notice, this list of conditions and the following disclaimer. 16 | 17 | Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in 19 | the documentation and/or other materials provided with the distribution. 20 | 21 | Neither the name Marcel Weiher nor the names of contributors may 22 | be used to endorse or promote products derived from this software 23 | without specific prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 29 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 35 | THE POSSIBILITY OF SUCH DAMAGE. 36 | 37 | */ 38 | 39 | // 40 | 41 | #import 42 | 43 | 44 | @interface MPWIntArray : NSObject { 45 | int *data; 46 | unsigned count,capacity; 47 | } 48 | 49 | +array; 50 | -(int)integerAtIndex:(unsigned)index; 51 | -(void)addIntegers:(int*)intArray count:(unsigned)numIntsToAdd; 52 | -(void)addInteger:(int)anInt; 53 | -(void)addObject:anObject; 54 | -(void)replaceIntegerAtIndex:(unsigned)anIndex withInteger:(int)anInt; 55 | -(NSUInteger)count; 56 | -(void)reset; 57 | -(int*)integers; 58 | -(int)lastInteger; 59 | -(void)removeLastObject; 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/Classes/MPWIntArray.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPWIntArray.m 3 | // MPWFoundation 4 | // 5 | // Created by Marcel Weiher on Sat Dec 27 2003. 6 | /* 7 | Copyright (c) 2003-2012 by Marcel Weiher. All rights reserved. 8 | 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions 12 | are met: 13 | 14 | Redistributions of source code must retain the above copyright 15 | notice, this list of conditions and the following disclaimer. 16 | 17 | Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in 19 | the documentation and/or other materials provided with the distribution. 20 | 21 | Neither the name Marcel Weiher nor the names of contributors may 22 | be used to endorse or promote products derived from this software 23 | without specific prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 29 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 35 | THE POSSIBILITY OF SUCH DAMAGE. 36 | 37 | */ 38 | // 39 | 40 | #import "MPWIntArray.h" 41 | #import 42 | 43 | @implementation MPWIntArray 44 | 45 | +array 46 | { 47 | return [[[self alloc] init] autorelease]; 48 | } 49 | 50 | -initWithCapacity:(unsigned int)newCapacity 51 | { 52 | if ( self = [super init] ) { 53 | capacity=newCapacity; 54 | count=0; 55 | data=malloc( (capacity+3) * sizeof(int) ); 56 | } 57 | return self; 58 | } 59 | 60 | -init 61 | { 62 | return [self initWithCapacity:10]; 63 | } 64 | 65 | -(int)integerAtIndex:(unsigned)index 66 | { 67 | if ( index < count ) { 68 | return data[index]; 69 | } else { 70 | [NSException raise:@"MPWRangeException" format:@"%@ range exception: %d beyond count: %d (capacity: %d)",[self class],index,count,capacity]; 71 | return 0; 72 | } 73 | } 74 | 75 | -(void)_growTo:(unsigned)newCapacity 76 | { 77 | capacity=capacity*2+2; 78 | capacity=MAX( capacity, newCapacity ); 79 | if ( data ) { 80 | data=realloc( data, (capacity+3)*sizeof(int) ); 81 | } else { 82 | data=calloc( (capacity+3), sizeof(int) ); 83 | } 84 | } 85 | 86 | 87 | -(void)addIntegers:(int*)intArray count:(unsigned)numIntsToAdd 88 | { 89 | unsigned newCount=count+numIntsToAdd; 90 | if ( newCount >= capacity ) { 91 | [self _growTo:newCount]; 92 | } 93 | memcpy( data+count, intArray, numIntsToAdd * sizeof(int)); 94 | count=newCount; 95 | } 96 | 97 | -(void)addInteger:(int)anInt 98 | { 99 | unsigned newCount=count+1; 100 | if ( newCount >= capacity ) { 101 | [self _growTo:newCount]; 102 | } 103 | data[count]=anInt; 104 | count=newCount; 105 | } 106 | 107 | -(void)addObject:anObject 108 | { 109 | [self addInteger:[anObject intValue]]; 110 | } 111 | 112 | -(void)removeLastObject 113 | { 114 | if ( count) { 115 | count--; 116 | } 117 | } 118 | 119 | -(void)replaceIntegerAtIndex:(unsigned)anIndex withInteger:(int)anInt 120 | { 121 | if ( anIndex < count ) { 122 | data[anIndex]=anInt; 123 | } else { 124 | [NSException raise:@"MPWRangeException" format:@"%@ range exception: %d beyond count: %d (capacity: %d)",[self class],anIndex,count,capacity]; 125 | } 126 | } 127 | 128 | -(void)replaceObjectAtIndex:(unsigned)anIndex withObject:anObject 129 | { 130 | [self replaceIntegerAtIndex:anIndex withInteger:[anObject intValue]]; 131 | } 132 | 133 | -(void)dealloc 134 | { 135 | if ( data ) { 136 | free(data); 137 | } 138 | [super dealloc]; 139 | } 140 | 141 | -(NSUInteger)count 142 | { 143 | return count; 144 | } 145 | 146 | -(void)reset 147 | { 148 | count=0; 149 | } 150 | 151 | -(int*)integers 152 | { 153 | return data; 154 | } 155 | 156 | -(int)lastInteger 157 | { 158 | return data[count-1]; 159 | } 160 | 161 | -description 162 | { 163 | if ( [self count] ) { 164 | NSMutableString *description=[NSMutableString stringWithFormat:@"( %d",[self integerAtIndex:0]]; 165 | for (int i=1;i<[self count];i++) { 166 | [description appendFormat:@", %d",[self integerAtIndex:i]]; 167 | } 168 | [description appendString:@")"]; 169 | return description; 170 | } else { 171 | return @"( )"; 172 | } 173 | } 174 | 175 | @end 176 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/Classes/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // DictTest 4 | // 5 | // Created by Wagner Truppel on 4/14/09. 6 | // Copyright Wagner Truppel 2009. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController: UIViewController 12 | { 13 | @private 14 | 15 | IBOutlet UITextField* stringDictNumWordsTF; 16 | IBOutlet UITextField* stringDictTimeTF; 17 | 18 | IBOutlet UITextField* stdioDictNumWordsTF; 19 | IBOutlet UITextField* stdioDictTimeTF; 20 | 21 | IBOutlet UITextField* txtNumWordsTF; 22 | IBOutlet UITextField* txtTimeTF; 23 | 24 | IBOutlet UITextField* xmlNumWordsTF; 25 | IBOutlet UITextField* xmlTimeTF; 26 | 27 | IBOutlet UITextField* binNumWordsTF; 28 | IBOutlet UITextField* binTimeTF; 29 | 30 | IBOutlet UITextField* lazyNumWordsTF; 31 | IBOutlet UITextField* lazyTimeTF; 32 | 33 | IBOutlet UIButton* reloadBtn; 34 | } 35 | 36 | - (IBAction) actionReload: (id) sender; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/Classes/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // DictTest 4 | // 5 | // Created by Wagner Truppel on 4/14/09. 6 | // Copyright Wagner Truppel 2009. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "StringTable.h" 11 | #import "MPWBinaryPlist.h" 12 | #import "SimpleStdioStringDict.h" 13 | #include 14 | 15 | typedef enum enFileKind 16 | { 17 | kFileKindTxt = 0, 18 | kFileKindXml, 19 | kFileKindBin 20 | 21 | } FileKind; 22 | 23 | 24 | @interface ViewController (Private) 25 | 26 | - (NSString*) pathToFileOfKind: (FileKind) fileKind; 27 | 28 | @end 29 | 30 | 31 | @implementation ViewController 32 | 33 | // ========================================================================= // 34 | 35 | - (void) dealloc 36 | { 37 | // NSLog(@"ViewController: -dealloc"); 38 | 39 | [txtNumWordsTF release]; 40 | [txtTimeTF release]; 41 | 42 | [xmlNumWordsTF release]; 43 | [xmlTimeTF release]; 44 | 45 | [binNumWordsTF release]; 46 | [binTimeTF release]; 47 | 48 | [reloadBtn release]; 49 | 50 | [super dealloc]; 51 | } 52 | 53 | // ========================================================================= // 54 | 55 | - (void) didReceiveMemoryWarning 56 | { 57 | NSLog(@"ViewController: -didReceiveMemoryWarning"); 58 | [super didReceiveMemoryWarning]; 59 | } 60 | 61 | // ========================================================================= // 62 | 63 | 64 | 65 | - (IBAction) actionReload: (id) sender 66 | { 67 | // NSLog(@"ViewController: -actionReload"); 68 | 69 | NSArray *strings=@[ @"abacate", @"MarcelWeiher" ]; 70 | 71 | NSString* path; 72 | NSDate* start; 73 | NSArray* array; 74 | NSTimeInterval timeElapsed; 75 | // NSString* result; 76 | 77 | [sender setEnabled: NO]; 78 | 79 | // ============== // 80 | 81 | path = [self pathToFileOfKind: kFileKindBin]; 82 | start = [NSDate date]; 83 | NSData *d=[NSData dataWithContentsOfMappedFile:path]; 84 | MPWBinaryPlist *plist=[[[MPWBinaryPlist alloc] initWithData:d] autorelease]; 85 | [plist setLazyArray:YES]; 86 | array = [plist rootObject]; 87 | 88 | timeElapsed = -[start timeIntervalSinceNow]; 89 | 90 | lazyTimeTF.text = [NSString stringWithFormat:@"%f",timeElapsed*1000]; 91 | lazyNumWordsTF.text = [NSString stringWithFormat: @"%i", (int)[array count]]; 92 | 93 | start = [NSDate date]; 94 | array = [[NSArray alloc] initWithContentsOfFile: path]; 95 | timeElapsed = -[start timeIntervalSinceNow]; 96 | 97 | 98 | binNumWordsTF.text = [NSString stringWithFormat: @"%lu", (unsigned long)[array count]]; 99 | 100 | [array release]; 101 | 102 | binTimeTF.text = [NSString stringWithFormat:@"%f",timeElapsed*1000]; 103 | 104 | // ============== // 105 | 106 | path = [self pathToFileOfKind: kFileKindXml]; 107 | 108 | start = [NSDate date]; 109 | array = [[NSArray alloc] initWithContentsOfFile: path]; 110 | timeElapsed = -[start timeIntervalSinceNow]; 111 | 112 | xmlNumWordsTF.text = [NSString stringWithFormat: @"%lu", (unsigned long)[array count]]; 113 | 114 | [array release]; 115 | 116 | xmlTimeTF.text = [NSString stringWithFormat:@"%f",timeElapsed*1000]; 117 | 118 | // ============== // 119 | 120 | path = [self pathToFileOfKind: kFileKindTxt]; 121 | 122 | start = [NSDate date]; 123 | 124 | NSError* error; 125 | NSString* stringFromFileAtPath = 126 | [[NSString alloc] initWithContentsOfFile: path 127 | encoding: NSUTF8StringEncoding 128 | error: &error]; 129 | NSSet *toSearch=nil; 130 | if (stringFromFileAtPath == nil) 131 | { 132 | NSLog(@"Error reading file at %@\n%@", 133 | path, [error localizedFailureReason]); 134 | } 135 | else 136 | { 137 | array = [stringFromFileAtPath componentsSeparatedByString: @"\n"]; 138 | timeElapsed = -[start timeIntervalSinceNow]; 139 | [stringFromFileAtPath release]; 140 | 141 | txtNumWordsTF.text = [NSString stringWithFormat: @"%lu", (unsigned long)[array count]]; 142 | 143 | txtTimeTF.text = [NSString stringWithFormat:@"%f",timeElapsed*1000]; 144 | } 145 | 146 | start = [NSDate date]; 147 | 148 | toSearch=[NSSet setWithArray:array]; 149 | timeElapsed = -[start timeIntervalSinceNow]; 150 | NSLog(@"time to convert NSArray to NSSet: %g",timeElapsed); 151 | #if 1 152 | 153 | start = [NSDate date]; 154 | for ( int i=0; i<50; i++) { 155 | for ( NSString *s in strings) { 156 | [array containsObject:s]; 157 | } 158 | } 159 | timeElapsed = -[start timeIntervalSinceNow]; 160 | NSLog(@"time to lineaer search nsarray 100 times: %g",timeElapsed); 161 | 162 | 163 | start = [NSDate date]; 164 | for ( int i=0; i<500000; i++) { 165 | for ( NSString *s in strings) { 166 | [toSearch containsObject:s]; 167 | } 168 | } 169 | timeElapsed = -[start timeIntervalSinceNow]; 170 | NSLog(@"time to search nsset (from nsarray) 1000000 times: %g",timeElapsed); 171 | 172 | start = [NSDate date]; 173 | for ( int i=0; i<500000; i++) { 174 | for ( NSString *s in strings) { 175 | [array indexOfObject:s inSortedRange:NSMakeRange(0, [array count]) options:NSBinarySearchingFirstEqual usingComparator:^( NSString* obj1, NSString* obj2){ 176 | return [obj1 compare:obj2 options:0]; 177 | }]; 178 | } 179 | } 180 | timeElapsed = -[start timeIntervalSinceNow]; 181 | NSLog(@"time to binary search array 1000000 times: %g",timeElapsed); 182 | #endif 183 | 184 | // ============== // 185 | 186 | path = [self pathToFileOfKind: kFileKindTxt]; 187 | 188 | start = [NSDate date]; 189 | 190 | StringTable* stringDict = 191 | [[[StringTable alloc] initWithContentsOfFile:path] autorelease]; 192 | 193 | timeElapsed = -[start timeIntervalSinceNow]; 194 | stringDictNumWordsTF.text = [NSString stringWithFormat: @"%i", [stringDict count]]; 195 | stringDictTimeTF.text = [NSString stringWithFormat:@"%f",timeElapsed*1000]; 196 | 197 | start = [NSDate date]; 198 | 199 | SimpleStdioStringDict* stdioDict = 200 | [[[SimpleStdioStringDict alloc] initWithContentsOfFile:path] autorelease]; 201 | NSLog(@"stdioDict: %@",stdioDict); 202 | timeElapsed = -[start timeIntervalSinceNow]; 203 | 204 | stdioDictNumWordsTF.text = [NSString stringWithFormat: @"%i", [stringDict count]]; 205 | stdioDictTimeTF.text = [NSString stringWithFormat:@"%f",timeElapsed*1000]; 206 | 207 | 208 | for ( NSString *s in strings) { 209 | NSLog(@"strings %@ in dict: %d",s,[stringDict containsString:s]); 210 | } 211 | 212 | start = [NSDate date]; 213 | 214 | 215 | for ( int i=0; i<1000; i++) { 216 | for ( NSString *s in strings) { 217 | [stringDict containsString:s]; 218 | } 219 | } 220 | 221 | timeElapsed = -[start timeIntervalSinceNow]; 222 | NSLog(@"time to bsearch 1000 times (via SimpleDict containsString:): %g",timeElapsed); 223 | // ============== // 224 | 225 | [sender setEnabled: YES]; 226 | } 227 | 228 | // ========================================================================= // 229 | #pragma mark private methods 230 | // ========================================================================= // 231 | 232 | - (NSString*) pathToFileOfKind: (FileKind) fileKind 233 | { 234 | // NSLog(@"ViewController: -pathToFileOfKind"); 235 | 236 | NSString* fname; 237 | NSString* path; 238 | 239 | switch (fileKind) 240 | { 241 | case kFileKindTxt: 242 | fname = @"dictionary.txt"; 243 | path = [[NSBundle mainBundle] 244 | pathForResource: @"dictionary" 245 | ofType: @"txt"]; 246 | break; 247 | 248 | case kFileKindXml: 249 | fname = @"dictionary_xml.plist"; 250 | path = [[NSBundle mainBundle] 251 | pathForResource: @"dictionary_xml" 252 | ofType: @"plist"]; 253 | break; 254 | 255 | case kFileKindBin: 256 | fname = @"dictionary_bin.plist"; 257 | path = [[NSBundle mainBundle] 258 | pathForResource: @"dictionary_bin" 259 | ofType: @"plist"]; 260 | break; 261 | 262 | default: 263 | fname = nil; 264 | path = nil; 265 | break; 266 | } 267 | 268 | BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath: path]; 269 | 270 | if (fileExists) 271 | { 272 | return path; 273 | } 274 | else 275 | { 276 | NSLog(@"*** ERROR *** ERROR *** ERROR *** ERROR ***"); 277 | NSLog(@"*** ERROR! file '%@' not found!", fname); 278 | 279 | return nil; 280 | } 281 | } 282 | 283 | // ========================================================================= // 284 | 285 | @end 286 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/Classes/nspl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpw/iOS-macOS-performance/2ff95f54e8278df3fd51016f0339cffb44f55824/Chapter-13/DictTest/Classes/nspl -------------------------------------------------------------------------------- /Chapter-13/DictTest/Classes/nspl.m: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007 Michael Ash 2 | Copyright (c) 2007 Jens Ayton (uid decoding) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 9 | #import "NSPropertyListReader_binary1.h" 10 | #import 11 | #import 12 | #import 13 | 14 | @interface NSPropertyListReader_binary1 (Private) 15 | 16 | - (id)_readInlineObjectAtOffset: (unsigned *)offset; 17 | 18 | @end 19 | 20 | @interface LazyArray : NSArray 21 | { 22 | unsigned count; 23 | id plist; 24 | id *objs; 25 | int *offsets; 26 | } 27 | @end 28 | 29 | @implementation LazyArray 30 | 31 | 32 | -(unsigned)count { return count; } 33 | 34 | 35 | -initWithPlist:newPlist offsets:(int*)newOffsets count:(unsigned )newCount 36 | { 37 | self=[super init]; 38 | if (self ) { 39 | count=newCount; 40 | objs=calloc( count , sizeof *objs); 41 | offsets=malloc( count * sizeof *offsets); 42 | memcpy(offsets, newOffsets,count * sizeof *offsets ); 43 | } 44 | return self; 45 | } 46 | 47 | -objectAtIndex:(unsigned)anIndex 48 | { 49 | id obj=nil; 50 | if ( anIndex < count) { 51 | obj=objs[anIndex]; 52 | if ( obj == nil) { 53 | unsigned localOffset=offsets[anIndex]; 54 | obj = [plist _readObjectAtOffset:&localOffset]; 55 | objs[anIndex]=obj; 56 | } 57 | } else { 58 | [NSException raise:@"outofbounds" format:@"index %d out of bounds",anIndex]; 59 | } 60 | return obj; 61 | } 62 | 63 | @end 64 | 65 | @implementation NSPropertyListReader_binary1 66 | 67 | +propertyListFromData:(NSData *)data { 68 | id result=nil; 69 | NSPropertyListReader_binary1 *reader=[[self alloc] initWithData:data]; 70 | 71 | if(reader==nil) 72 | return nil; 73 | 74 | result=[reader read]; 75 | [reader release]; 76 | 77 | return result; 78 | } 79 | 80 | #define MAGIC "bplist" 81 | #define FORMAT "00" 82 | #define TRAILER_SIZE (sizeof( uint8_t ) * 2 + sizeof( uint64_t ) * 3) 83 | 84 | - (id)initWithData: (NSData *)data 85 | { 86 | if( (self = [self init]) ) 87 | { 88 | unsigned magiclen = strlen( MAGIC FORMAT ); 89 | 90 | BOOL good = YES; 91 | if( good && [data length] < magiclen + TRAILER_SIZE ) 92 | good = NO; 93 | if( good && strncmp( [data bytes], MAGIC FORMAT, magiclen ) != 0 ) 94 | good = NO; 95 | 96 | if( !good ) 97 | { 98 | [self release]; 99 | return nil; 100 | } 101 | 102 | // [data subdataWithRange: NSMakeRange( magiclen, [data length] - magiclen )] 103 | _data = [data copy]; 104 | } 105 | return self; 106 | } 107 | 108 | - (void)dealloc 109 | { 110 | [_data release]; 111 | 112 | [super dealloc]; 113 | } 114 | 115 | - (uint64_t)_readIntOfSize: (unsigned)size atOffset: (unsigned *)offsetPtr 116 | { 117 | uint64_t ret = 0; 118 | const uint8_t *ptr = [_data bytes] + *offsetPtr; 119 | unsigned i; 120 | for( i = 0; i < size; i++ ) 121 | { 122 | ret <<= 8; 123 | ret |= *ptr; 124 | ptr++; 125 | } 126 | 127 | *offsetPtr += size; 128 | 129 | return ret; 130 | } 131 | 132 | - (double)_readFloatOfSize: (unsigned)size atOffset: (unsigned *)offsetPtr 133 | { 134 | uint64_t val = [self _readIntOfSize: size atOffset: offsetPtr]; 135 | 136 | if( size == 4 ) 137 | { 138 | uint32_t val32 = val; 139 | return *(float *)&val32; 140 | } 141 | if( size == 8 ) 142 | { 143 | return *(double *)&val; 144 | } 145 | 146 | [NSException raise: @"Invalid size" format: @"Don't know how to read float of size %u", size]; 147 | return 0.0; 148 | } 149 | 150 | - (void)_readHeader 151 | { 152 | unsigned trailerStart = [_data length] - TRAILER_SIZE; 153 | 154 | _trailerOffsetIntSize = [self _readIntOfSize: sizeof( _trailerOffsetIntSize ) 155 | atOffset: &trailerStart]; 156 | _trailerOffsetRefSize = [self _readIntOfSize: sizeof( _trailerOffsetRefSize ) 157 | atOffset: &trailerStart]; 158 | _trailerNumObjects = [self _readIntOfSize: sizeof( _trailerNumObjects ) 159 | atOffset: &trailerStart]; 160 | _trailerTopObject = [self _readIntOfSize: sizeof( _trailerTopObject ) 161 | atOffset: &trailerStart]; 162 | _trailerOffsetTableOffset = [self _readIntOfSize: sizeof( _trailerOffsetTableOffset ) 163 | atOffset: &trailerStart]; 164 | } 165 | 166 | static uint64_t ReadSizedInt(NSPropertyListReader_binary1 *bplist, uint64_t offset, uint8_t size) 167 | { 168 | const uint8_t *ptr = [bplist->_data bytes]; 169 | unsigned length=[bplist->_data length]; 170 | 171 | assert(ptr != NULL && size >= 1 && size <= 8 && offset + size <= length); 172 | 173 | uint64_t result = 0; 174 | const uint8_t *byte = ptr + offset; 175 | 176 | do 177 | { 178 | result = (result << 8) | *byte++; 179 | } while (--size); 180 | 181 | return result; 182 | } 183 | 184 | static BOOL ReadSelfSizedInt(NSPropertyListReader_binary1 *bplist, uint64_t offset, uint64_t *outValue, size_t *outSize) 185 | { 186 | const uint8_t *ptr = [bplist->_data bytes]; 187 | unsigned length=[bplist->_data length]; 188 | 189 | uint32_t size; 190 | int64_t value; 191 | 192 | assert(ptr != NULL && offset < length); 193 | 194 | size = 1 << (ptr[offset] & 0x0F); 195 | if (size > 8) 196 | { 197 | // Maximum allowable size in this implementation is 1<<3 = 8 bytes. 198 | // This also happens to be the biggest NSNumber can handle. 199 | return NO; 200 | } 201 | 202 | if (offset + 1+size > length) 203 | { 204 | // Out of range. 205 | return NO; 206 | } 207 | 208 | value = ReadSizedInt(bplist, offset +1, size); 209 | 210 | if (outValue != NULL) *outValue = value; 211 | if (outSize != NULL) *outSize = size + 1; // +1 for tag byte. 212 | return YES; 213 | } 214 | 215 | static id ExtractUID(NSPropertyListReader_binary1 *bplist, uint64_t offset) 216 | { 217 | /* UIDs are used by Cocoa's key-value coder. 218 | When writing other plist formats, they are expanded to dictionaries of 219 | the form CF$UIDvalue, so we 220 | do the same here on reading. This results in plists identical to what 221 | running plutil -convert xml1 gives us. However, this is not the same 222 | result as [Core]Foundation's plist parser, which extracts them as un- 223 | introspectable CF objects. In fact, it even seems to convert the CF$UID 224 | dictionaries from XML plists on the fly. 225 | */ 226 | 227 | uint64_t value; 228 | 229 | if (!ReadSelfSizedInt(bplist, offset, &value, NULL)) 230 | { 231 | NSLog(@"Bad binary plist: invalid UID object."); 232 | return nil; 233 | } 234 | 235 | return [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedLongLong:value] forKey:@"CF$UID"]; 236 | } 237 | 238 | - (id)_readObjectAtOffset: (unsigned *)offset 239 | { 240 | const uint8_t *ptr = [_data bytes]; 241 | uint8_t marker = ptr[*offset]; 242 | 243 | (*offset)++; 244 | 245 | if( marker == 0x00 ) 246 | return [NSNull null]; 247 | if( marker == 0x08 ) 248 | return [NSNumber numberWithBool: NO]; 249 | if( marker == 0x09 ) 250 | return [NSNumber numberWithBool: YES]; 251 | 252 | uint8_t topNibble = marker >> 4; 253 | uint8_t botNibble = marker & 0x0F; 254 | 255 | if( topNibble == 0x1 ) 256 | return [NSNumber numberWithLongLong: [self _readIntOfSize: 1 << botNibble 257 | atOffset: offset]]; 258 | if( topNibble == 0x2 ) 259 | { 260 | unsigned size = 1 << botNibble; 261 | uint64_t val = [self _readIntOfSize: size atOffset: offset]; 262 | 263 | if( size == 4 ) 264 | { 265 | uint32_t val32 = val; 266 | return [NSNumber numberWithFloat: *(float*)&val32]; 267 | } 268 | if( size == 8 ) 269 | { 270 | return [NSNumber numberWithDouble: *(double*)&val]; 271 | } 272 | return [NSNumber numberWithDouble:0.0]; 273 | } 274 | if( topNibble == 0x3 ) 275 | return [NSDate dateWithTimeIntervalSinceReferenceDate: 276 | [self _readFloatOfSize: 8 atOffset: offset]]; 277 | if( topNibble == 0x4 || topNibble == 0x5 || topNibble == 0x6 || topNibble == 0x8 || topNibble == 0xA || topNibble == 0xD ) 278 | { 279 | uint64_t length = 0; 280 | if( botNibble != 0xF ) 281 | length = botNibble; 282 | else 283 | length = [[self _readObjectAtOffset: offset] unsignedLongLongValue]; 284 | 285 | if( topNibble == 0x4 ) 286 | return [_data subdataWithRange: NSMakeRange( *offset, length )]; 287 | if( topNibble == 0x5 ) 288 | return [[[NSString alloc] 289 | initWithData: [_data subdataWithRange: NSMakeRange( *offset, length )] 290 | encoding: NSASCIIStringEncoding] autorelease]; 291 | if( topNibble == 0x6 ){ 292 | 293 | return [[[NSString alloc] 294 | initWithData: [_data subdataWithRange: NSMakeRange( *offset, length * 2 )] 295 | encoding: NSUTF16BigEndianStringEncoding] autorelease]; 296 | } 297 | if( topNibble == 0x8 ) 298 | return ExtractUID(self, (*offset)-1); 299 | 300 | if( topNibble == 0xA ) 301 | { 302 | id result; 303 | // id *objs = malloc( length * sizeof( *objs ) ); 304 | int *offsets=malloc( length * sizeof( *offsets ) ); 305 | 306 | 307 | //readOffsetAtOffset 308 | uint64_t i; 309 | for( i = 0; i < length; i++ ) { 310 | // objs[i] = [self _readInlineObjectAtOffset: offset]; 311 | // objs[i] = [self _readLazyObjectAtOffset:offset]; 312 | offsets[i]=[self readOffsetAtOffset:offset]; 313 | } 314 | result=[[[LazyArray alloc] initWithPlist:self offsets:offsets count:length] autorelease]; 315 | // free(objs); 316 | free(offsets); 317 | return result; 318 | } 319 | 320 | if( topNibble == 0xD ) 321 | { 322 | id result; 323 | id *keys = malloc( length * sizeof( *keys ) ); 324 | id *objs = malloc( length * sizeof( *objs ) ); 325 | uint64_t i; 326 | for( i = 0; i < length; i++ ) 327 | keys[i] = [self _readInlineObjectAtOffset: offset]; 328 | for( i = 0; i < length; i++ ) { 329 | // objs[i] = [self _readOffsetNumberAtOffset:offset]; 330 | objs[i] = [self _readInlineObjectAtOffset: offset]; 331 | } 332 | result=[NSDictionary dictionaryWithObjects: objs 333 | forKeys: keys 334 | count: length]; 335 | free(keys); 336 | free(objs); 337 | return result; 338 | } 339 | } 340 | 341 | [NSException raise: @"Unknown marker in plist" format: @"Unable to read marker 0x%uX", marker]; 342 | return nil; 343 | } 344 | 345 | 346 | -(int)readOffsetAtOffset:(unsigned *)baseOffset 347 | { 348 | unsigned objOffset = [self _readIntOfSize: _trailerOffsetRefSize 349 | atOffset: baseOffset]; 350 | 351 | // then transform the index into an offset in the file which points to 352 | // that offset table entry 353 | objOffset = _trailerOffsetTableOffset + objOffset * _trailerOffsetIntSize; 354 | 355 | // lastly read the offset stored at that entry 356 | objOffset = [self _readIntOfSize: _trailerOffsetIntSize atOffset: &objOffset]; 357 | return objOffset; 358 | } 359 | 360 | - (id)_readInlineObjectAtOffset: (unsigned *)offset 361 | { 362 | // first read the offset table index out of the file 363 | unsigned objOffset = [self readOffsetAtOffset:offset]; 364 | 365 | // and read the object stored there 366 | return [self _readObjectAtOffset: &objOffset]; 367 | 368 | } 369 | 370 | 371 | -(id)_readOffsetNumberAtOffset:(unsigned*)offset 372 | { 373 | unsigned objOffset = [self readOffsetAtOffset:offset]; 374 | return [NSNumber numberWithInt:objOffset]; 375 | } 376 | 377 | #if 0 378 | -(id)_readLazyObjectAtOffset:(unsigned*)offset 379 | { 380 | unsigned objOffset = [self readOffsetAtOffset:offset]; 381 | return [[[IndexPlaceHolder alloc] initWithPlist:self offset:objOffset] autorelease]; 382 | } 383 | #endif 384 | 385 | - (id)read 386 | { 387 | id result=nil; 388 | 389 | //@try 390 | NS_DURING 391 | { 392 | [self _readHeader]; 393 | 394 | unsigned offset = _trailerTopObject + strlen( MAGIC FORMAT ); 395 | result= [self _readObjectAtOffset: &offset]; 396 | } 397 | NS_HANDLER 398 | // @catch( id exception ) 399 | { 400 | NSLog( @"Unable to read binary plist: %@", localException ); 401 | } 402 | NS_ENDHANDLER 403 | 404 | return result; 405 | } 406 | 407 | @end 408 | 409 | #if 1 410 | int main( int argc, char *argv[] ) { 411 | NSLog(@"---"); 412 | NSString *filename=[NSString stringWithUTF8String:argv[1]]; 413 | // NSData *data=[NSData dataWithContentsOfMappedFile:filename]; 414 | NSData *data=[NSData dataWithContentsOfFile:filename]; 415 | id plist = [NSPropertyListReader_binary1 propertyListFromData:data]; 416 | NSLog(@"got top level plist"); 417 | // NSLog(@"done %@ %ld elements: %@",[plist class],(long)[plist count],plist); 418 | // NSLog(@"done %@ %ld ",[plist class],(long)[plist count]); 419 | 420 | NSLog(@"one leaf suboject %@ ",[[[[plist objectForKey:@"c"] objectAtIndex:10] objectForKey:@"c"] objectAtIndex:10] ); 421 | // NSLog(@"one suboject %@ ",[[plist objectForKey:@"c"] objectAtIndex:10] ); 422 | return 0; 423 | } 424 | 425 | #endif 426 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/DictTest.xcodeproj/marcel.pbxuser: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | 1D3623250D0F684500981E51 /* AppDelegate.m */ = { 4 | uiCtxt = { 5 | sepNavIntBoundsRect = "{{0, 0}, {519, 588}}"; 6 | sepNavSelRange = "{0, 0}"; 7 | sepNavVisRange = "{485, 384}"; 8 | }; 9 | }; 10 | 1D6058900D05DD3D006BFB54 /* DictTest */ = { 11 | activeExec = 0; 12 | executables = ( 13 | 1F7BBD2F0F968C2C00DD49DC /* DictTest */, 14 | ); 15 | }; 16 | 1F7BBD2F0F968C2C00DD49DC /* DictTest */ = { 17 | isa = PBXExecutable; 18 | activeArgIndices = ( 19 | ); 20 | argumentStrings = ( 21 | ); 22 | autoAttachOnCrash = 1; 23 | breakpointsEnabled = 0; 24 | configStateDict = { 25 | }; 26 | customDataFormattersEnabled = 1; 27 | debuggerPlugin = GDBDebugging; 28 | disassemblyDisplayState = 0; 29 | dylibVariantSuffix = ""; 30 | enableDebugStr = 1; 31 | environmentEntries = ( 32 | ); 33 | executableSystemSymbolLevel = 0; 34 | executableUserSymbolLevel = 0; 35 | libgmallocEnabled = 0; 36 | name = DictTest; 37 | savedGlobals = { 38 | }; 39 | sourceDirectories = ( 40 | ); 41 | }; 42 | 1F7BBD3E0F968C4B00DD49DC /* Source Control */ = { 43 | isa = PBXSourceControlManager; 44 | fallbackIsa = XCSourceControlManager; 45 | isSCMEnabled = 0; 46 | scmConfiguration = { 47 | }; 48 | }; 49 | 1F7BBD3F0F968C4B00DD49DC /* Code sense */ = { 50 | isa = PBXCodeSenseManager; 51 | indexTemplatePath = ""; 52 | }; 53 | 1F7BBD400F968D6000DD49DC /* SuperSimpleStringDict.h */ = { 54 | uiCtxt = { 55 | sepNavIntBoundsRect = "{{0, 0}, {617, 656}}"; 56 | sepNavSelRange = "{330, 0}"; 57 | sepNavVisRange = "{0, 338}"; 58 | }; 59 | }; 60 | 1F7BBD410F968D6000DD49DC /* SuperSimpleStringDict.m */ = { 61 | uiCtxt = { 62 | sepNavIntBoundsRect = "{{0, 0}, {617, 700}}"; 63 | sepNavSelRange = "{456, 218}"; 64 | sepNavVisRange = "{31, 735}"; 65 | }; 66 | }; 67 | 1F7BBD4C0F968FF700DD49DC /* PBXTextBookmark */ = { 68 | isa = PBXTextBookmark; 69 | fRef = 1D3623250D0F684500981E51 /* AppDelegate.m */; 70 | name = "AppDelegate.m: 1"; 71 | rLen = 0; 72 | rLoc = 0; 73 | rType = 0; 74 | vrLen = 384; 75 | vrLoc = 485; 76 | }; 77 | 1F7BBD4D0F968FF700DD49DC /* PBXTextBookmark */ = { 78 | isa = PBXTextBookmark; 79 | fRef = 28D7ACF60DDB3853001CB0EB /* ViewController.h */; 80 | name = "ViewController.h: 16"; 81 | rLen = 0; 82 | rLoc = 305; 83 | rType = 0; 84 | vrLen = 651; 85 | vrLoc = 0; 86 | }; 87 | 1F7BBD4E0F968FF700DD49DC /* PBXTextBookmark */ = { 88 | isa = PBXTextBookmark; 89 | fRef = 1F7BBD410F968D6000DD49DC /* SuperSimpleStringDict.m */; 90 | name = "SuperSimpleStringDict.m: 29"; 91 | rLen = 218; 92 | rLoc = 456; 93 | rType = 0; 94 | vrLen = 735; 95 | vrLoc = 31; 96 | }; 97 | 1F7BBD4F0F968FF700DD49DC /* PBXTextBookmark */ = { 98 | isa = PBXTextBookmark; 99 | fRef = 1F7BBD400F968D6000DD49DC /* SuperSimpleStringDict.h */; 100 | name = "SuperSimpleStringDict.h: 19"; 101 | rLen = 0; 102 | rLoc = 330; 103 | rType = 0; 104 | vrLen = 338; 105 | vrLoc = 0; 106 | }; 107 | 1F7BBD500F968FF700DD49DC /* PBXTextBookmark */ = { 108 | isa = PBXTextBookmark; 109 | comments = "error: redeclaration of ‘error’ with no linkage"; 110 | fRef = 28D7ACF70DDB3853001CB0EB /* ViewController.m */; 111 | rLen = 1; 112 | rLoc = 146; 113 | rType = 1; 114 | }; 115 | 1F7BBD510F968FF700DD49DC /* PBXTextBookmark */ = { 116 | isa = PBXTextBookmark; 117 | fRef = 1D3623250D0F684500981E51 /* AppDelegate.m */; 118 | name = "AppDelegate.m: 1"; 119 | rLen = 0; 120 | rLoc = 0; 121 | rType = 0; 122 | vrLen = 384; 123 | vrLoc = 485; 124 | }; 125 | 1F7BBD520F968FF700DD49DC /* PBXTextBookmark */ = { 126 | isa = PBXTextBookmark; 127 | fRef = 1F7BBD400F968D6000DD49DC /* SuperSimpleStringDict.h */; 128 | name = "SuperSimpleStringDict.h: 14"; 129 | rLen = 0; 130 | rLoc = 267; 131 | rType = 0; 132 | vrLen = 276; 133 | vrLoc = 0; 134 | }; 135 | 1F7BBD530F968FF700DD49DC /* PBXTextBookmark */ = { 136 | isa = PBXTextBookmark; 137 | fRef = 1F7BBD410F968D6000DD49DC /* SuperSimpleStringDict.m */; 138 | name = "SuperSimpleStringDict.m: 18"; 139 | rLen = 0; 140 | rLoc = 292; 141 | rType = 0; 142 | vrLen = 722; 143 | vrLoc = 44; 144 | }; 145 | 1F7BBD540F968FF700DD49DC /* PBXTextBookmark */ = { 146 | isa = PBXTextBookmark; 147 | fRef = 28D7ACF60DDB3853001CB0EB /* ViewController.h */; 148 | name = "ViewController.h: 1"; 149 | rLen = 0; 150 | rLoc = 0; 151 | rType = 0; 152 | vrLen = 578; 153 | vrLoc = 0; 154 | }; 155 | 1F7BBD550F968FF700DD49DC /* PBXTextBookmark */ = { 156 | isa = PBXTextBookmark; 157 | fRef = 28D7ACF70DDB3853001CB0EB /* ViewController.m */; 158 | name = "ViewController.m: 10"; 159 | rLen = 0; 160 | rLoc = 202; 161 | rType = 0; 162 | vrLen = 788; 163 | vrLoc = 0; 164 | }; 165 | 1F7BBD560F968FF700DD49DC /* PBXTextBookmark */ = { 166 | isa = PBXTextBookmark; 167 | fRef = 1F7BBD400F968D6000DD49DC /* SuperSimpleStringDict.h */; 168 | name = "SuperSimpleStringDict.h: 12"; 169 | rLen = 21; 170 | rLoc = 191; 171 | rType = 0; 172 | vrLen = 276; 173 | vrLoc = 0; 174 | }; 175 | 1F7BBD570F968FF700DD49DC /* PBXTextBookmark */ = { 176 | isa = PBXTextBookmark; 177 | fRef = 1F7BBD410F968D6000DD49DC /* SuperSimpleStringDict.m */; 178 | name = "SuperSimpleStringDict.m: 29"; 179 | rLen = 218; 180 | rLoc = 456; 181 | rType = 0; 182 | vrLen = 735; 183 | vrLoc = 31; 184 | }; 185 | 1F7BBD580F968FF700DD49DC /* PBXTextBookmark */ = { 186 | isa = PBXTextBookmark; 187 | fRef = 1F7BBD400F968D6000DD49DC /* SuperSimpleStringDict.h */; 188 | name = "SuperSimpleStringDict.h: 19"; 189 | rLen = 0; 190 | rLoc = 330; 191 | rType = 0; 192 | vrLen = 338; 193 | vrLoc = 0; 194 | }; 195 | 1F7BBD710F9690CD00DD49DC /* PBXTextBookmark */ = { 196 | isa = PBXTextBookmark; 197 | fRef = 28D7ACF70DDB3853001CB0EB /* ViewController.m */; 198 | name = "ViewController.m: 147"; 199 | rLen = 0; 200 | rLoc = 3347; 201 | rType = 0; 202 | vrLen = 1338; 203 | vrLoc = 2794; 204 | }; 205 | 28D7ACF60DDB3853001CB0EB /* ViewController.h */ = { 206 | uiCtxt = { 207 | sepNavIntBoundsRect = "{{0, 0}, {617, 656}}"; 208 | sepNavSelRange = "{305, 0}"; 209 | sepNavVisRange = "{0, 651}"; 210 | }; 211 | }; 212 | 28D7ACF70DDB3853001CB0EB /* ViewController.m */ = { 213 | uiCtxt = { 214 | sepNavIntBoundsRect = "{{0, 0}, {1145, 3122}}"; 215 | sepNavSelRange = "{3802, 0}"; 216 | sepNavVisRange = "{3266, 940}"; 217 | }; 218 | }; 219 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 220 | activeBuildConfigurationName = Debug; 221 | activeExecutable = 1F7BBD2F0F968C2C00DD49DC /* DictTest */; 222 | activeSDKPreference = iphoneos3.0; 223 | activeTarget = 1D6058900D05DD3D006BFB54 /* DictTest */; 224 | addToTargets = ( 225 | 1D6058900D05DD3D006BFB54 /* DictTest */, 226 | ); 227 | codeSenseManager = 1F7BBD3F0F968C4B00DD49DC /* Code sense */; 228 | executables = ( 229 | 1F7BBD2F0F968C2C00DD49DC /* DictTest */, 230 | ); 231 | perUserDictionary = { 232 | PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { 233 | PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; 234 | PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; 235 | PBXFileTableDataSourceColumnWidthsKey = ( 236 | 20, 237 | 439, 238 | 20, 239 | 48, 240 | 43, 241 | 43, 242 | 20, 243 | ); 244 | PBXFileTableDataSourceColumnsKey = ( 245 | PBXFileDataSource_FiletypeID, 246 | PBXFileDataSource_Filename_ColumnID, 247 | PBXFileDataSource_Built_ColumnID, 248 | PBXFileDataSource_ObjectSize_ColumnID, 249 | PBXFileDataSource_Errors_ColumnID, 250 | PBXFileDataSource_Warnings_ColumnID, 251 | PBXFileDataSource_Target_ColumnID, 252 | ); 253 | }; 254 | PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { 255 | PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; 256 | PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; 257 | PBXFileTableDataSourceColumnWidthsKey = ( 258 | 20, 259 | 399, 260 | 60, 261 | 20, 262 | 48.16259765625, 263 | 43, 264 | 43, 265 | ); 266 | PBXFileTableDataSourceColumnsKey = ( 267 | PBXFileDataSource_FiletypeID, 268 | PBXFileDataSource_Filename_ColumnID, 269 | PBXTargetDataSource_PrimaryAttribute, 270 | PBXFileDataSource_Built_ColumnID, 271 | PBXFileDataSource_ObjectSize_ColumnID, 272 | PBXFileDataSource_Errors_ColumnID, 273 | PBXFileDataSource_Warnings_ColumnID, 274 | ); 275 | }; 276 | PBXPerProjectTemplateStateSaveDate = 261526494; 277 | PBXWorkspaceStateSaveDate = 261526494; 278 | }; 279 | perUserProjectItems = { 280 | 1F7BBD4C0F968FF700DD49DC = 1F7BBD4C0F968FF700DD49DC /* PBXTextBookmark */; 281 | 1F7BBD4D0F968FF700DD49DC = 1F7BBD4D0F968FF700DD49DC /* PBXTextBookmark */; 282 | 1F7BBD4E0F968FF700DD49DC = 1F7BBD4E0F968FF700DD49DC /* PBXTextBookmark */; 283 | 1F7BBD4F0F968FF700DD49DC = 1F7BBD4F0F968FF700DD49DC /* PBXTextBookmark */; 284 | 1F7BBD500F968FF700DD49DC = 1F7BBD500F968FF700DD49DC /* PBXTextBookmark */; 285 | 1F7BBD510F968FF700DD49DC = 1F7BBD510F968FF700DD49DC /* PBXTextBookmark */; 286 | 1F7BBD520F968FF700DD49DC = 1F7BBD520F968FF700DD49DC /* PBXTextBookmark */; 287 | 1F7BBD530F968FF700DD49DC = 1F7BBD530F968FF700DD49DC /* PBXTextBookmark */; 288 | 1F7BBD540F968FF700DD49DC = 1F7BBD540F968FF700DD49DC /* PBXTextBookmark */; 289 | 1F7BBD550F968FF700DD49DC = 1F7BBD550F968FF700DD49DC /* PBXTextBookmark */; 290 | 1F7BBD560F968FF700DD49DC = 1F7BBD560F968FF700DD49DC /* PBXTextBookmark */; 291 | 1F7BBD570F968FF700DD49DC = 1F7BBD570F968FF700DD49DC /* PBXTextBookmark */; 292 | 1F7BBD580F968FF700DD49DC = 1F7BBD580F968FF700DD49DC /* PBXTextBookmark */; 293 | 1F7BBD710F9690CD00DD49DC = 1F7BBD710F9690CD00DD49DC /* PBXTextBookmark */; 294 | }; 295 | sourceControlManager = 1F7BBD3E0F968C4B00DD49DC /* Source Control */; 296 | userBuildSettings = { 297 | }; 298 | }; 299 | } 300 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/DictTest.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 45; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1D3623260D0F684500981E51 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* AppDelegate.m */; }; 11 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 12 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 13 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 14 | 1F21BF5C17E083FF003266F7 /* SimpleStdioStringDict.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F21BF5B17E083FF003266F7 /* SimpleStdioStringDict.m */; }; 15 | 1F8D7A93182806F500A46A31 /* MPWIntArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F8D7A92182806F500A46A31 /* MPWIntArray.m */; }; 16 | 1F8D7A981828075B00A46A31 /* StringTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F8D7A971828075B00A46A31 /* StringTable.m */; }; 17 | 1FA6DA6B1829486A00FE362E /* MPWBinaryPlist.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FA6DA6A1829486A00FE362E /* MPWBinaryPlist.m */; }; 18 | 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; 19 | 2899E5220DE3E06400AC0155 /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2899E5210DE3E06400AC0155 /* ViewController.xib */; }; 20 | 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; 21 | 28D7ACF80DDB3853001CB0EB /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* ViewController.m */; }; 22 | 3B28463E0F951E5600CF8FA4 /* dictionary.txt in Resources */ = {isa = PBXBuildFile; fileRef = 3B28463B0F951E5600CF8FA4 /* dictionary.txt */; }; 23 | 3B28463F0F951E5600CF8FA4 /* dictionary_xml.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B28463C0F951E5600CF8FA4 /* dictionary_xml.plist */; }; 24 | 3B2846400F951E5600CF8FA4 /* dictionary_bin.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B28463D0F951E5600CF8FA4 /* dictionary_bin.plist */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 29 | 1D3623240D0F684500981E51 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 30 | 1D3623250D0F684500981E51 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 31 | 1D6058910D05DD3D006BFB54 /* DictTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DictTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 33 | 1F21BF5A17E083FF003266F7 /* SimpleStdioStringDict.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SimpleStdioStringDict.h; path = ../SimpleStdioStringDict.h; sourceTree = ""; }; 34 | 1F21BF5B17E083FF003266F7 /* SimpleStdioStringDict.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SimpleStdioStringDict.m; path = ../SimpleStdioStringDict.m; sourceTree = ""; }; 35 | 1F7BBD400F968D6000DD49DC /* StringTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringTable.h; path = ../StringTable.h; sourceTree = ""; }; 36 | 1F8D7A92182806F500A46A31 /* MPWIntArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPWIntArray.m; sourceTree = ""; }; 37 | 1F8D7A941828070D00A46A31 /* MPWIntArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPWIntArray.h; sourceTree = ""; }; 38 | 1F8D7A971828075B00A46A31 /* StringTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StringTable.m; path = ../StringTable.m; sourceTree = ""; }; 39 | 1FA6DA691829486A00FE362E /* MPWBinaryPlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPWBinaryPlist.h; sourceTree = ""; }; 40 | 1FA6DA6A1829486A00FE362E /* MPWBinaryPlist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPWBinaryPlist.m; sourceTree = ""; }; 41 | 1FA6DA6C182948A800FE362E /* AccessorMacros.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AccessorMacros.h; sourceTree = ""; }; 42 | 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 43 | 2899E5210DE3E06400AC0155 /* ViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ViewController.xib; sourceTree = ""; }; 44 | 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; 45 | 28D7ACF60DDB3853001CB0EB /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 46 | 28D7ACF70DDB3853001CB0EB /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 47 | 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 48 | 32CA4F630368D1EE00C91783 /* DictTest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DictTest_Prefix.pch; sourceTree = ""; }; 49 | 3B28463B0F951E5600CF8FA4 /* dictionary.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dictionary.txt; sourceTree = ""; }; 50 | 3B28463C0F951E5600CF8FA4 /* dictionary_xml.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = dictionary_xml.plist; sourceTree = ""; }; 51 | 3B28463D0F951E5600CF8FA4 /* dictionary_bin.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = dictionary_bin.plist; sourceTree = ""; }; 52 | 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | /* End PBXFileReference section */ 54 | 55 | /* Begin PBXFrameworksBuildPhase section */ 56 | 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 61 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 62 | 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 080E96DDFE201D6D7F000001 /* Classes */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 1FA6DA6C182948A800FE362E /* AccessorMacros.h */, 73 | 1F21BF5A17E083FF003266F7 /* SimpleStdioStringDict.h */, 74 | 1F21BF5B17E083FF003266F7 /* SimpleStdioStringDict.m */, 75 | 1F7BBD400F968D6000DD49DC /* StringTable.h */, 76 | 1F8D7A971828075B00A46A31 /* StringTable.m */, 77 | 1D3623240D0F684500981E51 /* AppDelegate.h */, 78 | 1D3623250D0F684500981E51 /* AppDelegate.m */, 79 | 28D7ACF60DDB3853001CB0EB /* ViewController.h */, 80 | 28D7ACF70DDB3853001CB0EB /* ViewController.m */, 81 | 1F8D7A941828070D00A46A31 /* MPWIntArray.h */, 82 | 1F8D7A92182806F500A46A31 /* MPWIntArray.m */, 83 | 1FA6DA691829486A00FE362E /* MPWBinaryPlist.h */, 84 | 1FA6DA6A1829486A00FE362E /* MPWBinaryPlist.m */, 85 | ); 86 | path = Classes; 87 | sourceTree = ""; 88 | }; 89 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 1D6058910D05DD3D006BFB54 /* DictTest.app */, 93 | ); 94 | name = Products; 95 | sourceTree = ""; 96 | }; 97 | 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 080E96DDFE201D6D7F000001 /* Classes */, 101 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 102 | 29B97317FDCFA39411CA2CEA /* Resources */, 103 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 104 | 19C28FACFE9D520D11CA2CBB /* Products */, 105 | ); 106 | name = CustomTemplate; 107 | sourceTree = ""; 108 | }; 109 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 32CA4F630368D1EE00C91783 /* DictTest_Prefix.pch */, 113 | 29B97316FDCFA39411CA2CEA /* main.m */, 114 | ); 115 | name = "Other Sources"; 116 | sourceTree = ""; 117 | }; 118 | 29B97317FDCFA39411CA2CEA /* Resources */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 3B28463B0F951E5600CF8FA4 /* dictionary.txt */, 122 | 3B28463C0F951E5600CF8FA4 /* dictionary_xml.plist */, 123 | 3B28463D0F951E5600CF8FA4 /* dictionary_bin.plist */, 124 | 2899E5210DE3E06400AC0155 /* ViewController.xib */, 125 | 28AD733E0D9D9553002E5188 /* MainWindow.xib */, 126 | 8D1107310486CEB800E47090 /* Info.plist */, 127 | ); 128 | name = Resources; 129 | sourceTree = ""; 130 | }; 131 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 135 | 1D30AB110D05D00D00671497 /* Foundation.framework */, 136 | 288765A40DF7441C002DB57D /* CoreGraphics.framework */, 137 | ); 138 | name = Frameworks; 139 | sourceTree = ""; 140 | }; 141 | /* End PBXGroup section */ 142 | 143 | /* Begin PBXNativeTarget section */ 144 | 1D6058900D05DD3D006BFB54 /* DictTest */ = { 145 | isa = PBXNativeTarget; 146 | buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "DictTest" */; 147 | buildPhases = ( 148 | 1D60588D0D05DD3D006BFB54 /* Resources */, 149 | 1D60588E0D05DD3D006BFB54 /* Sources */, 150 | 1D60588F0D05DD3D006BFB54 /* Frameworks */, 151 | ); 152 | buildRules = ( 153 | ); 154 | dependencies = ( 155 | ); 156 | name = DictTest; 157 | productName = DictTest; 158 | productReference = 1D6058910D05DD3D006BFB54 /* DictTest.app */; 159 | productType = "com.apple.product-type.application"; 160 | }; 161 | /* End PBXNativeTarget section */ 162 | 163 | /* Begin PBXProject section */ 164 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 165 | isa = PBXProject; 166 | attributes = { 167 | }; 168 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DictTest" */; 169 | compatibilityVersion = "Xcode 3.1"; 170 | developmentRegion = English; 171 | hasScannedForEncodings = 1; 172 | knownRegions = ( 173 | en, 174 | ); 175 | mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; 176 | projectDirPath = ""; 177 | projectRoot = ""; 178 | targets = ( 179 | 1D6058900D05DD3D006BFB54 /* DictTest */, 180 | ); 181 | }; 182 | /* End PBXProject section */ 183 | 184 | /* Begin PBXResourcesBuildPhase section */ 185 | 1D60588D0D05DD3D006BFB54 /* Resources */ = { 186 | isa = PBXResourcesBuildPhase; 187 | buildActionMask = 2147483647; 188 | files = ( 189 | 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, 190 | 2899E5220DE3E06400AC0155 /* ViewController.xib in Resources */, 191 | 3B28463E0F951E5600CF8FA4 /* dictionary.txt in Resources */, 192 | 3B28463F0F951E5600CF8FA4 /* dictionary_xml.plist in Resources */, 193 | 3B2846400F951E5600CF8FA4 /* dictionary_bin.plist in Resources */, 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | }; 197 | /* End PBXResourcesBuildPhase section */ 198 | 199 | /* Begin PBXSourcesBuildPhase section */ 200 | 1D60588E0D05DD3D006BFB54 /* Sources */ = { 201 | isa = PBXSourcesBuildPhase; 202 | buildActionMask = 2147483647; 203 | files = ( 204 | 1FA6DA6B1829486A00FE362E /* MPWBinaryPlist.m in Sources */, 205 | 1F21BF5C17E083FF003266F7 /* SimpleStdioStringDict.m in Sources */, 206 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */, 207 | 1F8D7A93182806F500A46A31 /* MPWIntArray.m in Sources */, 208 | 1D3623260D0F684500981E51 /* AppDelegate.m in Sources */, 209 | 28D7ACF80DDB3853001CB0EB /* ViewController.m in Sources */, 210 | 1F8D7A981828075B00A46A31 /* StringTable.m in Sources */, 211 | ); 212 | runOnlyForDeploymentPostprocessing = 0; 213 | }; 214 | /* End PBXSourcesBuildPhase section */ 215 | 216 | /* Begin XCBuildConfiguration section */ 217 | 1D6058940D05DD3E006BFB54 /* Debug */ = { 218 | isa = XCBuildConfiguration; 219 | buildSettings = { 220 | ALWAYS_SEARCH_USER_PATHS = NO; 221 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 222 | COPY_PHASE_STRIP = NO; 223 | GCC_DYNAMIC_NO_PIC = NO; 224 | GCC_OPTIMIZATION_LEVEL = 0; 225 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 226 | GCC_PREFIX_HEADER = DictTest_Prefix.pch; 227 | INFOPLIST_FILE = Info.plist; 228 | ONLY_ACTIVE_ARCH = NO; 229 | PRODUCT_NAME = DictTest; 230 | SDKROOT = iphoneos; 231 | VALID_ARCHS = "arm64 armv7 armv7s x86_64"; 232 | }; 233 | name = Debug; 234 | }; 235 | 1D6058950D05DD3E006BFB54 /* Release */ = { 236 | isa = XCBuildConfiguration; 237 | buildSettings = { 238 | ALWAYS_SEARCH_USER_PATHS = NO; 239 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 240 | COPY_PHASE_STRIP = YES; 241 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 242 | GCC_PREFIX_HEADER = DictTest_Prefix.pch; 243 | INFOPLIST_FILE = Info.plist; 244 | ONLY_ACTIVE_ARCH = NO; 245 | PRODUCT_NAME = DictTest; 246 | SDKROOT = iphoneos; 247 | VALID_ARCHS = "arm64 armv7 armv7s x86_64"; 248 | }; 249 | name = Release; 250 | }; 251 | C01FCF4F08A954540054247B /* Debug */ = { 252 | isa = XCBuildConfiguration; 253 | buildSettings = { 254 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 255 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 256 | GCC_C_LANGUAGE_STANDARD = c99; 257 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 258 | GCC_WARN_UNUSED_VARIABLE = YES; 259 | ONLY_ACTIVE_ARCH = YES; 260 | PREBINDING = NO; 261 | SDKROOT = iphoneos2.2.1; 262 | }; 263 | name = Debug; 264 | }; 265 | C01FCF5008A954540054247B /* Release */ = { 266 | isa = XCBuildConfiguration; 267 | buildSettings = { 268 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 269 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 270 | GCC_C_LANGUAGE_STANDARD = c99; 271 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 272 | GCC_WARN_UNUSED_VARIABLE = YES; 273 | PREBINDING = NO; 274 | SDKROOT = iphoneos2.2.1; 275 | }; 276 | name = Release; 277 | }; 278 | /* End XCBuildConfiguration section */ 279 | 280 | /* Begin XCConfigurationList section */ 281 | 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "DictTest" */ = { 282 | isa = XCConfigurationList; 283 | buildConfigurations = ( 284 | 1D6058940D05DD3E006BFB54 /* Debug */, 285 | 1D6058950D05DD3E006BFB54 /* Release */, 286 | ); 287 | defaultConfigurationIsVisible = 0; 288 | defaultConfigurationName = Release; 289 | }; 290 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DictTest" */ = { 291 | isa = XCConfigurationList; 292 | buildConfigurations = ( 293 | C01FCF4F08A954540054247B /* Debug */, 294 | C01FCF5008A954540054247B /* Release */, 295 | ); 296 | defaultConfigurationIsVisible = 0; 297 | defaultConfigurationName = Release; 298 | }; 299 | /* End XCConfigurationList section */ 300 | }; 301 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 302 | } 303 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/DictTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/DictTest.xcodeproj/project.xcworkspace/xcuserdata/marcel.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpw/iOS-macOS-performance/2ff95f54e8278df3fd51016f0339cffb44f55824/Chapter-13/DictTest/DictTest.xcodeproj/project.xcworkspace/xcuserdata/marcel.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Chapter-13/DictTest/DictTest.xcodeproj/project.xcworkspace/xcuserdata/marcel.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/DictTest.xcodeproj/wlt.pbxuser: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | 1D6058900D05DD3D006BFB54 /* DictTest */ = { 4 | activeExec = 0; 5 | executables = ( 6 | 3B2846260F951D7F00CF8FA4 /* DictTest */, 7 | ); 8 | }; 9 | 28D7ACF70DDB3853001CB0EB /* ViewController.m */ = { 10 | uiCtxt = { 11 | sepNavIntBoundsRect = "{{0, 0}, {565, 2745}}"; 12 | sepNavSelRange = "{4792, 0}"; 13 | sepNavVisRange = "{708, 259}"; 14 | }; 15 | }; 16 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 17 | activeBuildConfigurationName = Release; 18 | activeExecutable = 3B2846260F951D7F00CF8FA4 /* DictTest */; 19 | activeTarget = 1D6058900D05DD3D006BFB54 /* DictTest */; 20 | addToTargets = ( 21 | 1D6058900D05DD3D006BFB54 /* DictTest */, 22 | ); 23 | codeSenseManager = 3B28462F0F951D9B00CF8FA4 /* Code sense */; 24 | executables = ( 25 | 3B2846260F951D7F00CF8FA4 /* DictTest */, 26 | ); 27 | perUserDictionary = { 28 | PBXPerProjectTemplateStateSaveDate = 261430825; 29 | PBXWorkspaceStateSaveDate = 261430825; 30 | }; 31 | sourceControlManager = 3B28462E0F951D9B00CF8FA4 /* Source Control */; 32 | userBuildSettings = { 33 | }; 34 | }; 35 | 3B2846260F951D7F00CF8FA4 /* DictTest */ = { 36 | isa = PBXExecutable; 37 | activeArgIndices = ( 38 | ); 39 | argumentStrings = ( 40 | ); 41 | autoAttachOnCrash = 1; 42 | breakpointsEnabled = 0; 43 | configStateDict = { 44 | }; 45 | customDataFormattersEnabled = 1; 46 | debuggerPlugin = GDBDebugging; 47 | disassemblyDisplayState = 0; 48 | dylibVariantSuffix = ""; 49 | enableDebugStr = 1; 50 | environmentEntries = ( 51 | ); 52 | executableSystemSymbolLevel = 0; 53 | executableUserSymbolLevel = 0; 54 | libgmallocEnabled = 0; 55 | name = DictTest; 56 | sourceDirectories = ( 57 | ); 58 | }; 59 | 3B28462E0F951D9B00CF8FA4 /* Source Control */ = { 60 | isa = PBXSourceControlManager; 61 | fallbackIsa = XCSourceControlManager; 62 | isSCMEnabled = 0; 63 | scmConfiguration = { 64 | }; 65 | }; 66 | 3B28462F0F951D9B00CF8FA4 /* Code sense */ = { 67 | isa = PBXCodeSenseManager; 68 | indexTemplatePath = ""; 69 | }; 70 | } 71 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/DictTest.xcodeproj/xcuserdata/marcel.xcuserdatad/xcschemes/DictTest.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/DictTest.xcodeproj/xcuserdata/marcel.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DictTest.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1D6058900D05DD3D006BFB54 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/DictTest_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'DictTest' 3 | // target in the 'DictTest' project 4 | // 5 | 6 | #ifdef __OBJC__ 7 | #import 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | com.metaobject.dictTest 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | NSMainNibFile 28 | MainWindow 29 | 30 | 31 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/MainWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 528 5 | 9E17 6 | 672 7 | 949.33 8 | 352.00 9 | 10 | YES 11 | 12 | 13 | 14 | YES 15 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 16 | 17 | 18 | YES 19 | 20 | IBFilesOwner 21 | 22 | 23 | IBFirstResponder 24 | 25 | 26 | 27 | ViewController 28 | 29 | 30 | 31 | 32 | 292 33 | {320, 480} 34 | 35 | 1 36 | MSAxIDEAA 37 | 38 | NO 39 | NO 40 | 41 | 42 | 43 | 44 | 45 | YES 46 | 47 | 48 | delegate 49 | 50 | 51 | 52 | 4 53 | 54 | 55 | 56 | viewController 57 | 58 | 59 | 60 | 11 61 | 62 | 63 | 64 | window 65 | 66 | 67 | 68 | 14 69 | 70 | 71 | 72 | 73 | YES 74 | 75 | 0 76 | 77 | YES 78 | 79 | 80 | 81 | 82 | 83 | -1 84 | 85 | 86 | RmlsZSdzIE93bmVyA 87 | 88 | 89 | 3 90 | 91 | 92 | DictTest App Delegate 93 | 94 | 95 | -2 96 | 97 | 98 | 99 | 100 | 10 101 | 102 | 103 | 104 | 105 | 12 106 | 107 | 108 | 109 | 110 | 111 | 112 | YES 113 | 114 | YES 115 | -1.CustomClassName 116 | -2.CustomClassName 117 | 10.CustomClassName 118 | 10.IBEditorWindowLastContentRect 119 | 10.IBPluginDependency 120 | 12.IBEditorWindowLastContentRect 121 | 12.IBPluginDependency 122 | 3.CustomClassName 123 | 3.IBPluginDependency 124 | 125 | 126 | YES 127 | UIApplication 128 | UIResponder 129 | ViewController 130 | {{512, 351}, {320, 480}} 131 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 132 | {{525, 346}, {320, 480}} 133 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 134 | AppDelegate 135 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 136 | 137 | 138 | 139 | YES 140 | 141 | YES 142 | 143 | 144 | YES 145 | 146 | 147 | 148 | 149 | YES 150 | 151 | YES 152 | 153 | 154 | YES 155 | 156 | 157 | 158 | 14 159 | 160 | 161 | 162 | YES 163 | 164 | AppDelegate 165 | NSObject 166 | 167 | YES 168 | 169 | YES 170 | viewController 171 | window 172 | 173 | 174 | YES 175 | ViewController 176 | UIWindow 177 | 178 | 179 | 180 | IBProjectSource 181 | Classes/AppDelegate.h 182 | 183 | 184 | 185 | AppDelegate 186 | NSObject 187 | 188 | IBUserSource 189 | 190 | 191 | 192 | 193 | ViewController 194 | UIViewController 195 | 196 | IBProjectSource 197 | Classes/ViewController.h 198 | 199 | 200 | 201 | 202 | 0 203 | DictTest.xcodeproj 204 | 3 205 | 206 | 207 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/Picture 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpw/iOS-macOS-performance/2ff95f54e8278df3fd51016f0339cffb44f55824/Chapter-13/DictTest/Picture 1.png -------------------------------------------------------------------------------- /Chapter-13/DictTest/SimpleStdioStringDict.h: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleStdioStringDict.h 3 | // DictTest 4 | // 5 | // Created by Marcel Weiher on 9/11/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface SimpleStdioStringDict : NSObject 12 | { 13 | char **strings; 14 | int capacity; 15 | int count; 16 | } 17 | -initWithContentsOfFile:(NSString*)filename ; 18 | -(int)count; 19 | -(BOOL)containsString:(NSString*)str; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/SimpleStdioStringDict.m: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleStdioStringDict.m 3 | // DictTest 4 | // 5 | // Created by Marcel Weiher on 9/11/13. 6 | // 7 | // 8 | 9 | #import "SimpleStdioStringDict.h" 10 | 11 | @implementation SimpleStdioStringDict 12 | 13 | -(void)_realloc 14 | { 15 | if ( count+2 >= capacity) { 16 | capacity=(capacity+10)*2; 17 | strings=realloc(strings, (capacity+2) * sizeof *strings); 18 | } 19 | } 20 | 21 | 22 | -initWithContentsOfFile1:(NSString*)filename 23 | { 24 | self=[super init]; 25 | const char *fname=[filename UTF8String]; 26 | FILE *f=fopen(fname, "r"); 27 | BOOL done=NO; 28 | if (f) { 29 | while (!done) { 30 | char buffer[8192]; 31 | [self _realloc]; 32 | char *line=fgets(buffer, 8000, f); 33 | if (line) { 34 | int len=(int)strlen(line); 35 | if (len>0) { 36 | len--; 37 | line[len]=0; 38 | strings[count++]=strdup(line); 39 | continue; 40 | } 41 | } 42 | done=YES; 43 | } 44 | fclose(f); 45 | } 46 | return self; 47 | } 48 | 49 | 50 | -initWithContentsOfFile:(NSString*)filename 51 | { 52 | self=[super init]; 53 | const char *fname=[filename UTF8String]; 54 | FILE *f=fopen(fname, "r"); 55 | if (f) { 56 | char *line; 57 | size_t lineLength; 58 | while ( (line=fgetln(f, &lineLength))) { 59 | [self _realloc]; 60 | strings[count++]=strndup(line,lineLength); 61 | } 62 | fclose(f); 63 | } 64 | return self; 65 | } 66 | 67 | 68 | -(int)count 69 | { 70 | return count; 71 | } 72 | 73 | -(BOOL)containsString:(NSString*)str 74 | { 75 | int maxLen=(int)[str length]; 76 | char buffer[ maxLen + 10 ]; 77 | [str getBytes:buffer maxLength:maxLen+1 usedLength:NULL encoding:NSASCIIStringEncoding options:0 range:NSMakeRange(0, maxLen) remainingRange:NULL]; 78 | buffer[maxLen]=0; 79 | void *result = bsearch_b((const void*)buffer, (const void*)strings, count, sizeof *strings , ^( const void *key, const void *elemptr){ 80 | const char *elem=*(const char**)elemptr; 81 | return strcasecmp(key,elem ); 82 | } ); 83 | return result != NULL; 84 | } 85 | 86 | 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/StringTable.h: -------------------------------------------------------------------------------- 1 | // 2 | // StringTable 3 | // DictTest 4 | // 5 | // Created by Marcel Weiher on 4/15/09. 6 | // Copyright 2009 Livescribe. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface StringTable : NSObject 13 | 14 | -initWithContentsOfFile:(NSString*)filename ; 15 | -(int)count; 16 | -(BOOL)containsString:(NSString*)str; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/StringTable.m: -------------------------------------------------------------------------------- 1 | // 2 | // StringTable.m 3 | // DictTest 4 | // 5 | // Created by Marcel Weiher on 4/15/09. 6 | // Copyright 2009 Livescribe. All rights reserved. 7 | // 8 | 9 | #import "StringTable.h" 10 | #import "MPWIntArray.h" 11 | 12 | @implementation StringTable { 13 | NSData *stringFileContents; 14 | MPWIntArray *offsets; 15 | } 16 | 17 | 18 | -(void)tokenizeWords 19 | { 20 | const char *bytes =[stringFileContents bytes]; 21 | const char *cur =bytes; 22 | const char *end=bytes + [stringFileContents length]; 23 | [offsets addInteger:0]; 24 | while ( cur < end ) { 25 | if ( *cur == '\n' ) { 26 | [offsets addInteger:(int)(cur-bytes+1)]; 27 | } 28 | cur++; 29 | } 30 | [offsets addInteger:(int)(end-bytes)]; 31 | } 32 | 33 | -initWithContentsOfFile:(NSString*)filename 34 | { 35 | if ( (self=[super init] ) ) { 36 | offsets=[[MPWIntArray alloc] init]; 37 | stringFileContents=[[NSData alloc] initWithContentsOfMappedFile:filename]; 38 | [self tokenizeWords]; 39 | } 40 | return self; 41 | } 42 | 43 | -(BOOL)containsString:(NSString*)str 44 | { 45 | const char *bytes =[stringFileContents bytes]; 46 | const char *searchStr=[str UTF8String]; 47 | long maxLen=[str length]; 48 | int *offsetsp=[offsets integers]; 49 | int max=[self count]; 50 | for (int i=0;i 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 38 | 45 | 52 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 119 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /Chapter-13/DictTest/dictionary_bin.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpw/iOS-macOS-performance/2ff95f54e8278df3fd51016f0339cffb44f55824/Chapter-13/DictTest/dictionary_bin.plist -------------------------------------------------------------------------------- /Chapter-13/DictTest/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // DictTest 4 | // 5 | // Created by Wagner Truppel on 4/14/09. 6 | // Copyright Wagner Truppel 2009. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char* argv[]) 12 | { 13 | NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 14 | int retVal = UIApplicationMain(argc, argv, nil, nil); 15 | [pool release]; 16 | return retVal; 17 | } 18 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench.xcodeproj/project.xcworkspace/xcshareddata/GLBench.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | AD59AE59-E5AD-45B7-BF52-EDC1F97EDDC5 9 | IDESourceControlProjectName 10 | GLBench 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 2BC61B30-D5A3-46AC-81CD-1AC94372C64C 14 | ssh://github.com/mpw/cocoa-optimization.git 15 | 16 | IDESourceControlProjectPath 17 | test-programs/GLBench/GLBench.xcodeproj/project.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 2BC61B30-D5A3-46AC-81CD-1AC94372C64C 21 | ../../../.. 22 | 23 | IDESourceControlProjectURL 24 | ssh://github.com/mpw/cocoa-optimization.git 25 | IDESourceControlProjectVersion 26 | 110 27 | IDESourceControlProjectWCCIdentifier 28 | 2BC61B30-D5A3-46AC-81CD-1AC94372C64C 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 2BC61B30-D5A3-46AC-81CD-1AC94372C64C 36 | IDESourceControlWCCName 37 | CocoaOptimizationBook 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench.xcodeproj/project.xcworkspace/xcuserdata/marcel.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpw/iOS-macOS-performance/2ff95f54e8278df3fd51016f0339cffb44f55824/Chapter-14/GLBench/GLBench.xcodeproj/project.xcworkspace/xcuserdata/marcel.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench.xcodeproj/xcuserdata/marcel.xcuserdatad/xcschemes/GLBench.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench.xcodeproj/xcuserdata/marcel.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | GLBench.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1F60513F18788A58004B6AED 16 | 17 | primary 18 | 19 | 20 | 1F60516018788A59004B6AED 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench/GLBench-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.metaobject.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2014 mo. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench/GLBench-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench/GLBenchView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GLBenchView.h 3 | // Cocoa OpenGL 4 | // 5 | // Created by Marcel Weiher on 1/1/14. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface GLBenchView : NSOpenGLView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench/GLBenchView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GLBenchView.m 3 | // Cocoa OpenGL 4 | // 5 | // Created by Marcel Weiher on 1/1/14. 6 | // 7 | // 8 | 9 | #import "GLBenchView.h" 10 | #import 11 | #import 12 | #import 13 | 14 | 15 | //#import 16 | //#import 17 | 18 | @implementation GLBenchView 19 | 20 | 21 | 22 | // pixel format definition 23 | + (NSOpenGLPixelFormat*) basicPixelFormat1 24 | { 25 | NSOpenGLPixelFormatAttribute attributes [] = { 26 | NSOpenGLPFAWindow, 27 | NSOpenGLPFADoubleBuffer, // double buffered 28 | NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)16, // 16 bit depth buffer 29 | (NSOpenGLPixelFormatAttribute)nil 30 | }; 31 | return [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; 32 | } 33 | 34 | 35 | -(id) initWithFrame: (NSRect) frameRect 36 | { 37 | self = [super initWithFrame: frameRect]; 38 | [self setWantsBestResolutionOpenGLSurface:YES]; 39 | return self; 40 | } 41 | 42 | - (void) resizeGL 43 | { 44 | NSRect viewRect = [self convertRectToBacking:[self bounds]]; 45 | glViewport (0, 0, viewRect.size.width, viewRect.size.width); 46 | } 47 | 48 | 49 | -(void)drawOn1:(id )aContext inRect:(NSRect)dirtyRect 50 | { 51 | int iterations=10000; 52 | NSLog(@"self: %@",self); 53 | CGContextRef context=[[NSGraphicsContext currentContext] graphicsPort]; 54 | CGContextSetRGBFillColor(context, 1.0,0.5,0.5,1.0 ); 55 | CGContextAddRect( context, dirtyRect); 56 | CGContextFillPath( context ); 57 | CGContextScaleCTM( context, [self frame].size.width,[self frame].size.height ); 58 | CGContextTranslateCTM( context, 0.25 , 0.5); 59 | CGContextScaleCTM( context,0.2, 0.2); 60 | 61 | for (int i=0;i)aContext inRect:(NSRect)dirtyRect 75 | { 76 | NSLog(@"draw"); 77 | int iterations=10000; 78 | [aContext ingsave:^(id aContext) { 79 | [aContext setFillColor:[aContext colorRed:1.0 green:0.5 blue:0.5 alpha:1.0]]; 80 | // [[aContext nsrect:dirtyRect] fill]; 81 | 82 | [aContext scale:[self frame].size.width :[self frame].size.height]; 83 | [aContext translate:0.1 :0.25]; 84 | [aContext scale:0.4 :0.7]; 85 | 86 | for (int i=0;i 10 | 11 | @interface MPWAppDelegate : NSObject 12 | 13 | @property (assign) IBOutlet NSWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench/MPWAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPWAppDelegate.m 3 | // GLBench 4 | // 5 | // Created by Marcel Weiher on 1/4/14. 6 | // Copyright (c) 2014 mo. All rights reserved. 7 | // 8 | 9 | #import "MPWAppDelegate.h" 10 | 11 | @implementation MPWAppDelegate 12 | 13 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 14 | { 15 | // Insert code here to initialize your application 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBench/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // GLBench 4 | // 5 | // Created by Marcel Weiher on 1/4/14. 6 | // Copyright (c) 2014 mo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) 12 | { 13 | return NSApplicationMain(argc, argv); 14 | } 15 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBenchTests/GLBenchTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.metaobject.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBenchTests/GLBenchTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // GLBenchTests.m 3 | // GLBenchTests 4 | // 5 | // Created by Marcel Weiher on 1/4/14. 6 | // Copyright (c) 2014 mo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GLBenchTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation GLBenchTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Chapter-14/GLBench/GLBenchTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Chapter-14/letter-a-with-control-points.eps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-3.0 EPSF-1.2 2 | %%BoundingBox: 0 0 1100 415 3 | %%EndComments 4 | 0.7 dup scale 5 | /Times-Roman 1090 selectfont 6 | 20 dup translate 7 | 7 setflat 8 | gsave 9 | 0 40 moveto 10 | 0 setgray 11 | 1 setlinewidth 12 | (a) false charpath 13 | gsave 14 | stroke 15 | grestore 16 | 1 setlinewidth 17 | 18 | 0 setgray 19 | /drawBoxAtCurrentPoint 20 | { 21 | gsave 22 | translate 23 | 0 0 0.7 setrgbcolor 24 | -3 -3 6 6 rectstroke 25 | grestore 26 | } bind def 27 | /fillBoxAtCurrentPoint 28 | { 29 | gsave 30 | translate 31 | 0.8 0 0 setrgbcolor 32 | 0.5 setlinewidth 33 | 0 0 4 0 360 arc stroke 34 | grestore 35 | } bind def 36 | 37 | /drawBoxAndMove 38 | { 39 | 2 copy 40 | drawBoxAtCurrentPoint 41 | moveto 42 | } bind def 43 | 44 | 45 | /drawControlPoint 46 | { 47 | 2 copy 48 | gsave 49 | 0.2 setgray 50 | [ 1 0 ] 0 setdash 51 | drawFilledBoxAtCurrentPoint 52 | grestore 53 | moveto 54 | } bind def 55 | 56 | { drawBoxAndMove } 57 | { drawBoxAndMove } 58 | { 59 | 6 dict begin 60 | currentpoint 61 | /oy exch def 62 | /ox exch def 63 | /fy exch def 64 | /fx exch def 65 | /c2y exch def 66 | /c2x exch def 67 | /c1y exch def 68 | /c1x exch def 69 | 70 | fx fy drawBoxAndMove 71 | ox oy moveto c1x c1y lineto stroke 72 | fx fy moveto c2x c2y lineto stroke 73 | c1x c1y fillBoxAtCurrentPoint 74 | c2x c2y fillBoxAtCurrentPoint 75 | fx fy moveto 76 | 77 | end 78 | } 79 | { } 80 | pathforall 81 | 82 | grestore 83 | 500 0 translate 84 | gsave 85 | 0 40 moveto 86 | 4 setflat 87 | 88 | (a) false charpath flattenpath 89 | gsave stroke grestore 90 | 91 | { drawBoxAndMove } 92 | { drawBoxAndMove } 93 | { } 94 | { } 95 | pathforall 96 | grestore 97 | 500 0 translate 98 | 30 40 moveto 99 | 0.15 setlinewidth 100 | 101 | /rectintersectscurrentclip 102 | { 103 | 4 { pop } repeat 104 | } bind def 105 | 106 | /grid { 107 | 5 dict begin 108 | /op exch def 109 | /ymax exch def 110 | /xmax exch def 111 | /step exch def 112 | 0 step ymax { 113 | /y exch def 114 | 0 step xmax { 115 | /x exch def 116 | x y step step op load exec 117 | } for 118 | } for 119 | end 120 | } bind def 121 | 122 | 10 520 570 /rectstroke grid 123 | 124 | 30 40 moveto 125 | 2 setlinewidth 126 | (a) false charpath gsave stroke grestore 127 | clip 128 | 129 | 130 | 131 | /insetrectfill { 132 | 4 dict begin 133 | /h exch def 134 | /w exch def 135 | /y exch def 136 | /x exch def 137 | x 1 add y 1 add w 2 sub h 2 sub rectfill 138 | end 139 | } bind def 140 | 141 | 142 | 0.7 setgray 143 | 10 520 570 /insetrectfill grid 144 | 145 | 146 | showpage 147 | 148 | -------------------------------------------------------------------------------- /Chapter-16/screen-refresh.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | 3 | class AppController: NSObject, NSApplicationDelegate { 4 | var mainWindow: NSWindow? 5 | let rect = NSMakeRect(200, 400, 820, 500) 6 | 7 | func applicationDidFinishLaunching(aNotification: NSNotification) { 8 | print(rect) 9 | let window = NSWindow(contentRect: rect, 10 | styleMask: NSTitledWindowMask | NSClosableWindowMask, 11 | backing: NSBackingStoreType.Buffered, 12 | defer: false) 13 | window.orderFrontRegardless() 14 | self.mainWindow = window 15 | NSApp.activateIgnoringOtherApps(true) 16 | redrawALot() 17 | } 18 | func redrawALot() { 19 | for _ in 1...600 { 20 | let window=self.mainWindow! 21 | window.contentView!.lockFocus() 22 | NSColor.whiteColor().set() 23 | NSBezierPath.fillRect(rect) 24 | NSColor.blackColor().set() 25 | "Iteration".drawAtPoint( NSPoint(x:10, y:10), withAttributes: nil) 26 | window.contentView!.unlockFocus() 27 | window.flushWindow() 28 | sleep(1) 29 | NSLog("flush") 30 | } 31 | NSApp.terminate( true ) 32 | } 33 | 34 | func applicationShouldTerminateAfterLastWindowClosed(app: NSApplication) -> Bool { 35 | return true 36 | } 37 | } 38 | 39 | NSApplication.sharedApplication() 40 | NSApp.setActivationPolicy(.Regular) 41 | 42 | let controller = AppController() 43 | NSApp.delegate = controller 44 | 45 | NSApp.run() 46 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 2 | iOS and macOS Performance 3 | ------------------------ 4 | 5 | Welcome to the code repository for [*iOS and macOS Performance Tuning: Cocoa, Cocoa Touch, Objective-C, and Swift*](https://www.pearsonhighered.com/program/Weiher-i-OS-and-mac-OS-Performance-Tuning-Cocoa-Cocoa-Touch-Objective-C-and-Swift/PGM161424.html). 6 | 7 | 8 | Cover 9 | 10 | Performance tricks and samples Chapter 3 are primarily from MPWFoundation: 11 | 12 | - [MPWFoundation](https://github.com/mpw/MPWFoundation) 13 | 14 | 15 | 16 | 17 | 18 | ### Chapter 1 19 | 20 | 21 | 22 | ### Chapter 4 23 | 24 | The XML parser described is available at [https://github.com/mpw/Objective-XML](https://github.com/mpw/Objective-XML). 25 | 26 | ### Chapter 17 27 | 28 | The JPJP fork of the JPNG file format can be found here: [https://github.com/mpw/JPNG](https://github.com/mpw/JPNG). 29 | 30 | 31 | 32 | --------------------------------------------------------------------------------