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