mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Implement a few blocks related enumeration methods on NSDictionary (with
unit tests). git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@34965 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
02a7bf73a7
commit
ecec748337
3 changed files with 138 additions and 9 deletions
|
@ -3,29 +3,29 @@
|
|||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: 1995
|
||||
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02111 USA.
|
||||
*/
|
||||
*/
|
||||
|
||||
#ifndef _NSDictionary_h_GNUSTEP_BASE_INCLUDE
|
||||
#define _NSDictionary_h_GNUSTEP_BASE_INCLUDE
|
||||
#import <GNUstepBase/GSVersionMacros.h>
|
||||
|
||||
#import <GNUstepBase/GSBlocks.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSEnumerator.h>
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
@class NSArray, NSString, NSURL;
|
||||
@class NSArray, NSSet, NSString, NSURL;
|
||||
|
||||
@interface NSDictionary : NSObject <NSCoding, NSCopying, NSMutableCopying, NSFastEnumeration>
|
||||
+ (id) dictionary;
|
||||
|
@ -86,6 +86,18 @@ extern "C" {
|
|||
- (id) valueForKey: (NSString*)key;
|
||||
- (BOOL) writeToURL: (NSURL*)url atomically: (BOOL)useAuxiliaryFile;
|
||||
#endif
|
||||
|
||||
|
||||
#if OS_API_VERSION(100600, GS_API_LATEST)
|
||||
DEFINE_BLOCK_TYPE(GSKeysAndObjectsEnumeratorBlock, void, id, id, BOOL*);
|
||||
DEFINE_BLOCK_TYPE(GSKeysAndObjectsPredicateBlock, BOOL, id, id, BOOL*);
|
||||
- (void)enumerateKeysAndObjectsWithOptions: (NSEnumerationOptions)opts
|
||||
usingBlock: (GSKeysAndObjectsEnumeratorBlock)aBlock;
|
||||
- (void)enumerateKeysAndObjectsUsingBlock: (GSKeysAndObjectsEnumeratorBlock)aBlock;
|
||||
- (NSSet*)keysOfEntriesWithOptions: (NSEnumerationOptions)opts
|
||||
passingTest: (GSKeysAndObjectsPredicateBlock)aPredicate;
|
||||
- (NSSet*)keysOfEntriesPassingTest: (GSKeysAndObjectsPredicateBlock)aPredicate;
|
||||
#endif
|
||||
@end
|
||||
|
||||
@interface NSMutableDictionary: NSDictionary
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#import "Foundation/NSAutoreleasePool.h"
|
||||
#import "Foundation/NSFileManager.h"
|
||||
#import "Foundation/NSCoder.h"
|
||||
#import "Foundation/NSSet.h"
|
||||
#import "Foundation/NSValue.h"
|
||||
#import "Foundation/NSKeyValueCoding.h"
|
||||
#import "Foundation/NSUserDefaults.h"
|
||||
|
@ -366,7 +367,7 @@ static SEL appSel;
|
|||
id *vals = NSZoneMalloc(NSDefaultMallocZone(), sizeof(id)*count);
|
||||
unsigned i;
|
||||
IMP dec;
|
||||
|
||||
|
||||
dec = [aCoder methodForSelector: @selector(decodeObject)];
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
|
@ -824,6 +825,7 @@ static SEL appSel;
|
|||
return AUTORELEASE(result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)getObjects: (__unsafe_unretained id[])objects
|
||||
andKeys: (__unsafe_unretained id[])keys
|
||||
{
|
||||
|
@ -964,6 +966,75 @@ compareIt(id o1, id o2, void* context)
|
|||
}
|
||||
}
|
||||
|
||||
#if OS_API_VERSION(100600, GS_API_LATEST)
|
||||
- (void)enumerateKeysAndObjectsWithOptions: (NSEnumerationOptions)opts
|
||||
usingBlock: (GSKeysAndObjectsEnumeratorBlock)aBlock
|
||||
{
|
||||
/*
|
||||
* NOTE: For the moment, we ignore the NSEnumerationOptions because, according
|
||||
* to the Cocoa documentation, NSEnumerationReverse is undefined for
|
||||
* NSDictionary and we cannot handle NSEnumerationConcurrent without
|
||||
* libdispatch.
|
||||
*/
|
||||
id<NSFastEnumeration> enumerator = [self keyEnumerator];
|
||||
SEL objectForKeySelector = @selector(objectForKey:);
|
||||
IMP objectForKey = [self methodForSelector: objectForKeySelector];
|
||||
BOOL shouldStop = NO;
|
||||
FOR_IN(id, key, enumerator)
|
||||
id obj = objectForKey(self, objectForKeySelector, key);
|
||||
CALL_BLOCK(aBlock, key, obj, &shouldStop);
|
||||
if (YES == shouldStop)
|
||||
{
|
||||
break;
|
||||
}
|
||||
END_FOR_IN(enumerator)
|
||||
}
|
||||
|
||||
- (void)enumerateKeysAndObjectsUsingBlock: (GSKeysAndObjectsEnumeratorBlock)aBlock
|
||||
{
|
||||
[self enumerateKeysAndObjectsWithOptions: 0
|
||||
usingBlock: aBlock];
|
||||
}
|
||||
|
||||
|
||||
- (NSSet*)keysOfEntriesWithOptions: (NSEnumerationOptions)opts
|
||||
passingTest: (GSKeysAndObjectsPredicateBlock)aPredicate;
|
||||
{
|
||||
/*
|
||||
* See -enumerateKeysAndObjectsWithOptions:usingBlock: for note about
|
||||
* NSEnumerationOptions.
|
||||
*/
|
||||
id<NSFastEnumeration> enumerator = [self keyEnumerator];
|
||||
SEL objectForKeySelector = @selector(objectForKey:);
|
||||
IMP objectForKey = [self methodForSelector: objectForKeySelector];
|
||||
BOOL shouldStop = NO;
|
||||
NSMutableSet *buildSet = [NSMutableSet new];
|
||||
SEL addObjectSelector = @selector(addObject:);
|
||||
IMP addObject = [buildSet methodForSelector: addObjectSelector];
|
||||
NSSet *resultSet = nil;
|
||||
FOR_IN(id, key, enumerator)
|
||||
id obj = objectForKey(self, objectForKeySelector, key);
|
||||
if (CALL_BLOCK(aPredicate, key, obj, &shouldStop))
|
||||
{
|
||||
addObject(buildSet, addObjectSelector, key);
|
||||
}
|
||||
if (YES == shouldStop)
|
||||
{
|
||||
break;
|
||||
}
|
||||
END_FOR_IN(enumerator)
|
||||
resultSet = [NSSet setWithSet: buildSet];
|
||||
[buildSet release];
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
- (NSSet*)keysOfEntriesPassingTest: (GSKeysAndObjectsPredicateBlock)aPredicate
|
||||
{
|
||||
return [self keysOfEntriesWithOptions: 0
|
||||
passingTest: aPredicate];
|
||||
}
|
||||
|
||||
#endif //OS_API_VERSION(100600,GS_API_LATEST)
|
||||
/**
|
||||
* <p>Writes the contents of the dictionary to the file specified by path.
|
||||
* The file contents will be in property-list format ... under GNUstep
|
||||
|
@ -1109,7 +1180,7 @@ compareIt(id o1, id o2, void* context)
|
|||
*/
|
||||
- (id) valueForKey: (NSString*)key
|
||||
{
|
||||
id o;
|
||||
id o;
|
||||
|
||||
if ([key hasPrefix: @"@"] == YES)
|
||||
{
|
||||
|
@ -1121,7 +1192,7 @@ compareIt(id o1, id o2, void* context)
|
|||
}
|
||||
return o;
|
||||
}
|
||||
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state
|
||||
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state
|
||||
objects: (__unsafe_unretained id[])stackbuf
|
||||
count: (NSUInteger)len
|
||||
{
|
||||
|
|
46
Tests/base/NSDictionary/blocks.m
Normal file
46
Tests/base/NSDictionary/blocks.m
Normal file
|
@ -0,0 +1,46 @@
|
|||
#import "Testing.h"
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSAutoreleasePool.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
#import <Foundation/NSData.h>
|
||||
#import <Foundation/NSDate.h>
|
||||
#import <Foundation/NSEnumerator.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#if defined(GNUSTEP_BASE_LIBRARY)
|
||||
#import <Foundation/NSSerialization.h>
|
||||
#endif
|
||||
|
||||
|
||||
static NSUInteger fooCount = 0;
|
||||
|
||||
int main()
|
||||
{
|
||||
START_SET("NSDictionary Blocks")
|
||||
# ifndef __has_feature
|
||||
# define __has_feature(x) 0
|
||||
# endif
|
||||
# if __has_feature(blocks)
|
||||
NSAutoreleasePool *arp = [NSAutoreleasePool new];
|
||||
|
||||
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: @"foo",
|
||||
@"key1", @"bar", @"key2", @"foo", @"key3", nil];
|
||||
[dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop){
|
||||
if ([obj isEqual: @"foo"]){ fooCount++;}}];
|
||||
PASS((2 == fooCount),
|
||||
"Can enumerate dictionary using a block");
|
||||
|
||||
NSSet *fooKeys = [dict keysOfEntriesPassingTest: ^(id key, id obj, BOOL *stop){
|
||||
return [obj isEqual: @"foo"];}];
|
||||
PASS((([fooKeys count] == 2)
|
||||
&& ([fooKeys containsObject: @"key1"])
|
||||
&& ([fooKeys containsObject: @"key3"]))
|
||||
, "Can use blocks as predicates.");
|
||||
[arp release]; arp = nil;
|
||||
# else
|
||||
SKIP("No Blocks support in the compiler.")
|
||||
# endif
|
||||
END_SET("NSDictionary Blocks")
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue