jens@0: // jens@0: // CollectionUtils.m jens@0: // MYUtilities jens@0: // jens@0: // Created by Jens Alfke on 1/5/08. jens@0: // Copyright 2008 Jens Alfke. All rights reserved. jens@0: // jens@0: jens@0: #import "CollectionUtils.h" jens@0: #import "Test.h" jens@0: jens@0: jens@0: NSDictionary* _dictof(const struct _dictpair* pairs, size_t count) jens@0: { jens@0: CAssert(count<10000); jens@0: id objects[count], keys[count]; jens@0: size_t n = 0; jens@0: for( size_t i=0; ivalue ) { jens@0: objects[n] = pairs->value; jens@0: keys[n] = pairs->key; jens@0: n++; jens@0: } jens@0: } jens@0: return [NSDictionary dictionaryWithObjects: objects forKeys: keys count: n]; jens@0: } jens@0: jens@0: jens@0: NSMutableDictionary* _mdictof(const struct _dictpair* pairs, size_t count) jens@0: { jens@0: CAssert(count<10000); jens@0: id objects[count], keys[count]; jens@0: size_t n = 0; jens@0: for( size_t i=0; ivalue ) { jens@0: objects[n] = pairs->value; jens@0: keys[n] = pairs->key; jens@0: n++; jens@0: } jens@0: } jens@0: return [NSMutableDictionary dictionaryWithObjects: objects forKeys: keys count: n]; jens@0: } jens@0: jens@0: jens@8: NSArray* $apply( NSArray *src, SEL selector, id defaultValue ) jens@8: { jens@8: NSMutableArray *dst = [NSMutableArray arrayWithCapacity: src.count]; jens@8: for( id obj in src ) { jens@8: id result = [obj performSelector: selector] ?: defaultValue; jens@8: [dst addObject: result]; jens@8: } jens@8: return dst; jens@8: } jens@8: jens@8: NSArray* $applyKeyPath( NSArray *src, NSString *keyPath, id defaultValue ) jens@8: { jens@8: NSMutableArray *dst = [NSMutableArray arrayWithCapacity: src.count]; jens@8: for( id obj in src ) { jens@8: id result = [obj valueForKeyPath: keyPath] ?: defaultValue; jens@8: [dst addObject: result]; jens@8: } jens@8: return dst; jens@8: } jens@8: jens@8: jens@0: BOOL $equal(id obj1, id obj2) // Like -isEqual: but works even if either/both are nil jens@0: { jens@0: if( obj1 ) jens@0: return obj2 && [obj1 isEqual: obj2]; jens@0: else jens@0: return obj2==nil; jens@0: } jens@0: jens@0: jens@0: NSValue* _box(const void *value, const char *encoding) jens@0: { jens@0: // file:///Developer/Documentation/DocSets/com.apple.ADC_Reference_Library.DeveloperTools.docset/Contents/Resources/Documents/documentation/DeveloperTools/gcc-4.0.1/gcc/Type-encoding.html jens@0: char e = encoding[0]; jens@0: if( e=='r' ) // ignore 'const' modifier jens@0: e = encoding[1]; jens@0: switch( e ) { jens@0: case 'c': return [NSNumber numberWithChar: *(char*)value]; jens@0: case 'C': return [NSNumber numberWithUnsignedChar: *(char*)value]; jens@0: case 's': return [NSNumber numberWithShort: *(short*)value]; jens@0: case 'S': return [NSNumber numberWithUnsignedShort: *(unsigned short*)value]; jens@0: case 'i': return [NSNumber numberWithInt: *(int*)value]; jens@0: case 'I': return [NSNumber numberWithUnsignedInt: *(unsigned int*)value]; jens@0: case 'l': return [NSNumber numberWithLong: *(long*)value]; jens@0: case 'L': return [NSNumber numberWithUnsignedLong: *(unsigned long*)value]; jens@0: case 'q': return [NSNumber numberWithLongLong: *(long long*)value]; jens@0: case 'Q': return [NSNumber numberWithUnsignedLongLong: *(unsigned long long*)value]; jens@0: case 'f': return [NSNumber numberWithFloat: *(float*)value]; jens@0: case 'd': return [NSNumber numberWithDouble: *(double*)value]; jens@0: case '*': return [NSString stringWithUTF8String: *(char**)value]; jens@0: case '@': return *(id*)value; jens@0: default: return [NSValue value: value withObjCType: encoding]; jens@0: } jens@0: } jens@0: jens@0: jens@0: id _cast( Class requiredClass, id object ) jens@0: { jens@0: if( object && ! [object isKindOfClass: requiredClass] ) jens@0: [NSException raise: NSInvalidArgumentException format: @"%@ required, but got %@ %p", jens@0: requiredClass,[object class],object]; jens@0: return object; jens@0: } jens@0: jens@0: id _castNotNil( Class requiredClass, id object ) jens@0: { jens@0: if( ! [object isKindOfClass: requiredClass] ) jens@0: [NSException raise: NSInvalidArgumentException format: @"%@ required, but got %@ %p", jens@0: requiredClass,[object class],object]; jens@0: return object; jens@0: } jens@0: jens@0: id _castIf( Class requiredClass, id object ) jens@0: { jens@0: if( object && ! [object isKindOfClass: requiredClass] ) jens@0: object = nil; jens@0: return object; jens@0: } jens@0: jens@0: NSArray* _castArrayOf(Class itemClass, NSArray *a) jens@0: { jens@0: id item; jens@0: foreach( item, $cast(NSArray,a) ) jens@0: _cast(itemClass,item); jens@0: return a; jens@0: } jens@0: jens@0: jens@0: void setObj( id *var, id value ) jens@0: { jens@0: if( value != *var ) { jens@0: [*var release]; jens@0: *var = [value retain]; jens@0: } jens@0: } jens@0: jens@0: BOOL ifSetObj( id *var, id value ) jens@0: { jens@0: if( value != *var && ![value isEqual: *var] ) { jens@0: [*var release]; jens@0: *var = [value retain]; jens@0: return YES; jens@0: } else { jens@0: return NO; jens@0: } jens@0: } jens@0: jens@0: jens@0: void setString( NSString **var, NSString *value ) jens@0: { jens@0: if( value != *var ) { jens@0: [*var release]; jens@0: *var = [value copy]; jens@0: } jens@0: } jens@0: jens@0: jens@0: BOOL ifSetString( NSString **var, NSString *value ) jens@0: { jens@0: if( value != *var && ![value isEqualToString: *var] ) { jens@0: [*var release]; jens@0: *var = [value copy]; jens@0: return YES; jens@0: } else { jens@0: return NO; jens@0: } jens@0: } jens@0: jens@0: jens@0: @implementation NSArray (MYUtils) jens@0: jens@0: - (BOOL) my_containsObjectIdenticalTo: (id)object jens@0: { jens@0: return [self indexOfObjectIdenticalTo: object] != NSNotFound; jens@0: } jens@0: jens@0: @end jens@0: jens@0: jens@5: jens@7: jens@5: @implementation NSSet (MYUtils) jens@7: jens@5: + (NSSet*) my_unionOfSet: (NSSet*)set1 andSet: (NSSet*)set2 jens@5: { jens@5: if( set1 == set2 || set2.count==0 ) jens@5: return set1; jens@5: else if( set1.count==0 ) jens@5: return set2; jens@5: else { jens@5: NSMutableSet *result = [set1 mutableCopy]; jens@5: [result unionSet: set2]; jens@5: return [result autorelease]; jens@5: } jens@5: } jens@5: jens@7: + (NSSet*) my_intersectionOfSet: (NSSet*)set1 andSet: (NSSet*)set2 jens@7: { jens@7: if( set1 == set2 || set1.count==0 ) jens@7: return set1; jens@7: else if( set2.count==0 ) jens@7: return set2; jens@7: else { jens@7: NSMutableSet *result = [set1 mutableCopy]; jens@7: [result intersectSet: set2]; jens@7: return [result autorelease]; jens@7: } jens@7: } jens@7: jens@5: + (NSSet*) my_differenceOfSet: (NSSet*)set1 andSet: (NSSet*)set2 jens@5: { jens@5: if( set1.count==0 || set2.count==0 ) jens@5: return set1; jens@5: else if( set1==set2 ) jens@5: return [NSSet set]; jens@5: else { jens@5: NSMutableSet *result = [set1 mutableCopy]; jens@5: [result minusSet: set2]; jens@5: return [result autorelease]; jens@5: } jens@5: } jens@7: jens@5: @end jens@5: jens@5: jens@5: jens@0: #import "Test.h" jens@0: jens@0: TestCase(CollectionUtils) { jens@0: NSArray *a = $array(@"foo",@"bar",@"baz"); jens@0: //Log(@"a = %@",a); jens@0: NSArray *aa = [NSArray arrayWithObjects: @"foo",@"bar",@"baz",nil]; jens@0: CAssertEqual(a,aa); jens@0: jens@0: const char *cstr = "a C string"; jens@0: id o = $object(cstr); jens@0: //Log(@"o = %@",o); jens@0: CAssertEqual(o,@"a C string"); jens@0: jens@0: NSDictionary *d = $dict({@"int", $object(1)}, jens@0: {@"double", $object(-1.1)}, jens@0: {@"char", $object('x')}, jens@0: {@"ulong", $object(1234567UL)}, jens@0: {@"longlong",$object(987654321LL)}, jens@0: {@"cstr", $object(cstr)}); jens@0: //Log(@"d = %@",d); jens@0: NSDictionary *dd = [NSDictionary dictionaryWithObjectsAndKeys: jens@0: [NSNumber numberWithInt: 1], @"int", jens@0: [NSNumber numberWithDouble: -1.1], @"double", jens@0: [NSNumber numberWithChar: 'x'], @"char", jens@0: [NSNumber numberWithUnsignedLong: 1234567UL], @"ulong", jens@0: [NSNumber numberWithDouble: 987654321LL], @"longlong", jens@0: @"a C string", @"cstr", jens@0: nil]; jens@0: CAssertEqual(d,dd); jens@0: }