libs-base/Source/NSHashTable.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

365 lines
9.2 KiB
Objective-C

/* NSHashTable implementation for GNUStep.
* Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Mon Dec 12 23:54:09 EST 1994
* Updated: Mon Mar 11 01:48:31 EST 1996
* Serial: 96.03.11.06
*
* 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/NSZone.h>
#include <Foundation/NSString.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSException.h>
#include <Foundation/NSHashTable.h>
#include <gnustep/base/o_hash.h>
#include "NSCallBacks.h"
/** Macros... **/
#define NSHT_CALLBACKS(T) \
(*((NSHashTableCallBacks *)(o_hash_extra((o_hash_t *)(T)))))
#define NSHT_DESCRIBE(T, P) \
(NSHT_CALLBACKS((T))).describe((T), (P))
/** Dummy callbacks... **/
size_t
_NSHT_hash(const void *element, NSHashTable *table)
{
return (NSHT_CALLBACKS(table)).hash((NSHashTable *)table, element);
}
int
_NSHT_compare(const void *element1, const void *element2, NSHashTable *table)
{
return !((NSHT_CALLBACKS(table)).isEqual(table, element1, element2));
}
int
_NSHT_is_equal(const void *element1, const void *element2, NSHashTable *table)
{
return (NSHT_CALLBACKS(table)).isEqual(table, element1, element2);
}
const void *
_NSHT_retain(const void *element, NSHashTable *table)
{
/* OpenStep (unlike we) does not allow for the possibility of
* substitution upon retaining. */
(NSHT_CALLBACKS(table)).retain(table, element);
return element;
}
void
_NSHT_release(void *element, NSHashTable *table)
{
(NSHT_CALLBACKS(table)).release(table, element);
return;
}
NSString *
_NSHT_describe(const void *element, const void *table)
{
return ((NSHT_CALLBACKS(table)).describe((NSHashTable *)table, element));
}
/* These are wrappers for getting at the real callbacks. */
o_callbacks_t _NSHT_callbacks =
{
(o_hash_func_t) _NSHT_hash,
(o_compare_func_t) _NSHT_compare,
(o_is_equal_func_t) _NSHT_is_equal,
(o_retain_func_t) _NSHT_retain,
(o_release_func_t) _NSHT_release,
(o_describe_func_t) _NSHT_describe,
0 /* Note that OpenStep decrees that '0' is the (only) forbidden value. */
};
/** Extra, extra **/
/* Make a copy of a hash table's callbacks. */
const void *
_NSHT_extra_retain (const NSHashTableCallBacks *callBacks, NSHashTable *table)
{
/* A pointer to some new callbacks. */
NSHashTableCallBacks *newCallBacks;
/* Set aside space for our new callbacks in the right zone. */
newCallBacks = (NSHashTableCallBacks *)NSZoneMalloc(o_hash_zone(table),
sizeof(NSHashTableCallBacks));
/* FIXME: Check for an invalid pointer? */
/* Copy CALLBACKS into NEWCALLBACKS. */
*newCallBacks = *callBacks;
/* Return our new callbacks. */
return (const void *) newCallBacks;
}
void
_NSHT_extra_release(NSHashTableCallBacks *callBacks, NSHashTable *table)
{
if (callBacks != 0)
NSZoneFree(o_hash_zone(table), callBacks);
return;
}
NSString *
_NSHT_extra_describe(NSHashTableCallBacks *callBacks, NSHashTable *table)
{
/* FIXME: Code this. */
return nil;
}
/* The idea here is that these callbacks ensure that the
* NSHashTableCallbacks which are associated with a given NSHashTable
* remain so associated throughout the life of the table and its copies. */
o_callbacks_t _NSHT_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) _NSHT_extra_retain,
(o_release_func_t) _NSHT_extra_release,
(o_describe_func_t) _NSHT_extra_describe,
0
};
/**** Function Implementations ***********************************************/
/** Creating NSHashTables **/
inline NSHashTable *
NSCreateHashTableWithZone(NSHashTableCallBacks callBacks,
unsigned int capacity,
NSZone *zone)
{
NSHashTable *table;
/* Build the core table. See the above for the definitions of
* the funny callbacks. */
table = o_hash_with_zone_with_callbacks(zone, _NSHT_callbacks);
/* Check to make sure our allocation has succeeded. */
if (table != 0)
{
/* Resize TABLE to CAPACITY. */
o_hash_resize(table, capacity);
/* Add CALLBACKS to TABLE. This takes care of everything for us. */
o_hash_set_extra_callbacks(table, _NSHT_extra_callbacks);
o_hash_set_extra(table, &callBacks);
}
/* Yah-hoo, kid! */
return table;
}
NSHashTable *
NSCreateHashTable(NSHashTableCallBacks callBacks,
unsigned int capacity)
{
return NSCreateHashTableWithZone(callBacks, capacity, NSDefaultMallocZone());
}
/** Copying **/
NSHashTable *
NSCopyHashTableWithZone(NSHashTable *table, NSZone *zone)
{
/* Due to the wonders of modern structure technology,
* everything we care about is automagically and safely destroyed. */
return o_hash_copy_with_zone(table, zone);
}
/** Destroying **/
void
NSFreeHashTable(NSHashTable *table)
{
/* Due to the wonders of modern technology,
* everything we care about is automagically and safely destroyed. */
o_hash_dealloc(table);
return;
}
/** Resetting **/
void
NSResetHashTable(NSHashTable *table)
{
o_hash_empty(table);
return;
}
/** Comparing **/
BOOL
NSCompareHashTables(NSHashTable *table1, NSHashTable *table2)
{
return (o_hash_is_equal_to_hash(table1, table2) ? YES : NO);
}
/** Counting **/
unsigned int
NSCountHashTable(NSHashTable *table)
{
return (unsigned int) o_hash_count(table);
}
/** Retrieving **/
void *
NSHashGet(NSHashTable *table, const void *pointer)
{
/* Just make the call. You know the number. */
return (void *) o_hash_element(table, pointer);
}
NSArray *
NSAllHashTableObjects (NSHashTable *table)
{
NSMutableArray *array;
NSHashEnumerator enumerator;
id element;
/* FIXME: We should really be locking TABLE somehow, to insure
* the thread-safeness of this method. */
/* Get us a mutable array with plenty of space. */
array = [NSMutableArray arrayWithCapacity:NSCountHashTable(table)];
/* Get an enumerator for TABLE. */
enumerator = NSEnumerateHashTable(table);
while ((element = NSNextHashEnumeratorItem(&enumerator)) != 0)
[array addObject:element];
/* ARRAY is already autoreleased. */
return (NSArray *) array;
}
/** Enumerating **/
NSHashEnumerator
NSEnumerateHashTable(NSHashTable *table)
{
return o_hash_enumerator_for_hash(table);
}
void *
NSNextHashEnumeratorItem(NSHashEnumerator *enumerator)
{
const void *element;
/* Grab the next element. */
o_hash_enumerator_next_element(enumerator, &element);
/* Return ELEMENT. */
return (void *) element;
}
/** Adding **/
void
NSHashInsert(NSHashTable *table, const void *pointer)
{
/* Place POINTER in TABLE. */
o_hash_add_element(table, pointer);
/* OpenStep doesn't care for any return value, so... */
return;
}
void
NSHashInsertKnownAbsent(NSHashTable *table, const void *element)
{
if (o_hash_contains_element(table, element))
{
/* 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:@"NSHashTable: illegal reinsertion of: %s",
[NSHT_DESCRIBE(table, element) cStringNoCopy]];
}
else
{
o_hash_add_element_known_absent(table, element);
}
/* OpenStep doesn't care for any return value, so... */
return;
}
void *
NSHashInsertIfAbsent(NSHashTable *table, const void *element)
{
const void *old_element;
/* Place ELEMENT in TABLE. */
old_element = o_hash_add_element_if_absent(table, element);
/* Return the version of ELEMENT in TABLE now. */
return (void *) old_element;
}
/** Removing **/
void
NSHashRemove(NSHashTable *table, const void *element)
{
/* Remove ELEMENT from TABLE. */
o_hash_remove_element(table, element);
/* OpenStep doesn't care about return values here, so... */
return;
}
/** Describing **/
NSString *
NSStringFromHashTable(NSHashTable *table)
{
NSMutableString *string;
NSHashEnumerator enumerator;
const void *pointer;
/* This will be our string. */
string = [NSMutableString stringWithCapacity:0];
/* Get an enumerator for TABLE. */
enumerator = NSEnumerateHashTable(table);
/* Iterate over the elements of TABLE, appending the description of
* each to the mutable string STRING. */
while ((pointer = NSNextHashEnumeratorItem(&enumerator)) != 0)
[string appendFormat:@"%s;\n",
[NSHT_DESCRIBE(table, pointer) cStringNoCopy]];
/* STRING is already autoreleased. */
return (NSString *) string;
}