libs-base/Source/NSMapTable.m
Scott Christley 369c38280a Remove dependency upon config.h by headers files and include
directly in source files because the config.h file is system
dependent, used just for compiling the source, and should
not be installed.
Some minor bug fixes.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@2619 72102866-910b-0410-8b05-ffd578937521
1997-11-06 00:51:23 +00:00

453 lines
11 KiB
Objective-C

/* NSMapTable implementation for GNUStep.
* Copyright (C) 1994, 1995, 1996 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
*
* 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 Library 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 Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/**** Included Headers *******************************************************/
#include <config.h>
#include <Foundation/NSObject.h>
#include <Foundation/NSString.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSException.h>
#include <Foundation/NSZone.h>
#include <Foundation/NSMapTable.h>
#include <gnustep/base/o_map.h>
#include "NSCallBacks.h"
/** Dummy callbacks... **/
size_t
_NSMT_key_hash (const void *element, const void *table)
{
return NSMT_KEY_CALLBACKS(table).hash((NSMapTable *)table,
element);
}
int
_NSMT_key_compare (const void *element1, const void *element2,
const void *table)
{
return !(NSMT_KEY_CALLBACKS(table).isEqual((NSMapTable *)table,
element1,
element2));
}
int
_NSMT_key_is_equal (const void *element1, const void *element2,
const void *table)
{
return NSMT_KEY_CALLBACKS(table).isEqual((NSMapTable *) table,
element1,
element2);
}
void *
_NSMT_key_retain (const void *element, const void *table)
{
NSMT_KEY_CALLBACKS(table).retain((NSMapTable *)table, element);
return (void*) element;
}
void
_NSMT_key_release (void *element, void *table)
{
NSMT_KEY_CALLBACKS(table).release ((NSMapTable*)table, element);
return;
}
NSString *
_NSMT_key_describe(const void *element, void *table)
{
return nil;
}
void *
_NSMT_value_retain (const void *element, const void *table)
{
NSMT_VALUE_CALLBACKS(table).retain((NSMapTable *)table, element);
return (void *) element;
}
void
_NSMT_value_release (void *element, const void *table)
{
NSMT_VALUE_CALLBACKS(table).release((NSMapTable *)table, element);
return;
}
NSString *
_NSMT_value_describe(const void *element, const void *table)
{
/* FIXME: Code this. */
return nil;
}
/* These are wrappers for getting at the real callbacks. */
o_callbacks_t _NSMT_key_callbacks =
{
(o_hash_func_t) _NSMT_key_hash,
(o_compare_func_t) _NSMT_key_compare,
(o_is_equal_func_t) _NSMT_key_is_equal,
(o_retain_func_t) _NSMT_key_retain,
(o_release_func_t) _NSMT_key_release,
(o_describe_func_t) _NSMT_key_describe,
0 /* This gets changed...See just below. */
};
static inline o_callbacks_t
_NSMT_callbacks_for_key_callbacks(NSMapTableKeyCallBacks keyCallBacks)
{
o_callbacks_t cbs = _NSMT_key_callbacks;
cbs.not_an_item_marker = keyCallBacks.notAKeyMarker;
return cbs;
}
o_callbacks_t _NSMT_value_callbacks =
{
(o_hash_func_t) o_non_owned_void_p_hash,
(o_compare_func_t) o_non_owned_void_p_compare,
(o_is_equal_func_t) o_non_owned_void_p_is_equal,
(o_retain_func_t) _NSMT_value_retain,
(o_release_func_t) _NSMT_value_release,
(o_describe_func_t) _NSMT_value_describe,
0 /* Not needed, really, for OpenStep...And so, ignored here. */
};
/** Extra, extra **/
/* Make a copy of a hash table's callbacks. */
const void *
_NSMT_extra_retain(_NSMT_extra_t *extra, NSMapTable *table)
{
/* A pointer to some space for new callbacks. */
_NSMT_extra_t *new_extra;
/* Set aside space for our new callbacks in the right zone. */
new_extra = (_NSMT_extra_t *)NSZoneMalloc(o_map_zone(table),
sizeof(_NSMT_extra_t));
/* Copy the old callbacks into NEW_EXTRA. */
*new_extra = *extra;
/* Return our new EXTRA. */
return new_extra;
}
void
_NSMT_extra_release(void *extra, NSMapTable *table)
{
if (extra != 0)
NSZoneFree(o_map_zone(table), extra);
return;
}
NSString *
_NSMT_extra_describe(const void *extra, NSMapTable *table)
{
/* FIXME: Code this. */
return nil;
}
/* The basic idea here is that these callbacks ensure that the
* NSMapTable...Callbacks which are associated with a given NSMapTable
* remain so throughout the life of the table and its copies. */
o_callbacks_t _NSMT_extra_callbacks =
{
(o_hash_func_t) o_non_owned_void_p_hash,
(o_compare_func_t) o_non_owned_void_p_compare,
(o_is_equal_func_t) o_non_owned_void_p_is_equal,
(o_retain_func_t) _NSMT_extra_retain,
(o_release_func_t)_NSMT_extra_release,
(o_describe_func_t)_NSMT_extra_describe,
0
};
/**** Function Implementations ****/
/** Creating an NSMapTable **/
inline NSMapTable *
NSCreateMapTableWithZone(NSMapTableKeyCallBacks keyCallBacks,
NSMapTableValueCallBacks valueCallBacks,
unsigned capacity,
NSZone *zone)
{
NSMapTable *table;
o_callbacks_t key_callbacks, value_callbacks;
/* Transform the callbacks we were given. */
key_callbacks = _NSMT_callbacks_for_key_callbacks(keyCallBacks);
value_callbacks = _NSMT_value_callbacks;
/* Create a map table. */
table = o_map_with_zone_with_callbacks(zone, key_callbacks,
value_callbacks);
/* Adjust the capacity of TABLE. */
o_map_resize(table, capacity);
if (table != 0)
{
_NSMT_extra_t extra;
/* Set aside space for TABLE's extra. */
extra.keyCallBacks = keyCallBacks;
extra.valueCallBacks = valueCallBacks;
/* These callbacks are defined above. */
o_map_set_extra_callbacks(table, _NSMT_extra_callbacks);
/* We send a pointer because that's all the room we have.
* The callbacks make a copy of these extras, so we needn't
* worry about the way they disappear real soon now. */
o_map_set_extra(table, &extra);
}
return table;
}
NSMapTable *
NSCreateMapTable(NSMapTableKeyCallBacks keyCallBacks,
NSMapTableValueCallBacks valueCallBacks,
unsigned int capacity)
{
return NSCreateMapTableWithZone(keyCallBacks, valueCallBacks,
capacity, NSDefaultMallocZone());
}
NSMapTable *
NSCopyMapTableWithZone(NSMapTable *table, NSZone *zone)
{
NSMapTable *new_table;
new_table = o_map_copy_with_zone(table, zone);
return new_table;
}
/** Freeing an NSMapTable **/
void
NSFreeMapTable(NSMapTable *table)
{
o_map_dealloc(table);
return;
}
void
NSResetMapTable(NSMapTable *table)
{
o_map_empty(table);
return;
}
/** Comparing two NSMapTables... **/
BOOL
NSCompareMapTables(NSMapTable *table1, NSMapTable *table2)
{
return o_map_is_equal_to_map(table1, table2) ? YES : NO;
}
/** Getting the number of items in an NSMapTable **/
unsigned int
NSCountMapTable(NSMapTable *table)
{
return (unsigned int) o_map_count(table);
}
/** Retrieving items from an NSMapTable **/
BOOL
NSMapMember(NSMapTable *table, const void *key,
void **originalKey, void **value)
{
int i;
/* Check for K in TABLE. */
i = o_map_key_and_value_at_key(table, (const void **)originalKey,
(const void **)value, key);
/* Indicate our state of success. */
return i ? YES : NO;
}
void *
NSMapGet(NSMapTable *table, const void *key)
{
return (void *) o_map_value_at_key(table, key);
}
NSMapEnumerator
NSEnumerateMapTable(NSMapTable *table)
{
return o_map_enumerator_for_map(table);
}
BOOL
NSNextMapEnumeratorPair(NSMapEnumerator *enumerator,
void **key, void **value)
{
int i;
/* Get the next pair. */
i = o_map_enumerator_next_key_and_value(enumerator,
(const void **)key,
(const void **)value);
/* Indicate our success or failure. */
return i ? YES : NO;
}
NSArray *
NSAllMapTableKeys(NSMapTable *table)
{
NSMutableArray *keyArray;
NSMapEnumerator enumerator;
id key = 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), 0))
[keyArray addObject:key];
return keyArray;
}
NSArray *
NSAllMapTableValues(NSMapTable *table)
{
NSMapEnumerator enumerator;
NSMutableArray *valueArray;
id value = 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, 0, (void **)(&value)))
[valueArray addObject:value];
return valueArray;
}
/** Adding items to an NSMapTable... **/
void
NSMapInsert(NSMapTable *table, const void *key, const void *value)
{
/* Put KEY -> VALUE into TABLE. */
o_map_at_key_put_value(table, key, value);
return;
}
void *
NSMapInsertIfAbsent(NSMapTable *table, const void *key, const void *value)
{
if (o_map_contains_key (table, key))
return (void *) o_map_key_at_key(table, key);
else
{
/* Put KEY -> VALUE into TABLE. */
o_map_at_key_put_value_known_absent (table, key, value);
return 0;
}
}
void
NSMapInsertKnownAbsent(NSMapTable *table, const void *key, const void *value)
{
/* Is the key already in the table? */
if (o_map_contains_key(table, key))
{
/* FIXME: I should make this give the user/programmer more
* information. Not difficult to do, just something for a later
* date. */
[NSException raise:NSInvalidArgumentException
format:@"NSMapTable: illegal reinsertion of: %s -> %s",
[NSMT_DESCRIBE_KEY(table, key) cStringNoCopy],
[NSMT_DESCRIBE_VALUE(table, value) cStringNoCopy]];
}
else
{
/* Well, we know it's not there, so... */
o_map_at_key_put_value_known_absent (table, key, value);
}
/* Yah-hoo! */
return;
}
/** Removing items from an NSMapTable **/
void
NSMapRemove(NSMapTable *table, const void *key)
{
o_map_remove_key (table, key);
return;
}
/** Getting an NSString representation of an NSMapTable **/
NSString *
NSStringFromMapTable(NSMapTable *table)
{
NSMutableString *string;
NSMapEnumerator enumerator;
NSMapTableKeyCallBacks keyCallBacks;
NSMapTableValueCallBacks valueCallBacks;
void *key, *value;
/* Get an empty mutable string. */
string = [NSMutableString stringWithCapacity:0];
/* Pull the NSMapTable...CallBacks out of the mess. */
keyCallBacks = NSMT_KEY_CALLBACKS(table);
valueCallBacks = NSMT_VALUE_CALLBACKS(table);
/* Get an enumerator for our table. */
enumerator = NSEnumerateMapTable(table);
/* Now, just step through the elements of the table, and add their
* descriptions to the string. */
while (NSNextMapEnumeratorPair(&enumerator, &key, &value))
[string appendFormat:@"%@ = %@;",
[(keyCallBacks.describe)(table, key) cStringNoCopy],
[(valueCallBacks.describe)(table, value) cStringNoCopy]];
/* Note that this string'll need to be `retain'ed. */
return string;
}