mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
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:
parent
81cc2a07a8
commit
971de91d62
11 changed files with 1391 additions and 799 deletions
14
ChangeLog
14
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 />
|
||||
|
|
|
@ -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
1081
Source/NSConcreteMapTable.m
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
NSString * const NSInvalidUnarchiveOperationException
|
||||
= @"NSInvalidUnarchiveOperationException";
|
||||
|
||||
static NSMapTable globalClassMap = 0;
|
||||
static NSMapTable *globalClassMap = 0;
|
||||
|
||||
#define GETVAL \
|
||||
id o; \
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue