Line data Source code
1 0 : /* 2 : 3 : OOFilteringEnumerator.m 4 : By Jens Ayton 5 : 6 : 7 : Copyright (C) 2008-2013 Jens Ayton 8 : 9 : Permission is hereby granted, free of charge, to any person obtaining a copy 10 : of this software and associated documentation files (the "Software"), to deal 11 : in the Software without restriction, including without limitation the rights 12 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 : copies of the Software, and to permit persons to whom the Software is 14 : furnished to do so, subject to the following conditions: 15 : 16 : The above copyright notice and this permission notice shall be included in all 17 : copies or substantial portions of the Software. 18 : 19 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 : SOFTWARE. 26 : 27 : */ 28 : 29 : #import "OOFilteringEnumerator.h" 30 : 31 : 32 0 : typedef BOOL (*BoolReturnMsgSend)(id, SEL); 33 0 : typedef BOOL (*BoolReturnWithParamMsgSend)(id, SEL, id); 34 : 35 : 36 : @implementation OOFilteringEnumerator 37 : 38 : + (id) filterEnumerator:(NSEnumerator *)enumerator withSelector:(SEL)selector 39 : { 40 : if (selector == NULL) return [[enumerator retain] autorelease]; 41 : 42 : return [[[self alloc] initWithUnderlyingEnumerator:enumerator 43 : withSelector:selector 44 : takingArgument:NO 45 : argumentValue:nil] 46 : autorelease]; 47 : } 48 : 49 : 50 : + (id) filterEnumerator:(NSEnumerator *)enumerator withSelector:(SEL)selector andArgument:(id)argument 51 : { 52 : if (selector == NULL) return [[enumerator retain] autorelease]; 53 : 54 : return [[[self alloc] initWithUnderlyingEnumerator:enumerator 55 : withSelector:selector 56 : takingArgument:YES 57 : argumentValue:argument] 58 : autorelease]; 59 : } 60 : 61 : - (id) initWithUnderlyingEnumerator:(NSEnumerator *)enumerator 62 : withSelector:(SEL)selector 63 : takingArgument:(BOOL)takesArgument 64 : argumentValue:(id)argument 65 : { 66 : self = [super init]; 67 : if (self != nil) 68 : { 69 : _underlyingEnum = [enumerator retain]; 70 : _selector = selector; 71 : _takesArgument = takesArgument; 72 : if (_takesArgument) 73 : { 74 : _argument = [argument retain]; 75 : } 76 : } 77 : return self; 78 : } 79 : 80 : 81 0 : - (void) dealloc 82 : { 83 : [_underlyingEnum release]; 84 : [_argument release]; 85 : 86 : [super dealloc]; 87 : } 88 : 89 : 90 0 : - (NSString *) descriptionComponents 91 : { 92 : NSString *subDesc = NSStringFromSelector(_selector); 93 : if (_takesArgument) 94 : { 95 : subDesc = [subDesc stringByAppendingString:[_argument shortDescription]]; 96 : } 97 : 98 : return [NSString stringWithFormat:@"%@ matching %@", [_underlyingEnum shortDescription], subDesc]; 99 : } 100 : 101 : 102 0 : - (NSString *) shortDescriptionComponents 103 : { 104 : return NSStringFromSelector(_selector); 105 : } 106 : 107 : 108 0 : - (id) nextObject 109 : { 110 : for (;;) 111 : { 112 : // Get next object 113 : id obj = [_underlyingEnum nextObject]; 114 : BOOL filter; 115 : 116 : if (obj == nil) 117 : { 118 : // End of enumeration 119 : if (_underlyingEnum != nil) 120 : { 121 : [_underlyingEnum release]; 122 : _underlyingEnum = nil; 123 : [_argument release]; 124 : _argument = nil; 125 : } 126 : return nil; 127 : } 128 : 129 : // Check against filter 130 : IMP predicate = [obj methodForSelector:_selector]; 131 : if (predicate != NULL) 132 : { 133 : if (!_takesArgument) 134 : { 135 : filter = ((BoolReturnMsgSend)predicate)(obj, _selector); 136 : } 137 : else 138 : { 139 : filter = ((BoolReturnWithParamMsgSend)predicate)(obj, _selector, _argument); 140 : } 141 : } 142 : else 143 : { 144 : // Unsupported method 145 : filter = NO; 146 : } 147 : 148 : // If object passed, return it. 149 : if (filter) return obj; 150 : } 151 : } 152 : 153 : @end 154 : 155 : 156 : @implementation NSEnumerator (OOFilteringEnumerator) 157 : 158 : - (id) filteredWithSelector:(SEL)selector 159 : { 160 : return [OOFilteringEnumerator filterEnumerator:self withSelector:selector]; 161 : } 162 : 163 : 164 : - (id) filteredWithSelector:(SEL)selector andArgument:(id)argument 165 : { 166 : return [OOFilteringEnumerator filterEnumerator:self withSelector:selector andArgument:argument]; 167 : } 168 : 169 : @end 170 : 171 : 172 : @implementation NSArray (OOFilteringEnumerator) 173 : 174 : - (id) objectEnumeratorFilteredWithSelector:(SEL)selector 175 : { 176 : return [[self objectEnumerator] filteredWithSelector:selector]; 177 : } 178 : 179 : 180 : - (id) objectEnumeratorFilteredWithSelector:(SEL)selector andArgument:(id)argument 181 : { 182 : return [[self objectEnumerator] filteredWithSelector:selector andArgument:argument]; 183 : } 184 : 185 : @end 186 : 187 : 188 : @implementation NSSet (OOFilteringEnumerator) 189 : 190 : - (id) objectEnumeratorFilteredWithSelector:(SEL)selector 191 : { 192 : return [[self objectEnumerator] filteredWithSelector:selector]; 193 : } 194 : 195 : 196 : - (id) objectEnumeratorFilteredWithSelector:(SEL)selector andArgument:(id)argument 197 : { 198 : return [[self objectEnumerator] filteredWithSelector:selector andArgument:argument]; 199 : } 200 : 201 : @end 202 : 203 : 204 : @implementation NSDictionary (OOFilteringEnumerator) 205 : 206 : - (id) objectEnumeratorFilteredWithSelector:(SEL)selector 207 : { 208 : return [[self objectEnumerator] filteredWithSelector:selector]; 209 : } 210 : 211 : 212 : - (id) objectEnumeratorFilteredWithSelector:(SEL)selector andArgument:(id)argument 213 : { 214 : return [[self objectEnumerator] filteredWithSelector:selector andArgument:argument]; 215 : } 216 : 217 : 218 : - (id) keyEnumeratorFilteredWithSelector:(SEL)selector 219 : { 220 : return [[self keyEnumerator] filteredWithSelector:selector]; 221 : } 222 : 223 : 224 : - (id) keyEnumeratorFilteredWithSelector:(SEL)selector andArgument:(id)argument 225 : { 226 : return [[self keyEnumerator] filteredWithSelector:selector andArgument:argument]; 227 : } 228 : 229 : @end 230 : 231 : 232 : @implementation NSEnumerator (OOMakeObjectsPerformSelector) 233 : 234 : - (void)makeObjectsPerformSelector:(SEL)selector 235 : { 236 : id object = nil; 237 : while ((object = [self nextObject])) 238 : { 239 : if (selector != NULL && [object respondsToSelector:selector]) 240 : { 241 : [object performSelector:selector]; 242 : } 243 : } 244 : } 245 : 246 : 247 : - (void)makeObjectsPerformSelector:(SEL)selector withObject:(id)argument 248 : { 249 : id object = nil; 250 : while ((object = [self nextObject])) 251 : { 252 : if (selector != NULL && [object respondsToSelector:selector]) 253 : { 254 : [object performSelector:selector withObject:argument]; 255 : } 256 : } 257 : } 258 : 259 : @end