CollectionUtils.m
author Jens Alfke <jens@mooseyard.com>
Sat May 24 13:24:33 2008 -0700 (2008-05-24)
changeset 11 e5976864dfe9
parent 9 823e7e74088e
child 29 8874aff14cc9
permissions -rw-r--r--
* Added BSD license to more .m files.
* Updated some copyright notices.
* Added some #imports to make the MYNetwork classes build without using the MYUtilities.pch prefix header.
     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 }
   270 
   271 
   272 /*
   273  Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
   274  
   275  Redistribution and use in source and binary forms, with or without modification, are permitted
   276  provided that the following conditions are met:
   277  
   278  * Redistributions of source code must retain the above copyright notice, this list of conditions
   279  and the following disclaimer.
   280  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   281  and the following disclaimer in the documentation and/or other materials provided with the
   282  distribution.
   283  
   284  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
   285  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
   286  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
   287  BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   288  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
   289   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   290  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
   291  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   292  */