mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +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
b9c5b1414b
commit
c6df5dc455
3 changed files with 138 additions and 9 deletions
|
@ -3,29 +3,29 @@
|
||||||
|
|
||||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||||
Date: 1995
|
Date: 1995
|
||||||
|
|
||||||
This file is part of the GNUstep Base Library.
|
This file is part of the GNUstep Base Library.
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2 of the License, or (at your option) any later version.
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Library General Public License for more details.
|
Library General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this library; if not, write to the Free
|
License along with this library; if not, write to the Free
|
||||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
Boston, MA 02111 USA.
|
Boston, MA 02111 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _NSDictionary_h_GNUSTEP_BASE_INCLUDE
|
#ifndef _NSDictionary_h_GNUSTEP_BASE_INCLUDE
|
||||||
#define _NSDictionary_h_GNUSTEP_BASE_INCLUDE
|
#define _NSDictionary_h_GNUSTEP_BASE_INCLUDE
|
||||||
#import <GNUstepBase/GSVersionMacros.h>
|
#import <GNUstepBase/GSVersionMacros.h>
|
||||||
|
#import <GNUstepBase/GSBlocks.h>
|
||||||
#import <Foundation/NSObject.h>
|
#import <Foundation/NSObject.h>
|
||||||
#import <Foundation/NSEnumerator.h>
|
#import <Foundation/NSEnumerator.h>
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@class NSArray, NSString, NSURL;
|
@class NSArray, NSSet, NSString, NSURL;
|
||||||
|
|
||||||
@interface NSDictionary : NSObject <NSCoding, NSCopying, NSMutableCopying, NSFastEnumeration>
|
@interface NSDictionary : NSObject <NSCoding, NSCopying, NSMutableCopying, NSFastEnumeration>
|
||||||
+ (id) dictionary;
|
+ (id) dictionary;
|
||||||
|
@ -86,6 +86,18 @@ extern "C" {
|
||||||
- (id) valueForKey: (NSString*)key;
|
- (id) valueForKey: (NSString*)key;
|
||||||
- (BOOL) writeToURL: (NSURL*)url atomically: (BOOL)useAuxiliaryFile;
|
- (BOOL) writeToURL: (NSURL*)url atomically: (BOOL)useAuxiliaryFile;
|
||||||
#endif
|
#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
|
@end
|
||||||
|
|
||||||
@interface NSMutableDictionary: NSDictionary
|
@interface NSMutableDictionary: NSDictionary
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#import "Foundation/NSAutoreleasePool.h"
|
#import "Foundation/NSAutoreleasePool.h"
|
||||||
#import "Foundation/NSFileManager.h"
|
#import "Foundation/NSFileManager.h"
|
||||||
#import "Foundation/NSCoder.h"
|
#import "Foundation/NSCoder.h"
|
||||||
|
#import "Foundation/NSSet.h"
|
||||||
#import "Foundation/NSValue.h"
|
#import "Foundation/NSValue.h"
|
||||||
#import "Foundation/NSKeyValueCoding.h"
|
#import "Foundation/NSKeyValueCoding.h"
|
||||||
#import "Foundation/NSUserDefaults.h"
|
#import "Foundation/NSUserDefaults.h"
|
||||||
|
@ -366,7 +367,7 @@ static SEL appSel;
|
||||||
id *vals = NSZoneMalloc(NSDefaultMallocZone(), sizeof(id)*count);
|
id *vals = NSZoneMalloc(NSDefaultMallocZone(), sizeof(id)*count);
|
||||||
unsigned i;
|
unsigned i;
|
||||||
IMP dec;
|
IMP dec;
|
||||||
|
|
||||||
dec = [aCoder methodForSelector: @selector(decodeObject)];
|
dec = [aCoder methodForSelector: @selector(decodeObject)];
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
|
@ -824,6 +825,7 @@ static SEL appSel;
|
||||||
return AUTORELEASE(result);
|
return AUTORELEASE(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)getObjects: (__unsafe_unretained id[])objects
|
- (void)getObjects: (__unsafe_unretained id[])objects
|
||||||
andKeys: (__unsafe_unretained id[])keys
|
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.
|
* <p>Writes the contents of the dictionary to the file specified by path.
|
||||||
* The file contents will be in property-list format ... under GNUstep
|
* 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) valueForKey: (NSString*)key
|
||||||
{
|
{
|
||||||
id o;
|
id o;
|
||||||
|
|
||||||
if ([key hasPrefix: @"@"] == YES)
|
if ([key hasPrefix: @"@"] == YES)
|
||||||
{
|
{
|
||||||
|
@ -1121,7 +1192,7 @@ compareIt(id o1, id o2, void* context)
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state
|
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state
|
||||||
objects: (__unsafe_unretained id[])stackbuf
|
objects: (__unsafe_unretained id[])stackbuf
|
||||||
count: (NSUInteger)len
|
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…
Add table
Add a link
Reference in a new issue