CollectionUtils.m
author Jens Alfke <jens@mooseyard.com>
Tue May 20 17:40:28 2008 -0700 (2008-05-20)
changeset 10 82a37ccf6b8c
parent 8 5588347dfcbd
child 11 e5976864dfe9
permissions -rw-r--r--
Split ExceptionUtils out of Test.
     1 //
     2 //  CollectionUtils.m
     3 //  MYUtilities
     4 //
     5 //  Created by Jens Alfke on 1/5/08.
     6 //  Copyright 2008 Jens Alfke. All rights reserved.
     7 //
     8 
     9 #import "CollectionUtils.h"
    10 #import "Test.h"
    11 
    12 
    13 NSDictionary* _dictof(const struct _dictpair* pairs, size_t count)
    14 {
    15     CAssert(count<10000);
    16     id objects[count], keys[count];
    17     size_t n = 0;
    18     for( size_t i=0; i<count; i++,pairs++ ) {
    19         if( pairs->value ) {
    20             objects[n] = pairs->value;
    21             keys[n] = pairs->key;
    22             n++;
    23         }
    24     }
    25     return [NSDictionary dictionaryWithObjects: objects forKeys: keys count: n];
    26 }
    27 
    28 
    29 NSMutableDictionary* _mdictof(const struct _dictpair* pairs, size_t count)
    30 {
    31     CAssert(count<10000);
    32     id objects[count], keys[count];
    33     size_t n = 0;
    34     for( size_t i=0; i<count; i++,pairs++ ) {
    35         if( pairs->value ) {
    36             objects[n] = pairs->value;
    37             keys[n] = pairs->key;
    38             n++;
    39         }
    40     }
    41     return [NSMutableDictionary dictionaryWithObjects: objects forKeys: keys count: n];
    42 }
    43 
    44 
    45 NSArray* $apply( NSArray *src, SEL selector, id defaultValue )
    46 {
    47     NSMutableArray *dst = [NSMutableArray arrayWithCapacity: src.count];
    48     for( id obj in src ) {
    49         id result = [obj performSelector: selector] ?: defaultValue;
    50         [dst addObject: result];
    51     }
    52     return dst;
    53 }
    54 
    55 NSArray* $applyKeyPath( NSArray *src, NSString *keyPath, id defaultValue )
    56 {
    57     NSMutableArray *dst = [NSMutableArray arrayWithCapacity: src.count];
    58     for( id obj in src ) {
    59         id result = [obj valueForKeyPath: keyPath] ?: defaultValue;
    60         [dst addObject: result];
    61     }
    62     return dst;
    63 }
    64 
    65 
    66 BOOL $equal(id obj1, id obj2)      // Like -isEqual: but works even if either/both are nil
    67 {
    68     if( obj1 )
    69         return obj2 && [obj1 isEqual: obj2];
    70     else
    71         return obj2==nil;
    72 }
    73 
    74 
    75 NSValue* _box(const void *value, const char *encoding)
    76 {
    77     // file:///Developer/Documentation/DocSets/com.apple.ADC_Reference_Library.DeveloperTools.docset/Contents/Resources/Documents/documentation/DeveloperTools/gcc-4.0.1/gcc/Type-encoding.html
    78     char e = encoding[0];
    79     if( e=='r' )                // ignore 'const' modifier
    80         e = encoding[1];
    81     switch( e ) {
    82         case 'c':   return [NSNumber numberWithChar: *(char*)value];
    83         case 'C':   return [NSNumber numberWithUnsignedChar: *(char*)value];
    84         case 's':   return [NSNumber numberWithShort: *(short*)value];
    85         case 'S':   return [NSNumber numberWithUnsignedShort: *(unsigned short*)value];
    86         case 'i':   return [NSNumber numberWithInt: *(int*)value];
    87         case 'I':   return [NSNumber numberWithUnsignedInt: *(unsigned int*)value];
    88         case 'l':   return [NSNumber numberWithLong: *(long*)value];
    89         case 'L':   return [NSNumber numberWithUnsignedLong: *(unsigned long*)value];
    90         case 'q':   return [NSNumber numberWithLongLong: *(long long*)value];
    91         case 'Q':   return [NSNumber numberWithUnsignedLongLong: *(unsigned long long*)value];
    92         case 'f':   return [NSNumber numberWithFloat: *(float*)value];
    93         case 'd':   return [NSNumber numberWithDouble: *(double*)value];
    94         case '*':   return [NSString stringWithUTF8String: *(char**)value];
    95         case '@':   return *(id*)value;
    96         default:    return [NSValue value: value withObjCType: encoding];
    97     }
    98 }
    99 
   100 
   101 id _cast( Class requiredClass, id object )
   102 {
   103     if( object && ! [object isKindOfClass: requiredClass] )
   104         [NSException raise: NSInvalidArgumentException format: @"%@ required, but got %@ %p",
   105          requiredClass,[object class],object];
   106     return object;
   107 }
   108 
   109 id _castNotNil( Class requiredClass, id object )
   110 {
   111     if( ! [object isKindOfClass: requiredClass] )
   112         [NSException raise: NSInvalidArgumentException format: @"%@ required, but got %@ %p",
   113          requiredClass,[object class],object];
   114     return object;
   115 }
   116 
   117 id _castIf( Class requiredClass, id object )
   118 {
   119     if( object && ! [object isKindOfClass: requiredClass] )
   120         object = nil;
   121     return object;
   122 }
   123 
   124 NSArray* _castArrayOf(Class itemClass, NSArray *a)
   125 {
   126     id item;
   127     foreach( item, $cast(NSArray,a) )
   128         _cast(itemClass,item);
   129     return a;
   130 }
   131 
   132 
   133 void setObj( id *var, id value )
   134 {
   135     if( value != *var ) {
   136         [*var release];
   137         *var = [value retain];
   138     }
   139 }
   140 
   141 BOOL ifSetObj( id *var, id value )
   142 {
   143     if( value != *var && ![value isEqual: *var] ) {
   144         [*var release];
   145         *var = [value retain];
   146         return YES;
   147     } else {
   148         return NO;
   149     }
   150 }
   151 
   152 
   153 void setString( NSString **var, NSString *value )
   154 {
   155     if( value != *var ) {
   156         [*var release];
   157         *var = [value copy];
   158     }
   159 }
   160 
   161 
   162 BOOL ifSetString( NSString **var, NSString *value )
   163 {
   164     if( value != *var && ![value isEqualToString: *var] ) {
   165         [*var release];
   166         *var = [value copy];
   167         return YES;
   168     } else {
   169         return NO;
   170     }
   171 }
   172 
   173 
   174 NSString* $string( const char *utf8Str )
   175 {
   176     if( utf8Str )
   177         return [NSString stringWithCString: utf8Str encoding: NSUTF8StringEncoding];
   178     else
   179         return nil;
   180 }
   181 
   182 
   183 @implementation NSArray (MYUtils)
   184 
   185 - (BOOL) my_containsObjectIdenticalTo: (id)object
   186 {
   187     return [self indexOfObjectIdenticalTo: object] != NSNotFound;
   188 }
   189 
   190 @end
   191 
   192 
   193 
   194 
   195 @implementation NSSet (MYUtils)
   196 
   197 + (NSSet*) my_unionOfSet: (NSSet*)set1 andSet: (NSSet*)set2
   198 {
   199     if( set1 == set2 || set2.count==0 )
   200         return set1;
   201     else if( set1.count==0 )
   202         return set2;
   203     else {
   204         NSMutableSet *result = [set1 mutableCopy];
   205         [result unionSet: set2];
   206         return [result autorelease];
   207     }
   208 }
   209 
   210 + (NSSet*) my_intersectionOfSet: (NSSet*)set1 andSet: (NSSet*)set2
   211 {
   212     if( set1 == set2 || set1.count==0 )
   213         return set1;
   214     else if( set2.count==0 )
   215         return set2;
   216     else {
   217         NSMutableSet *result = [set1 mutableCopy];
   218         [result intersectSet: set2];
   219         return [result autorelease];
   220     }
   221 }
   222 
   223 + (NSSet*) my_differenceOfSet: (NSSet*)set1 andSet: (NSSet*)set2
   224 {
   225     if( set1.count==0 || set2.count==0 )
   226         return set1;
   227     else if( set1==set2 )
   228         return [NSSet set];
   229     else {
   230         NSMutableSet *result = [set1 mutableCopy];
   231         [result minusSet: set2];
   232         return [result autorelease];
   233     }
   234 }
   235 
   236 @end
   237 
   238 
   239 
   240 #import "Test.h"
   241 
   242 TestCase(CollectionUtils) {
   243     NSArray *a = $array(@"foo",@"bar",@"baz");
   244     //Log(@"a = %@",a);
   245     NSArray *aa = [NSArray arrayWithObjects: @"foo",@"bar",@"baz",nil];
   246     CAssertEqual(a,aa);
   247     
   248     const char *cstr = "a C string";
   249     id o = $object(cstr);
   250     //Log(@"o = %@",o);
   251     CAssertEqual(o,@"a C string");
   252     
   253     NSDictionary *d = $dict({@"int",    $object(1)},
   254                             {@"double", $object(-1.1)},
   255                             {@"char",   $object('x')},
   256                             {@"ulong",  $object(1234567UL)},
   257                             {@"longlong",$object(987654321LL)},
   258                             {@"cstr",   $object(cstr)});
   259     //Log(@"d = %@",d);
   260     NSDictionary *dd = [NSDictionary dictionaryWithObjectsAndKeys:
   261                         [NSNumber numberWithInt: 1],                    @"int",
   262                         [NSNumber numberWithDouble: -1.1],              @"double",
   263                         [NSNumber numberWithChar: 'x'],                 @"char",
   264                         [NSNumber numberWithUnsignedLong: 1234567UL],   @"ulong",
   265                         [NSNumber numberWithDouble: 987654321LL],       @"longlong",
   266                         @"a C string",                                  @"cstr",
   267                         nil];
   268     CAssertEqual(d,dd);
   269 }