Implement OSX10.5 NSMapTable API

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28086 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2009-03-16 10:54:59 +00:00
parent 81cc2a07a8
commit 971de91d62
11 changed files with 1391 additions and 799 deletions

View file

@ -1,3 +1,17 @@
2009-03-16 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSConcretePointerFunctions.h: Minor GC tweaks
* Source/NSMessagePortNameServer.m: Fix map table declaration
* Source/NSKeyedUnarchiver.m: ditto
* Source/NSKeyValueObserving.m: ditto
* Source/NSObject.m: ditto
* Source/GNUmakefile: Add NSConcreteMapTable.m
* Source/NSConcreteMapTable.m: New file for new class
* Source/NSMapTable.m: Change to be an abstract class
* Headers/Foundation/NSMapTable.h: Add new MacOS-X 10.5 API
* Headers/Additions/GNUstepBase/GSIMap.h: Some changes for
new map table API.
2009-03-12 Bernard Cafferelli <voyageursp@gmail.com>
* configure.ac: Add --disable-zeroconf option to control whether

View file

@ -278,13 +278,13 @@ extern "C" {
* of size "increment".
*/
typedef struct _GSIMapTable GSIMapTable_t;
#if !defined(GSI_MAP_TABLE_T)
typedef struct _GSIMapBucket GSIMapBucket_t;
typedef struct _GSIMapNode GSIMapNode_t;
typedef GSIMapTable_t *GSIMapTable;
typedef GSIMapBucket_t *GSIMapBucket;
typedef GSIMapNode_t *GSIMapNode;
#endif
struct _GSIMapNode {
GSIMapNode nextInBucket; /* Linked list of bucket. */
@ -299,6 +299,12 @@ struct _GSIMapBucket {
GSIMapNode firstNode; /* The linked list of nodes. */
};
#if defined(GSI_MAP_TABLE_T)
typedef GSI_MAP_TABLE_T *GSIMapTable;
#else
typedef struct _GSIMapTable GSIMapTable_t;
typedef GSIMapTable_t *GSIMapTable;
struct _GSIMapTable {
NSZone *zone;
size_t nodeCount; /* Number of used nodes in map. */
@ -312,6 +318,7 @@ struct _GSIMapTable {
GSI_MAP_EXTRA extra;
#endif
};
#endif
typedef struct _GSIMapEnumerator {
GSIMapTable map; /* the map being enumerated. */
@ -482,52 +489,6 @@ GSIMapMoreNodes(GSIMapTable map, unsigned required)
}
}
#if GSI_MAP_HAS_VALUE
static INLINE GSIMapNode
GSIMapNewNode(GSIMapTable map, GSIMapKey key, GSIMapVal value)
{
GSIMapNode node = map->freeNodes;
if (node == 0)
{
GSIMapMoreNodes(map, map->nodeCount < map->increment ? 0: map->increment);
node = map->freeNodes;
if (node == 0)
{
return 0;
}
}
map->freeNodes = node->nextInBucket;
node->key = key;
node->value = value;
node->nextInBucket = 0;
return node;
}
#else
static INLINE GSIMapNode
GSIMapNewNode(GSIMapTable map, GSIMapKey key)
{
GSIMapNode node = map->freeNodes;
if (node == 0)
{
GSIMapMoreNodes(map, map->nodeCount < map->increment ? 0: map->increment);
node = map->freeNodes;
if (node == 0)
{
return 0;
}
}
map->freeNodes = node->nextInBucket;
node->key = key;
node->nextInBucket = 0;
return node;
}
#endif
static INLINE void
GSIMapFreeNode(GSIMapTable map, GSIMapNode node)
{
@ -771,63 +732,93 @@ GSIMapEnumeratorNextNode(GSIMapEnumerator enumerator)
static INLINE GSIMapNode
GSIMapAddPairNoRetain(GSIMapTable map, GSIMapKey key, GSIMapVal value)
{
GSIMapNode node;
GSIMapNode node = map->freeNodes;
node = GSIMapNewNode(map, key, value);
if (node != 0)
if (node == 0)
{
GSIMapRightSizeMap(map, map->nodeCount);
GSIMapAddNodeToMap(map, node);
GSIMapMoreNodes(map, map->nodeCount < map->increment ? 0: map->increment);
node = map->freeNodes;
if (node == 0)
{
return 0;
}
}
map->freeNodes = node->nextInBucket;
node->key = key;
node->value = value;
node->nextInBucket = 0;
GSIMapRightSizeMap(map, map->nodeCount);
GSIMapAddNodeToMap(map, node);
return node;
}
static INLINE GSIMapNode
GSIMapAddPair(GSIMapTable map, GSIMapKey key, GSIMapVal value)
{
GSIMapNode node;
GSIMapNode node = map->freeNodes;
GSI_MAP_RETAIN_KEY(map, key);
GSI_MAP_RETAIN_VAL(map, value);
node = GSIMapNewNode(map, key, value);
if (node != 0)
if (node == 0)
{
GSIMapRightSizeMap(map, map->nodeCount);
GSIMapAddNodeToMap(map, node);
GSIMapMoreNodes(map, map->nodeCount < map->increment ? 0: map->increment);
node = map->freeNodes;
if (node == 0)
{
return 0;
}
}
map->freeNodes = node->nextInBucket;
node->key = key;
node->value = value;
GSI_MAP_RETAIN_KEY(map, node->key);
GSI_MAP_RETAIN_VAL(map, node->value);
node->nextInBucket = 0;
GSIMapRightSizeMap(map, map->nodeCount);
GSIMapAddNodeToMap(map, node);
return node;
}
#else
static INLINE GSIMapNode
GSIMapAddKeyNoRetain(GSIMapTable map, GSIMapKey key)
{
GSIMapNode node;
GSIMapNode node = map->freeNodes;
node = GSIMapNewNode(map, key);
if (node != 0)
if (node == 0)
{
GSIMapRightSizeMap(map, map->nodeCount);
GSIMapAddNodeToMap(map, node);
GSIMapMoreNodes(map, map->nodeCount < map->increment ? 0: map->increment);
node = map->freeNodes;
if (node == 0)
{
return 0;
}
}
map->freeNodes = node->nextInBucket;
node->key = key;
node->nextInBucket = 0;
GSIMapRightSizeMap(map, map->nodeCount);
GSIMapAddNodeToMap(map, node);
return node;
}
static INLINE GSIMapNode
GSIMapAddKey(GSIMapTable map, GSIMapKey key)
{
GSIMapNode node;
GSIMapNode node = map->freeNodes;
GSI_MAP_RETAIN_KEY(map, key);
node = GSIMapNewNode(map, key);
if (node != 0)
if (node == 0)
{
GSIMapRightSizeMap(map, map->nodeCount);
GSIMapAddNodeToMap(map, node);
GSIMapMoreNodes(map, map->nodeCount < map->increment ? 0: map->increment);
node = map->freeNodes;
if (node == 0)
{
return 0;
}
}
map->freeNodes = node->nextInBucket;
node->key = key;
GSI_MAP_RETAIN_KEY(map, node->key);
node->nextInBucket = 0;
GSIMapRightSizeMap(map, map->nodeCount);
GSIMapAddNodeToMap(map, node);
return node;
}
#endif

View file

@ -1,11 +1,12 @@
/* NSMapTable interface for GNUStep.
* Copyright (C) 1994, 1995, 1996, 2002 Free Software Foundation, Inc.
* Copyright (C) 1994, 1995, 1996, 2002, 2009 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Tue Dec 13 00:05:02 EST 1994
* Updated: Thu Mar 21 15:12:42 EST 1996
* Serial: 96.03.21.05
* Modified by: Richard Frith-Macdonald <rfm@gnu.org>
* Updated: March 2009
*
* This file is part of the GNUstep Base Library.
*
@ -34,6 +35,8 @@
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSPointerFunctions.h>
#if defined(__cplusplus)
extern "C" {
@ -41,10 +44,103 @@ extern "C" {
/**** Type, Constant, and Macro Definitions **********************************/
/**
* Map table type ... an opaque pointer to a data structure.
enum {
NSMapTableStrongMemory
= NSPointerFunctionsStrongMemory,
NSMapTableZeroingWeakMemory
= NSPointerFunctionsZeroingWeakMemory,
NSMapTableCopyIn
= NSPointerFunctionsCopyIn,
NSMapTableObjectPointerPersonality
= NSPointerFunctionsObjectPointerPersonality
};
typedef NSUInteger NSMapTableOptions;
@interface NSMapTable : NSObject <NSCopying, NSCoding, NSFastEnumeration>
/** Return a map table initialised using the specified options for
* keys and values.
*/
typedef void *NSMapTable;
+ (id) mapTableWithKeyOptions: (NSPointerFunctionsOptions)keyOptions
valueOptions: (NSPointerFunctionsOptions)valueOptions;
/** Convenience method for creating a map table to store object values
* using object keys.
*/
+ (id) mapTableWithStrongToStrongObjects;
/** Convenience method for creating a map table to store non-retained
* object values with retained object keys.
*/
+ (id) mapTableWithStrongToWeakObjects;
/** Convenience method for creating a map table to store retained
* object values with non-retained object keys.
*/
+ (id) mapTableWithWeakToStrongObjects;
/** Convenience method for creating a map table to store non-retained
* object values with non-retained object keys.
*/
+ (id) mapTableWithWeakToWeakObjects;
/** Initialiser using option bitmasks to describe the keys and values.
*/
- (id) initWithKeyOptions: (NSPointerFunctionsOptions)keyOptions
valueOptions: (NSPointerFunctionsOptions)valueOptions
capacity: (NSUInteger)initialCapacity;
/** Initialiser using full pointer function information to describe
* the keys and values.
*/
- (id) initWithKeyPointerFunctions: (NSPointerFunctions*)keyFunctions
valuePointerFunctions: (NSPointerFunctions*)valueFunctions
capacity: (NSUInteger)initialCapacity;
/** Return the number of items stored in the map.
*/
- (NSUInteger) count;
/** Return a dictionary containing the keys and values in the receiver.
*/
- (NSDictionary*) dictionaryRepresentation;
/** Return an enumerator able to enumerate the keys in the receiver.
*/
- (NSEnumerator*) keyEnumerator;
/** Return an NSPointerFunctions value describind the functions used by the
* receiver to handle keys.
*/
- (NSPointerFunctions*) keyPointerFunctions;
/** Return an enumerator able to enumerate the values in the receiver.
*/
- (NSEnumerator*) objectEnumerator;
/** Return the object stored under the specified key.
*/
- (id) objectForKey: (id)aKey;
/** Empty the receiver of all stored values.
*/
- (void) removeAllObjects;
/** Remove the object stored under the specified key.
*/
- (void) removeObjectForKey: (id)aKey;
/** Store the object under the specified key, replacing any object which
* was previously stored under that key.
*/
- (void) setObject: (id)anObject forKey: (id)aKey;
/** Return an NSPointerFunctions value describind the functions used by the
* receiver to handle values.
*/
- (NSPointerFunctions*) valuePointerFunctions;
@end
/**
* Type for enumerating.<br />

View file

@ -176,6 +176,7 @@ NSClassDescription.m \
NSCoder.m \
NSCopyObject.m \
NSCountedSet.m \
NSConcreteMapTable.m \
NSConcreteNumber.m \
NSConnection.m \
NSData.m \

1081
Source/NSConcreteMapTable.m Normal file

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,7 @@
#import "Foundation/NSPointerFunctions.h"
/* Declare a structure type to copy poinnnnnnter functions information
/* Declare a structure type to copy pointer functions information
* around easily.
*/
typedef struct

View file

@ -552,7 +552,7 @@ replacementForClass(Class c)
}
else
{
NSMapTable depKeys = NSMapGet(dependentKeyTable, original);
NSMapTable *depKeys = NSMapGet(dependentKeyTable, original);
if (depKeys)
{
@ -1474,7 +1474,7 @@ replacementForClass(Class c)
- (void) willChangeValueForDependentsOfKey: (NSString *)aKey
{
NSMapTable keys = NSMapGet(dependentKeyTable, [self class]);
NSMapTable *keys = NSMapGet(dependentKeyTable, [self class]);
if (keys != nil)
{
@ -1497,7 +1497,7 @@ replacementForClass(Class c)
- (void) didChangeValueForDependentsOfKey: (NSString *)aKey
{
NSMapTable keys = NSMapGet(dependentKeyTable, [self class]);
NSMapTable *keys = NSMapGet(dependentKeyTable, [self class]);
if (keys != nil)
{
@ -1807,7 +1807,7 @@ replacementForClass(Class c)
+ (void) setKeys: (NSArray*)triggerKeys
triggerChangeNotificationsForDependentKey: (NSString*)dependentKey
{
NSMapTable affectingKeys;
NSMapTable *affectingKeys;
NSEnumerator *enumerator;
NSString *affectingKey;

View file

@ -64,7 +64,7 @@
NSString * const NSInvalidUnarchiveOperationException
= @"NSInvalidUnarchiveOperationException";
static NSMapTable globalClassMap = 0;
static NSMapTable *globalClassMap = 0;
#define GETVAL \
id o; \

View file

@ -1,11 +1,7 @@
/** NSMapTable implementation for GNUStep.
* Copyright (C) 1994, 1995, 1996, 2002 Free Software Foundation, Inc.
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Mon Dec 12 23:59:57 EST 1994
* Updated: Sun Mar 17 18:37:12 EST 1996
* Serial: 96.03.17.31
* Rewrite by: Richard Frith-Macdonald <rfm@gnu.org>
* Author: Richard Frith-Macdonald <rfm@gnu.org>
*
* This file is part of the GNUstep Base Library.
*
@ -28,776 +24,189 @@
* $Date$ $Revision$
*/
/**** Included Headers *******************************************************/
#include "config.h"
#include "Foundation/NSObject.h"
#include "Foundation/NSString.h"
#include "Foundation/NSArray.h"
#include "Foundation/NSException.h"
#include "Foundation/NSPointerFunctions.h"
#include "Foundation/NSZone.h"
#include "Foundation/NSMapTable.h"
#include "Foundation/NSDebug.h"
#include "NSCallBacks.h"
@implementation NSMapTable
typedef struct {
NSMapTableKeyCallBacks k;
NSMapTableValueCallBacks v;
} extraData;
@class NSConcreteMapTable;
/*
* The 'Fastmap' stuff provides an inline implementation of a mapping
* table - for maximum performance.
*/
#define GSI_MAP_EXTRA extraData
#define GSI_MAP_KTYPES GSUNION_PTR
#define GSI_MAP_VTYPES GSUNION_PTR
#define GSI_MAP_HASH(M, X)\
(M->extra.k.hash)((NSMapTable*)M, X.ptr)
#define GSI_MAP_EQUAL(M, X, Y)\
(M->extra.k.isEqual)((NSMapTable*)M, X.ptr, Y.ptr)
#define GSI_MAP_RELEASE_KEY(M, X)\
(M->extra.k.release)((NSMapTable*)M, X.ptr)
#define GSI_MAP_RETAIN_KEY(M, X)\
(M->extra.k.retain)((NSMapTable*)M, X.ptr)
#define GSI_MAP_RELEASE_VAL(M, X)\
(M->extra.v.release)((NSMapTable*)M, X.ptr)
#define GSI_MAP_RETAIN_VAL(M, X)\
(M->extra.v.retain)((NSMapTable*)M, X.ptr)
#define GSI_MAP_ENUMERATOR NSMapEnumerator
static Class abstractClass = 0;
static Class concreteClass = 0;
#if GS_WITH_GC
#include <gc_typed.h>
static GC_descr nodeSS = 0;
static GC_descr nodeSW = 0;
static GC_descr nodeWS = 0;
static GC_descr nodeWW = 0;
#define GSI_MAP_NODES(M, X) \
(GSIMapNode)GC_calloc_explicitly_typed(X, sizeof(GSIMapNode_t), (GC_descr)M->zone)
+ (id) allocWithZone: (NSZone*)aZone
{
if (self == abstractClass)
{
return NSAllocateObject(concreteClass, 0, aZone);
}
return NSAllocateObject(self, 0, aZone);
}
+ (void) initialize
{
if (abstractClass == 0)
{
abstractClass = [NSMapTable class];
concreteClass = [NSConcreteMapTable class];
}
}
+ (id) mapTableWithKeyOptions: (NSPointerFunctionsOptions)keyOptions
valueOptions: (NSPointerFunctionsOptions)valueOptions
{
NSMapTable *t;
t = [self allocWithZone: NSDefaultMallocZone()];
t = [t initWithKeyOptions: keyOptions
valueOptions: valueOptions
capacity: 0];
return AUTORELEASE(t);
}
+ (id) mapTableWithStrongToStrongObjects
{
return [self mapTableWithKeyOptions: NSPointerFunctionsObjectPersonality
valueOptions: NSPointerFunctionsObjectPersonality];
}
+ (id) mapTableWithStrongToWeakObjects
{
return [self mapTableWithKeyOptions: NSPointerFunctionsObjectPersonality
valueOptions: NSPointerFunctionsObjectPersonality
| NSPointerFunctionsZeroingWeakMemory];
}
+ (id) mapTableWithWeakToStrongObjects
{
return [self mapTableWithKeyOptions: NSPointerFunctionsObjectPersonality
| NSPointerFunctionsZeroingWeakMemory
valueOptions: NSPointerFunctionsObjectPersonality];
}
+ (id) mapTableWithWeakToWeakObjects
{
return [self mapTableWithKeyOptions: NSPointerFunctionsObjectPersonality
| NSPointerFunctionsZeroingWeakMemory
valueOptions: NSPointerFunctionsObjectPersonality
| NSPointerFunctionsZeroingWeakMemory];
}
- (id) initWithKeyOptions: (NSPointerFunctionsOptions)keyOptions
valueOptions: (NSPointerFunctionsOptions)valueOptions
capacity: (NSUInteger)initialCapacity
{
NSPointerFunctions *k;
NSPointerFunctions *v;
id o;
k = [[NSPointerFunctions alloc] initWithOptions: keyOptions];
v = [[NSPointerFunctions alloc] initWithOptions: valueOptions];
o = [self initWithKeyPointerFunctions: k
valuePointerFunctions: v
capacity: initialCapacity];
#if !GS_WITH_GC
[k release];
[v release];
#endif
#include "GNUstepBase/GSIMap.h"
#if GS_WITH_GC
static void
initialize()
{
/* We create a typed memory descriptor for map nodes.
*/
if (nodeSS == 0)
{
GC_word w[GC_BITMAP_SIZE(GSIMapNode_t)] = {0};
nodeWW = GC_make_descriptor(w, GC_WORD_LEN(GSIMapNode_t));
GC_set_bit(w, GC_WORD_OFFSET(GSIMapNode_t, key));
nodeSW = GC_make_descriptor(w, GC_WORD_LEN(GSIMapNode_t));
GC_set_bit(w, GC_WORD_OFFSET(GSIMapNode_t, value));
nodeSS = GC_make_descriptor(w, GC_WORD_LEN(GSIMapNode_t));
memset(&w[0], '\0', sizeof(w));
GC_set_bit(w, GC_WORD_OFFSET(GSIMapNode_t, value));
nodeWS = GC_make_descriptor(w, GC_WORD_LEN(GSIMapNode_t));
}
}
#endif
/**** Function Implementations ****/
/**
* Returns an array of all the keys in the table.
* NB. The table <em>must</em> contain objects for its keys.
*/
NSArray *
NSAllMapTableKeys(NSMapTable *table)
{
NSMutableArray *keyArray;
NSMapEnumerator enumerator;
id key = nil;
void *dummy;
if (table == 0)
{
NSWarnFLog(@"Nul table argument supplied");
return nil;
}
/* Create our mutable key array. */
keyArray = [NSMutableArray arrayWithCapacity: NSCountMapTable(table)];
/* Get an enumerator for TABLE. */
enumerator = NSEnumerateMapTable(table);
/* Step through TABLE... */
while (NSNextMapEnumeratorPair(&enumerator, (void **)(&key), &dummy))
{
[keyArray addObject: key];
}
NSEndMapTableEnumeration(&enumerator);
return keyArray;
return o;
}
/**
* Returns an array of all the values in the table.
* NB. The table <em>must</em> contain objects for its values.
*/
NSArray *
NSAllMapTableValues(NSMapTable *table)
- (id) initWithKeyPointerFunctions: (NSPointerFunctions*)keyFunctions
valuePointerFunctions: (NSPointerFunctions*)valueFunctions
capacity: (NSUInteger)initialCapacity
{
NSMapEnumerator enumerator;
NSMutableArray *valueArray;
id value = nil;
void *dummy;
if (table == 0)
{
NSWarnFLog(@"Nul table argument supplied");
return nil;
}
/* Create our mutable value array. */
valueArray = [NSMutableArray arrayWithCapacity: NSCountMapTable(table)];
/* Get an enumerator for TABLE. */
enumerator = NSEnumerateMapTable(table);
/* Step through TABLE... */
while (NSNextMapEnumeratorPair(&enumerator, &dummy, (void **)(&value)))
{
[valueArray addObject: value];
}
NSEndMapTableEnumeration(&enumerator);
return valueArray;
return [self subclassResponsibility: _cmd];
}
/**
* Compares the two map tables for equality.
* If the tables are different sizes, returns NO.
* Otherwise, compares the keys <em>(not the values)</em>
* in the two map tables and returns NO if they differ.<br />
* The GNUstep implementation enumerates the keys in table1
* and uses the hash and isEqual functions of table2 for comparison.
*/
BOOL
NSCompareMapTables(NSMapTable *table1, NSMapTable *table2)
- (id) copyWithZone: (NSZone*)aZone
{
GSIMapTable t1 = (GSIMapTable)table1;
GSIMapTable t2 = (GSIMapTable)table2;
if (t1 == t2)
{
return YES;
}
if (t1 == 0)
{
NSWarnFLog(@"Nul first argument supplied");
return NO;
}
if (t2 == 0)
{
NSWarnFLog(@"Nul second argument supplied");
return NO;
}
if (t1->nodeCount != t2->nodeCount)
{
return NO;
}
else
{
NSMapEnumerator enumerator = GSIMapEnumeratorForMap((GSIMapTable)t1);
GSIMapNode n;
while ((n = GSIMapEnumeratorNextNode(&enumerator)) != 0)
{
if (GSIMapNodeForKey(t2, n->key) == 0)
{
GSIMapEndEnumerator((GSIMapEnumerator)&enumerator);
return NO;
}
}
GSIMapEndEnumerator((GSIMapEnumerator)&enumerator);
return YES;
}
return [self subclassResponsibility: _cmd];
}
/**
* Copy the supplied map table.<br />
* Returns a map table, space for which is allocated in zone, which
* has (newly retained) copies of table's keys and values. As always,
* if zone is 0, then NSDefaultMallocZone() is used.
*/
NSMapTable *
NSCopyMapTableWithZone(NSMapTable *table, NSZone *zone)
- (NSUInteger) count
{
GSIMapTable t;
GSIMapNode n;
NSMapEnumerator enumerator;
if (table == 0)
{
NSWarnFLog(@"Nul table argument supplied");
return 0;
}
#if GS_WITH_GC
t = (GSIMapTable)NSAllocateCollectable(sizeof(GSIMapTable_t),
NSScannedOption);
zone = ((GSIMapTable)table)->zone;
#else
t = (GSIMapTable)NSZoneMalloc(zone, sizeof(GSIMapTable_t));
#endif
GSIMapInitWithZoneAndCapacity(t, zone, ((GSIMapTable)table)->nodeCount);
t->extra.k = ((GSIMapTable)table)->extra.k;
t->extra.v = ((GSIMapTable)table)->extra.v;
enumerator = GSIMapEnumeratorForMap((GSIMapTable)table);
while ((n = GSIMapEnumeratorNextNode(&enumerator)) != 0)
{
GSIMapAddPair(t, n->key, n->value);
}
GSIMapEndEnumerator((GSIMapEnumerator)&enumerator);
return (NSMapTable*)t;
return (NSUInteger)[self subclassResponsibility: _cmd];
}
/**
* Returns the number of key/value pairs in the table.
*/
unsigned int
NSCountMapTable(NSMapTable *table)
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state
objects: (id*)stackbuf
count: (NSUInteger)len
{
if (table == 0)
{
NSWarnFLog(@"Nul table argument supplied");
return 0;
}
return ((GSIMapTable)table)->nodeCount;
return (NSUInteger)[self subclassResponsibility: _cmd];
}
/**
* Create a new map table by calling NSCreateMapTableWithZone() using
* NSDefaultMallocZone().<br />
* Returns a (pointer to) an NSMapTable space for which is allocated
* in the default zone. If capacity is small or 0, then the returned
* table has a reasonable capacity.
*/
NSMapTable *
NSCreateMapTable(
NSMapTableKeyCallBacks keyCallBacks,
NSMapTableValueCallBacks valueCallBacks,
unsigned int capacity)
- (NSDictionary*) dictionaryRepresentation
{
return NSCreateMapTableWithZone(keyCallBacks, valueCallBacks,
capacity, NSDefaultMallocZone());
return [self subclassResponsibility: _cmd];
}
/**
* Create a new map table using the supplied callbacks structures.
* If any functions in the callback structures are null the default
* values are used ... as for non-owned pointers.<br />
* Of course, if you send 0 for zone, then the map table will be
* created in NSDefaultMallocZone().<br />
* The table will be created with the specified capacity ... ie ready
* to hold at least that many items.
*/
NSMapTable *
NSCreateMapTableWithZone(
NSMapTableKeyCallBacks keyCallBacks,
NSMapTableValueCallBacks valueCallBacks,
unsigned int capacity,
NSZone *zone)
- (void) encodeWithCoder: (NSCoder*)aCoder
{
GSIMapTable table;
#if GS_WITH_GC
initialize();
table = (GSIMapTable)NSAllocateCollectable(sizeof(GSIMapTable_t),
NSScannedOption);
zone = (NSZone*)nodeSS;
#else
table = (GSIMapTable)NSZoneMalloc(zone, sizeof(GSIMapTable_t));
#endif
GSIMapInitWithZoneAndCapacity(table, zone, capacity);
table->extra.k = keyCallBacks;
table->extra.v = valueCallBacks;
if (table->extra.k.hash == 0)
table->extra.k.hash = NSNonOwnedPointerMapKeyCallBacks.hash;
if (table->extra.k.isEqual == 0)
table->extra.k.isEqual = NSNonOwnedPointerMapKeyCallBacks.isEqual;
if (table->extra.k.retain == 0)
table->extra.k.retain = NSNonOwnedPointerMapKeyCallBacks.retain;
if (table->extra.k.release == 0)
table->extra.k.release = NSNonOwnedPointerMapKeyCallBacks.release;
if (table->extra.k.describe == 0)
table->extra.k.describe = NSNonOwnedPointerMapKeyCallBacks.describe;
if (table->extra.v.retain == 0)
table->extra.v.retain = NSNonOwnedPointerMapValueCallBacks.retain;
if (table->extra.v.release == 0)
table->extra.v.release = NSNonOwnedPointerMapValueCallBacks.release;
if (table->extra.v.describe == 0)
table->extra.v.describe = NSNonOwnedPointerMapValueCallBacks.describe;
return (NSMapTable*)table;
[self subclassResponsibility: _cmd];
}
/**
* Function to be called when finished with the enumerator.
* This permits memory used by the enumerator to be released!
*/
void
NSEndMapTableEnumeration(NSMapEnumerator *enumerator)
- (NSUInteger) hash
{
if (enumerator == 0)
{
NSWarnFLog(@"Nul enumerator argument supplied");
return;
}
GSIMapEndEnumerator((GSIMapEnumerator)enumerator);
return (NSUInteger)[self subclassResponsibility: _cmd];
}
/**
* Return an enumerator for stepping through a map table using the
* NSNextMapEnumeratorPair() function.
*/
NSMapEnumerator
NSEnumerateMapTable(NSMapTable *table)
- (id) initWithCoder: (NSCoder*)aCoder
{
if (table == 0)
{
NSMapEnumerator v = {0, 0};
NSWarnFLog(@"Nul table argument supplied");
return v;
}
return GSIMapEnumeratorForMap((GSIMapTable)table);
return [self subclassResponsibility: _cmd];
}
/**
* Destroy the map table and release its contents.<br />
* Releases all the keys and values of table (using the key and
* value callbacks specified at the time of table's creation),
* and then proceeds to deallocate the space allocated for table itself.
*/
void
NSFreeMapTable(NSMapTable *table)
- (BOOL) isEqual: (id)other
{
if (table == 0)
{
NSWarnFLog(@"Nul table argument supplied");
}
else
{
#if GS_WITH_GC
GSIMapEmptyMap((GSIMapTable)table);
#else
NSZone *z = ((GSIMapTable)table)->zone;
GSIMapEmptyMap((GSIMapTable)table);
NSZoneFree(z, table);
#endif
}
return (BOOL)(uintptr_t)[self subclassResponsibility: _cmd];
}
/**
* Returns the value for the specified key, or a null pointer if the
* key is not found in the table.
*/
void *
NSMapGet(NSMapTable *table, const void *key)
- (NSEnumerator*) keyEnumerator
{
GSIMapNode n;
if (table == 0)
{
NSWarnFLog(@"Nul table argument supplied");
return 0;
}
n = GSIMapNodeForKey((GSIMapTable)table, (GSIMapKey)key);
if (n == 0)
{
return 0;
}
else
{
return n->value.ptr;
}
return [self subclassResponsibility: _cmd];
}
/**
* Adds the key and value to table.<br />
* If an equal key is already in table, replaces its mapped value
* with the new one, without changing the key itself.<br />
* If key is equal to the notAKeyMarker field of the table's
* NSMapTableKeyCallBacks, raises an NSInvalidArgumentException.
*/
void
NSMapInsert(NSMapTable *table, const void *key, const void *value)
- (NSPointerFunctions*) keyPointerFunctions
{
GSIMapTable t = (GSIMapTable)table;
GSIMapNode n;
if (table == 0)
{
[NSException raise: NSInvalidArgumentException
format: @"Attempt to place key-value in null table"];
}
if (key == t->extra.k.notAKeyMarker)
{
[NSException raise: NSInvalidArgumentException
format: @"Attempt to place notAKeyMarker in map table"];
}
n = GSIMapNodeForKey(t, (GSIMapKey)key);
if (n == 0)
{
GSIMapAddPair(t, (GSIMapKey)key, (GSIMapVal)value);
}
else
{
GSIMapVal tmp = n->value;
n->value = (GSIMapVal)value;
GSI_MAP_RETAIN_VAL(t, n->value);
GSI_MAP_RELEASE_VAL(t, tmp);
}
return [self subclassResponsibility: _cmd];
}
/**
* Adds the key and value to table and returns nul.<br />
* If an equal key is already in table, returns the old key
* instead of adding the new key-value pair.<br />
* If key is equal to the notAKeyMarker field of the table's
* NSMapTableKeyCallBacks, raises an NSInvalidArgumentException.
*/
void *
NSMapInsertIfAbsent(NSMapTable *table, const void *key, const void *value)
- (NSEnumerator*) objectEnumerator
{
GSIMapTable t = (GSIMapTable)table;
GSIMapNode n;
if (table == 0)
{
[NSException raise: NSInvalidArgumentException
format: @"Attempt to place key-value in null table"];
}
if (key == t->extra.k.notAKeyMarker)
{
[NSException raise: NSInvalidArgumentException
format: @"Attempt to place notAKeyMarker in map table"];
}
n = GSIMapNodeForKey(t, (GSIMapKey)key);
if (n == 0)
{
GSIMapAddPair(t, (GSIMapKey)key, (GSIMapVal)value);
return 0;
}
else
{
return n->key.ptr;
}
return [self subclassResponsibility: _cmd];
}
/**
* Adds the key and value to table and returns nul.<br />
* If an equal key is already in table, raises an NSInvalidArgumentException.
* <br />If key is equal to the notAKeyMarker field of the table's
* NSMapTableKeyCallBacks, raises an NSInvalidArgumentException.
*/
void
NSMapInsertKnownAbsent(NSMapTable *table, const void *key, const void *value)
- (id) objectForKey: (id)aKey
{
GSIMapTable t = (GSIMapTable)table;
GSIMapNode n;
if (table == 0)
{
[NSException raise: NSInvalidArgumentException
format: @"Attempt to place key-value in null table"];
}
if (key == t->extra.k.notAKeyMarker)
{
[NSException raise: NSInvalidArgumentException
format: @"Attempt to place notAKeyMarker in map table"];
}
n = GSIMapNodeForKey(t, (GSIMapKey)key);
if (n == 0)
{
GSIMapAddPair(t, (GSIMapKey)key, (GSIMapVal)value);
}
else
{
[NSException raise: NSInvalidArgumentException
format: @"NSMapInsertKnownAbsent ... key not absent"];
}
return [self subclassResponsibility: _cmd];
}
/**
* Returns a flag to say whether the table contains the specified key.
* Returns the original key and the value it maps to.<br />
* The GNUstep implementation checks originalKey and value to see if
* they are null pointers, and only updates them if non-null.
*/
BOOL
NSMapMember(NSMapTable *table, const void *key,
void **originalKey, void **value)
- (void) removeAllObjects
{
GSIMapNode n;
if (table == 0)
{
NSWarnFLog(@"Nul table argument supplied");
return NO;
}
n = GSIMapNodeForKey((GSIMapTable)table, (GSIMapKey)key);
if (n == 0)
{
return NO;
}
else
{
if (originalKey != 0)
{
*originalKey = n->key.ptr;
}
if (value != 0)
{
*value = n->value.ptr;
}
return YES;
}
[self subclassResponsibility: _cmd];
}
/**
* Remove the specified key from the table (if present).<br />
* Causes the key and its associated value to be released.
*/
void
NSMapRemove(NSMapTable *table, const void *key)
- (void) removeObjectForKey: (id)aKey
{
if (table == 0)
{
NSWarnFLog(@"Nul table argument supplied");
return;
}
GSIMapRemoveKey((GSIMapTable)table, (GSIMapKey)key);
[self subclassResponsibility: _cmd];
}
/**
* Step through the map table ... return the next key-value pair and
* return YES, or hit the end of the table and return NO.<br />
* The enumerator parameter is a value supplied by NSEnumerateMapTable()
* and must be destroyed using NSEndMapTableEnumeration().<br />
* The GNUstep implementation permits either key or value to be a
* null pointer, and refrains from attempting to return the appropriate
* result in that case.
*/
BOOL
NSNextMapEnumeratorPair(NSMapEnumerator *enumerator,
void **key, void **value)
- (void) setObject: (id)anObject forKey: (id)aKey
{
GSIMapNode n;
if (enumerator == 0)
{
NSWarnFLog(@"Nul enumerator argument supplied");
return NO;
}
n = GSIMapEnumeratorNextNode((GSIMapEnumerator)enumerator);
if (n == 0)
{
return NO;
}
else
{
if (key != 0)
{
*key = n->key.ptr;
}
else
{
NSWarnFLog(@"Nul key return address");
}
if (value != 0)
{
*value = n->value.ptr;
}
else
{
NSWarnFLog(@"Nul value return address");
}
return YES;
}
[self subclassResponsibility: _cmd];
}
/**
* Empty the map table (releasing every key and value),
* but preserve its capacity.
*/
void
NSResetMapTable(NSMapTable *table)
- (NSPointerFunctions*) valuePointerFunctions
{
if (table == 0)
{
NSWarnFLog(@"Nul table argument supplied");
}
else
{
GSIMapCleanMap((GSIMapTable)table);
}
return [self subclassResponsibility: _cmd];
}
/**
* Returns a string describing the table contents.<br />
* For each key-value pair, a string of the form "key = value;\n"
* is appended. The appropriate describe functions are used to generate
* the strings for each key and value.
*/
NSString *
NSStringFromMapTable(NSMapTable *table)
{
GSIMapTable t = (GSIMapTable)table;
NSMutableString *string;
NSMapEnumerator enumerator;
void *key;
void *value;
if (table == 0)
{
NSWarnFLog(@"Nul table argument supplied");
return nil;
}
string = [NSMutableString stringWithCapacity: 0];
enumerator = NSEnumerateMapTable(table);
/*
* Now, just step through the elements of the table, and add their
* descriptions to the string.
*/
while (NSNextMapEnumeratorPair(&enumerator, &key, &value) == YES)
{
[string appendFormat: @"%@ = %@;\n",
(t->extra.k.describe)(table, key),
(t->extra.v.describe)(table, value)];
}
NSEndMapTableEnumeration(&enumerator);
return string;
}
/* These are to increase readabilty locally. */
typedef unsigned int (*NSMT_hash_func_t)(NSMapTable *, const void *);
typedef BOOL (*NSMT_is_equal_func_t)(NSMapTable *, const void *, const void *);
typedef void (*NSMT_retain_func_t)(NSMapTable *, const void *);
typedef void (*NSMT_release_func_t)(NSMapTable *, void *);
typedef NSString *(*NSMT_describe_func_t)(NSMapTable *, const void *);
/** For keys that are pointer-sized or smaller quantities. */
const NSMapTableKeyCallBacks NSIntMapKeyCallBacks =
{
(NSMT_hash_func_t) _NS_int_hash,
(NSMT_is_equal_func_t) _NS_int_is_equal,
(NSMT_retain_func_t) _NS_int_retain,
(NSMT_release_func_t) _NS_int_release,
(NSMT_describe_func_t) _NS_int_describe,
NSNotAnIntMapKey
};
/** For keys that are pointers not freed. */
const NSMapTableKeyCallBacks NSNonOwnedPointerMapKeyCallBacks =
{
(NSMT_hash_func_t) _NS_non_owned_void_p_hash,
(NSMT_is_equal_func_t) _NS_non_owned_void_p_is_equal,
(NSMT_retain_func_t) _NS_non_owned_void_p_retain,
(NSMT_release_func_t) _NS_non_owned_void_p_release,
(NSMT_describe_func_t) _NS_non_owned_void_p_describe,
NSNotAPointerMapKey
};
/** For keys that are pointers not freed, or 0. */
const NSMapTableKeyCallBacks NSNonOwnedPointerOrNullMapKeyCallBacks =
{
(NSMT_hash_func_t) _NS_non_owned_void_p_hash,
(NSMT_is_equal_func_t) _NS_non_owned_void_p_is_equal,
(NSMT_retain_func_t) _NS_non_owned_void_p_retain,
(NSMT_release_func_t) _NS_non_owned_void_p_release,
(NSMT_describe_func_t) _NS_non_owned_void_p_describe,
NSNotAPointerMapKey
};
/** For sets of objects without retaining and releasing. */
const NSMapTableKeyCallBacks NSNonRetainedObjectMapKeyCallBacks =
{
(NSMT_hash_func_t) _NS_non_retained_id_hash,
(NSMT_is_equal_func_t) _NS_non_retained_id_is_equal,
(NSMT_retain_func_t) _NS_non_retained_id_retain,
(NSMT_release_func_t) _NS_non_retained_id_release,
(NSMT_describe_func_t) _NS_non_retained_id_describe,
NSNotAPointerMapKey
};
/** For keys that are objects. */
const NSMapTableKeyCallBacks NSObjectMapKeyCallBacks =
{
(NSMT_hash_func_t) _NS_id_hash,
(NSMT_is_equal_func_t) _NS_id_is_equal,
(NSMT_retain_func_t) _NS_id_retain,
(NSMT_release_func_t) _NS_id_release,
(NSMT_describe_func_t) _NS_id_describe,
NSNotAPointerMapKey
};
/** For keys that are pointers with transfer of ownership upon insertion. */
const NSMapTableKeyCallBacks NSOwnedPointerMapKeyCallBacks =
{
(NSMT_hash_func_t) _NS_owned_void_p_hash,
(NSMT_is_equal_func_t) _NS_owned_void_p_is_equal,
(NSMT_retain_func_t) _NS_owned_void_p_retain,
(NSMT_release_func_t) _NS_owned_void_p_release,
(NSMT_describe_func_t) _NS_owned_void_p_describe,
NSNotAPointerMapKey
};
/** For values that are pointer-sized integer quantities. */
const NSMapTableValueCallBacks NSIntMapValueCallBacks =
{
(NSMT_retain_func_t) _NS_int_retain,
(NSMT_release_func_t) _NS_int_release,
(NSMT_describe_func_t) _NS_int_describe
};
/** For values that are pointers not freed. */
const NSMapTableValueCallBacks NSNonOwnedPointerMapValueCallBacks =
{
(NSMT_retain_func_t) _NS_non_owned_void_p_retain,
(NSMT_release_func_t) _NS_non_owned_void_p_release,
(NSMT_describe_func_t) _NS_non_owned_void_p_describe
};
/** For sets of objects without retaining and releasing. */
const NSMapTableValueCallBacks NSNonRetainedObjectMapValueCallBacks =
{
(NSMT_retain_func_t) _NS_non_retained_id_retain,
(NSMT_release_func_t) _NS_non_retained_id_release,
(NSMT_describe_func_t) _NS_non_retained_id_describe
};
/** For values that are objects. */
const NSMapTableValueCallBacks NSObjectMapValueCallBacks =
{
(NSMT_retain_func_t) _NS_id_retain,
(NSMT_release_func_t) _NS_id_release,
(NSMT_describe_func_t) _NS_id_describe
};
/** For values that are pointers with transfer of ownership upon insertion. */
const NSMapTableValueCallBacks NSOwnedPointerMapValueCallBacks =
{
(NSMT_retain_func_t) _NS_owned_void_p_retain,
(NSMT_release_func_t) _NS_owned_void_p_release,
(NSMT_describe_func_t) _NS_owned_void_p_describe
};
@end

View file

@ -74,7 +74,7 @@ Since we _have_to_ deal with this anyway, we handle it in -removePort: and
-removePort:forName:, and we don't bother removing entries in the map when
unregistering a name not for a specific port.
*/
static NSMapTable portToNamesMap;
static NSMapTable *portToNamesMap;
@interface NSMessagePortNameServer (private)

View file

@ -122,7 +122,7 @@ BOOL NSDeallocateZombies = NO;
@class NSZombie;
static Class zombieClass;
static NSMapTable zombieMap;
static NSMapTable *zombieMap;
#if !GS_WITH_GC
static void GSMakeZombie(NSObject *o)