mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Rewrite maptable code and clean up / simplify source.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@12273 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
d488842cc6
commit
5448f399a1
33 changed files with 888 additions and 8067 deletions
38
ChangeLog
38
ChangeLog
|
@ -1,3 +1,41 @@
|
|||
2002-01-30 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
* Headers/gnustep/base/GSIMap.h: Fix bug cleaning table and add
|
||||
option to specify type of enumerator structure externally.
|
||||
* Headers/gnustep/base/NSHashTable.h: Modify to conform to MacOS-X
|
||||
documentation and to work with GSIMAP stuff.
|
||||
* Headers/gnustep/base/NSMapTable.h: ditto
|
||||
* Headers/gnustep/base/o_array.h: deleted
|
||||
* Headers/gnustep/base/o_cbs.h: deleted
|
||||
* Headers/gnustep/base/o_hash.h: deleted
|
||||
* Headers/gnustep/base/o_list.h: deleted
|
||||
* Headers/gnustep/base/o_map.h: deleted
|
||||
* Headers/gnustep/base/o_x_bas.h.in: deleted
|
||||
* Headers/gnustep/base/o_x_cbs.h.in: deleted
|
||||
* Source/GNUmakefile: Remove o_... rules
|
||||
* Source/GSTcpPort.m: Remove unused include file
|
||||
* Source/Makefile.postamble: remove o_... rules
|
||||
* Source/NSCallBacks.h: Remove o_... info
|
||||
* Source/NSCallBacks.m: remove o_... info
|
||||
* Source/NSHashTable.m: Rewrite to use GSIMAP
|
||||
* Source/NSMapTable.m: Rewrite to use GSIMAP
|
||||
* Source/NSObject.m: Use GSIMAP for reference counts.
|
||||
* Source/NSRunLoop.m: Fix function prototypes for map table callbacks.
|
||||
* Source/externs.m: Remove o_... stuff and tidy callbacks.
|
||||
* Source/o_array.m: deleted
|
||||
* Source/o_cbs.m: deleted
|
||||
* Source/o_cbs_char_p.m: deleted
|
||||
* Source/o_cbs_id.m: deleted
|
||||
* Source/o_cbs_int.m: deleted
|
||||
* Source/o_cbs_int_p.m: deleted
|
||||
* Source/o_cbs_void_p.m: deleted
|
||||
* Source/o_hash.m: deleted
|
||||
* Source/o_list.m: deleted
|
||||
* Source/o_map.m: deleted
|
||||
* Source/o_x_bas.m.in: deleted
|
||||
* Source/o_x_cbs.m.in: deleted
|
||||
Masses of changes to simplify codebase and standardise all maptable
|
||||
code. Hopefully, the new NSMapTable code now conforms to the spec.
|
||||
|
||||
2002-01-30 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Headers/Foundation/NSRunLoop.h: revert
|
||||
|
|
|
@ -198,12 +198,10 @@
|
|||
typedef struct _GSIMapTable GSIMapTable_t;
|
||||
typedef struct _GSIMapBucket GSIMapBucket_t;
|
||||
typedef struct _GSIMapNode GSIMapNode_t;
|
||||
typedef struct _GSIMapEnumerator GSIMapEnumerator_t;
|
||||
|
||||
typedef GSIMapTable_t *GSIMapTable;
|
||||
typedef GSIMapBucket_t *GSIMapBucket;
|
||||
typedef GSIMapNode_t *GSIMapNode;
|
||||
typedef GSIMapEnumerator_t *GSIMapEnumerator;
|
||||
|
||||
struct _GSIMapNode {
|
||||
GSIMapNode nextInBucket; /* Linked list of bucket. */
|
||||
|
@ -233,10 +231,16 @@ struct _GSIMapTable {
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef GSI_MAP_ENUMERATOR
|
||||
typedef GSI_MAP_ENUMERATOR GSIMapEnumerator_t;
|
||||
#else
|
||||
struct _GSIMapEnumerator {
|
||||
GSIMapTable map; /* the map being enumerated. */
|
||||
GSIMapNode node; /* The next node to use. */
|
||||
};
|
||||
typedef struct _GSIMapEnumerator GSIMapEnumerator_t;
|
||||
#endif
|
||||
typedef GSIMapEnumerator_t *GSIMapEnumerator;
|
||||
|
||||
static INLINE GSIMapBucket
|
||||
GSIMapPickBucket(unsigned hash, GSIMapBucket buckets, size_t bucketCount)
|
||||
|
@ -772,7 +776,7 @@ GSIMapCleanMap(GSIMapTable map)
|
|||
{
|
||||
GSIMapNode node = bucket->firstNode;
|
||||
|
||||
GSIMapRemoveNodeFromBucket(bucket, node);
|
||||
GSIMapRemoveNodeFromMap(map, bucket, node);
|
||||
GSIMapFreeNode(map, node);
|
||||
}
|
||||
bucket++;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/* NSHashTable interface for GNUStep.
|
||||
* Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1994, 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Mon Dec 12 23:56:03 EST 1994
|
||||
* Updated: Thu Mar 21 15:13:46 EST 1996
|
||||
* Serial: 96.03.21.06
|
||||
* Modified by: Richard Frith-Macdonald <rfm@gnu.org>
|
||||
*
|
||||
* This file is part of the GNUstep Base Library.
|
||||
*
|
||||
|
@ -20,7 +21,8 @@
|
|||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __NSHashTable_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __NSHashTable_h_GNUSTEP_BASE_INCLUDE 1
|
||||
|
@ -30,15 +32,19 @@
|
|||
#include <Foundation/NSObject.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <base/o_hash.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
/* Hash table type. */
|
||||
typedef o_hash_t NSHashTable;
|
||||
/**
|
||||
* Hash table type ... an opaque pointer to a data structure.
|
||||
*/
|
||||
typedef void* NSHashTable;
|
||||
|
||||
/* Private type for enumerating. */
|
||||
typedef o_hash_enumerator_t NSHashEnumerator;
|
||||
/**
|
||||
* Type for enumerating.
|
||||
* NB. layout *must* correspond to that used by the GSIMap code.
|
||||
*/
|
||||
typedef struct { void *map; void *node; } NSHashEnumerator;
|
||||
|
||||
/* Callback functions. */
|
||||
typedef struct _NSHashTableCallBacks NSHashTableCallBacks;
|
||||
|
@ -56,7 +62,7 @@ struct _NSHashTableCallBacks
|
|||
|
||||
/* Releasing function called when a data element is
|
||||
* removed from the table. */
|
||||
void (*release)(NSHashTable *, void *);
|
||||
void (*release)(NSHashTable *, const void *);
|
||||
|
||||
/* Description function. */
|
||||
NSString *(*describe)(NSHashTable *, const void *);
|
||||
|
@ -81,15 +87,6 @@ GS_EXPORT const NSHashTableCallBacks NSOwnedPointerHashCallBacks;
|
|||
* struct is the size of an int. */
|
||||
GS_EXPORT const NSHashTableCallBacks NSPointerToStructHashCallBacks;
|
||||
|
||||
/* These are to increase readabilty locally. */
|
||||
typedef unsigned int (*NSHT_hash_func_t)(NSHashTable *, const void *);
|
||||
typedef BOOL (*NSHT_isEqual_func_t)(NSHashTable *, const void *, const void *);
|
||||
typedef void (*NSHT_retain_func_t)(NSHashTable *, const void *);
|
||||
typedef void (*NSHT_release_func_t)(NSHashTable *, void *);
|
||||
typedef NSString *(*NSHT_describe_func_t)(NSHashTable *, const void *);
|
||||
|
||||
/**** Function Prototypes ****************************************************/
|
||||
|
||||
/** Creating an NSHashTable... **/
|
||||
|
||||
/* Returns a (pointer to) an NSHashTable space for which is allocated
|
||||
|
@ -147,7 +144,7 @@ NSCountHashTable(NSHashTable *table);
|
|||
* member of TABLE. If not, then 0 (the only completely
|
||||
* forbidden element) is returned. */
|
||||
GS_EXPORT void *
|
||||
NSHashGet(NSHashTable *table, const void *pointer);
|
||||
NSHashGet(NSHashTable *table, const void *element);
|
||||
|
||||
/* Returns an NSArray which contains all of the elements of TABLE.
|
||||
* WARNING: Call this function only when the elements of TABLE
|
||||
|
@ -155,6 +152,9 @@ NSHashGet(NSHashTable *table, const void *pointer);
|
|||
GS_EXPORT NSArray *
|
||||
NSAllHashTableObjects(NSHashTable *table);
|
||||
|
||||
GS_EXPORT void
|
||||
NSEndHashTableEnumeration(NSHashEnumerator *enumerator);
|
||||
|
||||
/* Returns an NSHashEnumerator structure (a pointer to) which
|
||||
* can be passed repeatedly to the function 'NSNextHashEnumeratorItem()'
|
||||
* to enumerate the elements of TABLE. */
|
||||
|
@ -174,24 +174,24 @@ NSNextHashEnumeratorItem(NSHashEnumerator *enumerator);
|
|||
* incarnation is released from TABLE, and POINTER is put in its place.
|
||||
* Raises an NSInvalidArgumentException if POINTER is 0. */
|
||||
GS_EXPORT void
|
||||
NSHashInsert(NSHashTable *table, const void *pointer);
|
||||
NSHashInsert(NSHashTable *table, const void *element);
|
||||
|
||||
/* Just like 'NSHashInsert()', with one exception: If POINTER is already
|
||||
* in TABLE, then an NSInvalidArgumentException is raised. */
|
||||
GS_EXPORT void
|
||||
NSHashInsertKnownAbsent(NSHashTable *table, const void *pointer);
|
||||
NSHashInsertKnownAbsent(NSHashTable *table, const void *element);
|
||||
|
||||
/* If POINTER is already in TABLE, the pre-existing item is returned.
|
||||
* Otherwise, 0 is returned, and this is just like 'NSHashInsert()'. */
|
||||
GS_EXPORT void *
|
||||
NSHashInsertIfAbsent(NSHashTable *table, const void *pointer);
|
||||
NSHashInsertIfAbsent(NSHashTable *table, const void *element);
|
||||
|
||||
/** Removing an item from an NSHashTable... **/
|
||||
|
||||
/* Releases POINTER from TABLE. It is not
|
||||
* an error if POINTER is not already in TABLE. */
|
||||
GS_EXPORT void
|
||||
NSHashRemove(NSHashTable *table, const void *pointer);
|
||||
NSHashRemove(NSHashTable *table, const void *element);
|
||||
|
||||
/** Getting an NSString representation of an NSHashTable... **/
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/* NSMapTable interface for GNUStep.
|
||||
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1994, 1995, 1996, 2002 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>
|
||||
*
|
||||
* This file is part of the GNUstep Base Library.
|
||||
*
|
||||
|
@ -30,15 +31,19 @@
|
|||
#include <Foundation/NSObject.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <base/o_map.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
/* Map table type. */
|
||||
typedef o_map_t NSMapTable;
|
||||
/**
|
||||
* Map table type ... an opaque pointer to a data structure.
|
||||
*/
|
||||
typedef void *NSMapTable;
|
||||
|
||||
/* Private type for enumerating. */
|
||||
typedef o_map_enumerator_t NSMapEnumerator;
|
||||
/**
|
||||
* Type for enumerating.
|
||||
* NB. layout *must* correspond to that used by the GSIMap code.
|
||||
*/
|
||||
typedef struct { void *map; void *node; } NSMapEnumerator;
|
||||
|
||||
/* Callback functions for a key. */
|
||||
typedef struct _NSMapTableKeyCallBacks NSMapTableKeyCallBacks;
|
||||
|
@ -56,7 +61,7 @@ struct _NSMapTableKeyCallBacks
|
|||
|
||||
/* Releasing function called when a data element is
|
||||
* removed from the table. */
|
||||
void (*release)(NSMapTable *, void *);
|
||||
void (*release)(NSMapTable *, const void *);
|
||||
|
||||
/* Description function. */
|
||||
NSString *(*describe)(NSMapTable *, const void *);
|
||||
|
@ -74,15 +79,15 @@ struct _NSMapTableValueCallBacks
|
|||
|
||||
/* Releasing function called when a data element is
|
||||
* removed from the table. */
|
||||
void (*release)(NSMapTable *, void *);
|
||||
void (*release)(NSMapTable *, const void *);
|
||||
|
||||
/* Description function. */
|
||||
NSString *(*describe)(NSMapTable *, const void *);
|
||||
};
|
||||
|
||||
/* Quantities that are never map keys. */
|
||||
#define NSNotAnIntMapKey o_not_an_int_marker
|
||||
#define NSNotAPointerMapKey o_not_a_void_p_marker
|
||||
#define NSNotAnIntMapKey ((const void *)0x80000000)
|
||||
#define NSNotAPointerMapKey ((const void *)0xffffffff)
|
||||
|
||||
/* For keys that are pointer-sized or smaller quantities. */
|
||||
GS_EXPORT const NSMapTableKeyCallBacks NSIntMapKeyCallBacks;
|
||||
|
@ -117,42 +122,6 @@ GS_EXPORT const NSMapTableValueCallBacks NSObjectMapValueCallBacks;
|
|||
/* For values that are pointers with transfer of ownership upon insertion. */
|
||||
GS_EXPORT const NSMapTableValueCallBacks NSOwnedPointerMapValueCallBacks;
|
||||
|
||||
/* This is for keeping track of information... */
|
||||
typedef struct _NSMT_extra _NSMT_extra_t;
|
||||
|
||||
struct _NSMT_extra
|
||||
{
|
||||
NSMapTableKeyCallBacks keyCallBacks;
|
||||
NSMapTableValueCallBacks valueCallBacks;
|
||||
};
|
||||
|
||||
/* 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 *);
|
||||
|
||||
/** Macros... **/
|
||||
|
||||
#define NSMT_EXTRA(T) \
|
||||
((_NSMT_extra_t *)(o_map_extra((o_map_t *)(T))))
|
||||
|
||||
#define NSMT_KEY_CALLBACKS(T) \
|
||||
((NSMT_EXTRA((T)))->keyCallBacks)
|
||||
|
||||
#define NSMT_VALUE_CALLBACKS(T) \
|
||||
((NSMT_EXTRA((T)))->valueCallBacks)
|
||||
|
||||
#define NSMT_DESCRIBE_KEY(T, P) \
|
||||
NSMT_KEY_CALLBACKS((T)).describe((T), (P))
|
||||
|
||||
#define NSMT_DESCRIBE_VALUE(T, P) \
|
||||
NSMT_VALUE_CALLBACKS((T)).describe((T), (P))
|
||||
|
||||
/**** Function Prototypes ****************************************************/
|
||||
|
||||
/** Creating an NSMapTable... **/
|
||||
|
||||
/* Returns a (pointer to) an NSMapTable space for which is allocated
|
||||
|
@ -224,6 +193,9 @@ NSMapMember(NSMapTable *table,
|
|||
GS_EXPORT void *
|
||||
NSMapGet(NSMapTable *table, const void *key);
|
||||
|
||||
GS_EXPORT void
|
||||
NSEndMapTableEnumeration(NSMapEnumerator *enumerator);
|
||||
|
||||
/* Returns an NSMapEnumerator structure (a pointer to) which
|
||||
* can be passed repeatedly to the function 'NSNextMapEnumeratorPair()'
|
||||
* to enumerate the key/value pairs of TABLE. */
|
||||
|
|
|
@ -1,247 +0,0 @@
|
|||
/* A sparse array structure.
|
||||
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Thu Mar 2 02:30:02 EST 1994
|
||||
* Updated: Tue Mar 12 02:42:54 EST 1996
|
||||
* Serial: 96.03.12.13
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#ifndef __array_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __array_h_GNUSTEP_BASE_INCLUDE 1
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <Foundation/NSZone.h>
|
||||
#include <base/o_cbs.h>
|
||||
#include <base/o_hash.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
typedef struct _o_array o_array_t;
|
||||
typedef struct _o_array_bucket o_array_bucket_t;
|
||||
typedef o_array_bucket_t *o_array_slot_t;
|
||||
typedef struct _o_array_enumerator o_array_enumerator_t;
|
||||
|
||||
struct _o_array_bucket
|
||||
{
|
||||
/* The bucket's real (or external) index */
|
||||
size_t index;
|
||||
|
||||
/* The bucket's cargo */
|
||||
const void *element;
|
||||
};
|
||||
|
||||
struct _o_array
|
||||
{
|
||||
/* Identifying information. */
|
||||
int magic_number;
|
||||
size_t serial_number;
|
||||
NSString *name;
|
||||
const void *extra;
|
||||
o_callbacks_t extra_callbacks;
|
||||
|
||||
/* Callbacks for the items in the array. */
|
||||
o_callbacks_t callbacks;
|
||||
|
||||
/* Internal counters */
|
||||
size_t slot_count;
|
||||
size_t element_count;
|
||||
|
||||
/* Databanks */
|
||||
o_array_slot_t *slots;
|
||||
o_array_slot_t *sorted_slots;
|
||||
};
|
||||
|
||||
struct _o_array_enumerator
|
||||
{
|
||||
o_array_t *array;
|
||||
size_t index;
|
||||
int is_sorted;
|
||||
int is_ascending;
|
||||
};
|
||||
|
||||
/**** Function Prototypes ****************************************************/
|
||||
|
||||
/** Basics **/
|
||||
|
||||
#include <base/o_array_bas.h>
|
||||
#include <base/o_array_cbs.h>
|
||||
|
||||
/** Creating **/
|
||||
|
||||
o_array_t *
|
||||
o_array_alloc(void);
|
||||
|
||||
o_array_t *
|
||||
o_array_alloc_with_zone(NSZone *zone);
|
||||
|
||||
o_array_t *
|
||||
o_array(void);
|
||||
|
||||
o_array_t *
|
||||
o_array_with_zone(NSZone *zone);
|
||||
|
||||
o_array_t *
|
||||
o_array_with_zone_with_callbacks(NSZone *zone,
|
||||
o_callbacks_t callbacks);
|
||||
|
||||
o_array_t *
|
||||
o_array_with_callbacks(o_callbacks_t callbacks);
|
||||
|
||||
o_array_t *
|
||||
o_array_of_char_p(void);
|
||||
|
||||
o_array_t *
|
||||
o_array_of_non_owned_void_p(void);
|
||||
|
||||
o_array_t *
|
||||
o_array_of_owned_void_p(void);
|
||||
|
||||
o_array_t *
|
||||
o_array_of_int(void);
|
||||
|
||||
o_array_t *
|
||||
o_array_of_id(void);
|
||||
|
||||
/** Initializing **/
|
||||
|
||||
o_array_t *
|
||||
o_array_init(o_array_t *array);
|
||||
|
||||
o_array_t *
|
||||
o_array_init_with_callbacks(o_array_t *array,
|
||||
o_callbacks_t callbacks);
|
||||
|
||||
o_array_t *
|
||||
o_array_init_with_array(o_array_t *array,
|
||||
o_array_t *other_array);
|
||||
|
||||
/** Copying **/
|
||||
|
||||
o_array_t *
|
||||
o_array_copy(o_array_t *array);
|
||||
|
||||
o_array_t *
|
||||
o_array_copy_with_zone(o_array_t *array, NSZone *zone);
|
||||
|
||||
/** Destroying **/
|
||||
|
||||
void
|
||||
o_array_dealloc(o_array_t *array);
|
||||
|
||||
/** Comparing **/
|
||||
|
||||
int
|
||||
o_array_is_equal_to_array(o_array_t *array,
|
||||
o_array_t *other_array);
|
||||
|
||||
/** Adding **/
|
||||
|
||||
const void *
|
||||
o_array_at_index_put_element(o_array_t *array,
|
||||
size_t index,
|
||||
const void *element);
|
||||
|
||||
/** Replacing **/
|
||||
|
||||
/** Removing **/
|
||||
|
||||
void
|
||||
o_array_remove_element_at_index(o_array_t *array, size_t index);
|
||||
|
||||
void
|
||||
o_array_remove_element(o_array_t *array, const void *element);
|
||||
|
||||
void
|
||||
o_array_remove_element_known_present(o_array_t *array,
|
||||
const void *element);
|
||||
|
||||
/** Emptying **/
|
||||
|
||||
void
|
||||
o_array_empty(o_array_t *array);
|
||||
|
||||
/** Searching **/
|
||||
|
||||
int
|
||||
o_array_contains_element(o_array_t *array, const void *element);
|
||||
|
||||
const void *
|
||||
o_array_element(o_array_t *array, const void *element);
|
||||
|
||||
size_t
|
||||
o_array_index_of_element(o_array_t *array, const void *element);
|
||||
|
||||
const void *
|
||||
o_array_element_at_index(o_array_t *array, size_t index);
|
||||
|
||||
const void **
|
||||
o_array_all_elements(o_array_t *array);
|
||||
|
||||
const void **
|
||||
o_array_all_elements_ascending(o_array_t *array);
|
||||
|
||||
const void **
|
||||
o_array_all_element_descending(o_array_t *array);
|
||||
|
||||
/** Enumerating **/
|
||||
|
||||
o_array_enumerator_t
|
||||
o_array_enumerator(o_array_t *array);
|
||||
|
||||
o_array_enumerator_t
|
||||
o_array_ascending_enumerator(o_array_t *array);
|
||||
|
||||
o_array_enumerator_t
|
||||
o_array_descending_enumerator(o_array_t *array);
|
||||
|
||||
int
|
||||
o_array_enumerator_next_index_and_element(o_array_enumerator_t *enumerator,
|
||||
size_t *index,
|
||||
const void **element);
|
||||
|
||||
int
|
||||
o_array_enumerator_next_element(o_array_enumerator_t *enumerator,
|
||||
const void **element);
|
||||
|
||||
int
|
||||
o_array_enumerator_next_index(o_array_enumerator_t *enumerator,
|
||||
size_t *element);
|
||||
|
||||
/** Statistics **/
|
||||
|
||||
int
|
||||
o_array_is_empty(o_array_t *array);
|
||||
|
||||
size_t
|
||||
o_array_count(o_array_t *array);
|
||||
|
||||
size_t
|
||||
o_array_capacity(o_array_t *array);
|
||||
|
||||
int
|
||||
o_array_check(o_array_t *array);
|
||||
|
||||
/** Miscellaneous **/
|
||||
|
||||
o_hash_t *
|
||||
o_hash_init_from_array(o_hash_t *hash, o_array_t *array);
|
||||
|
||||
#endif /* __array_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,179 +0,0 @@
|
|||
/* Handling various types in a uniform manner.
|
||||
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Sun Oct 9 13:18:50 EDT 1994
|
||||
* Updated: Mon Mar 11 00:31:13 EST 1996
|
||||
* Serial: 96.03.11.01
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#ifndef __callbacks_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __callbacks_h_GNUSTEP_BASE_INCLUDE 1
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
typedef size_t (*o_hash_func_t)(const void *, void *);
|
||||
typedef int (*o_compare_func_t)(const void *, const void *, void *);
|
||||
typedef int (*o_is_equal_func_t)(const void *, const void *, void *);
|
||||
typedef const void *(*o_retain_func_t)(const void *, void *);
|
||||
typedef void (*o_release_func_t)(void *, void *);
|
||||
typedef NSString *(*o_describe_func_t)(const void *, void *);
|
||||
|
||||
typedef struct _o_callbacks o_callbacks_t;
|
||||
|
||||
struct _o_callbacks
|
||||
{
|
||||
o_hash_func_t hash;
|
||||
o_compare_func_t compare;
|
||||
o_is_equal_func_t is_equal;
|
||||
o_retain_func_t retain;
|
||||
o_release_func_t release;
|
||||
o_describe_func_t describe;
|
||||
const void *not_an_item_marker;
|
||||
};
|
||||
|
||||
/** Callbacks for various types **/
|
||||
|
||||
extern const o_callbacks_t o_callbacks_for_int;
|
||||
extern const o_callbacks_t o_callbacks_for_char_p;
|
||||
extern const o_callbacks_t o_callbacks_for_non_owned_void_p;
|
||||
extern const o_callbacks_t o_callbacks_for_owned_void_p;
|
||||
extern const o_callbacks_t o_callbacks_for_int_p;
|
||||
extern const o_callbacks_t o_callbacks_for_id;
|
||||
|
||||
/* FIXME: I need to figure out what each of these should be. Hmmm? */
|
||||
extern const void *o_not_an_int_marker;
|
||||
extern const void *o_not_a_char_p_marker;
|
||||
extern const void *o_not_a_void_p_marker;
|
||||
extern const void *o_not_an_int_p_marker;
|
||||
extern const void *o_not_an_id_marker;
|
||||
|
||||
/* Change this if you need different default callbacks. */
|
||||
extern o_callbacks_t __o_callbacks_standard;
|
||||
|
||||
/**** Function Prototypes ****************************************************/
|
||||
|
||||
/** Generic callbacks **/
|
||||
|
||||
/* Returns the programmer-alterable `__o_callbacks_standard',
|
||||
* defined above. */
|
||||
o_callbacks_t
|
||||
o_callbacks_standard(void);
|
||||
|
||||
/** Standardizing callbacks **/
|
||||
|
||||
/* Makes sure that enough of CALLBACKS is defined (i.e., non-zero)
|
||||
* to be used. This is used, rather than local checks for usability,
|
||||
* to improve the efficiency of callback use. */
|
||||
o_callbacks_t
|
||||
o_callbacks_standardize(o_callbacks_t callbacks);
|
||||
|
||||
/** Using callbacks **/
|
||||
|
||||
size_t
|
||||
o_hash(o_callbacks_t callbacks,
|
||||
const void *thing,
|
||||
void *user_data);
|
||||
|
||||
int
|
||||
o_compare(o_callbacks_t callbacks,
|
||||
const void *thing1,
|
||||
const void *thing2,
|
||||
void *user_data);
|
||||
|
||||
int
|
||||
o_is_equal(o_callbacks_t callbacks,
|
||||
const void *thing1,
|
||||
const void *thing2,
|
||||
void *user_data);
|
||||
|
||||
const void *
|
||||
o_retain(o_callbacks_t callbacks,
|
||||
const void *thing,
|
||||
void *user_data);
|
||||
|
||||
void
|
||||
o_release(o_callbacks_t callbacks,
|
||||
void *thing,
|
||||
void *user_data);
|
||||
|
||||
NSString *
|
||||
o_describe(o_callbacks_t callbacks,
|
||||
const void *thing,
|
||||
void *user_data);
|
||||
|
||||
const void *
|
||||
o_not_an_item_marker(o_callbacks_t callbacks);
|
||||
|
||||
/** Specific callback functions... **/
|
||||
|
||||
/* For non-owned `void *' */
|
||||
size_t o_non_owned_void_p_hash(const void *ptr);
|
||||
int o_non_owned_void_p_compare(const void *ptr, const void *qtr);
|
||||
int o_non_owned_void_p_is_equal(const void *ptr, const void *qtr);
|
||||
const void *o_non_owned_void_p_retain(const void *ptr);
|
||||
void o_non_owned_void_p_release(void *ptr);
|
||||
NSString *o_non_owned_void_p_describe(const void *ptr);
|
||||
|
||||
/* For owned `void *' */
|
||||
size_t o_owned_void_p_hash(const void *ptr);
|
||||
int o_owned_void_p_compare(const void *ptr, const void *qtr);
|
||||
int o_owned_void_p_is_equal(const void *ptr, const void *qtr);
|
||||
const void *o_owned_void_p_retain(const void *ptr);
|
||||
void o_owned_void_p_release(void *ptr);
|
||||
NSString *o_owned_void_p_describe(const void *ptr);
|
||||
|
||||
/* For `int' */
|
||||
size_t o_int_hash(int i);
|
||||
int o_int_compare(int i, int j);
|
||||
int o_int_is_equal(int i, int j);
|
||||
const void *o_int_retain(int i);
|
||||
void o_int_release(int i);
|
||||
NSString *o_int_describe(int i);
|
||||
|
||||
/* For `int *' */
|
||||
size_t o_int_p_hash(const int *iptr);
|
||||
int o_int_p_compare(const int *iptr, const int *jptr);
|
||||
int o_int_p_is_equal(const int *iptr, const int *jptr);
|
||||
const void *o_int_p_retain(const int *iptr);
|
||||
void o_int_p_release(int *iptr);
|
||||
NSString *o_int_p_describe(const int *iptr);
|
||||
|
||||
/* For `char *' */
|
||||
size_t o_char_p_hash(const char *cptr);
|
||||
int o_char_p_compare(const char *cptr, const char *dptr);
|
||||
int o_char_p_is_equal(const char *cptr, const char *dptr);
|
||||
const void *o_char_p_retain(const char *cptr);
|
||||
void o_char_p_release(char *cptr);
|
||||
NSString *o_char_p_describe(const char *cptr);
|
||||
|
||||
/* For `id' */
|
||||
size_t o_id_hash(id obj);
|
||||
int o_id_compare(id obj, id jbo);
|
||||
int o_id_is_equal(id obj, id jbo);
|
||||
const void *o_id_retain(id obj);
|
||||
void o_id_release(id obj);
|
||||
NSString *o_id_describe(id obj);
|
||||
|
||||
#endif /* __callbacks_h_GNUSTEP_BASE_INCLUDE */
|
||||
|
|
@ -1,392 +0,0 @@
|
|||
/* A hash table.
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: ??? ??? ?? ??:??:?? ??? 1993
|
||||
* Updated: Tue Mar 19 00:25:34 EST 1996
|
||||
* Serial: 96.03.19.05
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#ifndef __hash_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __hash_h_GNUSTEP_BASE_INCLUDE 1
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <Foundation/NSZone.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <base/o_cbs.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
/* Need these up here because of their interdependence. */
|
||||
typedef struct _o_hash o_hash_t;
|
||||
typedef struct _o_hash_enumerator o_hash_enumerator_t;
|
||||
typedef struct _o_hash_node o_hash_node_t;
|
||||
typedef struct _o_hash_bucket o_hash_bucket_t;
|
||||
|
||||
/* Private type for elemental holding. */
|
||||
struct _o_hash_node
|
||||
{
|
||||
/* The hash table with which the node is associated. */
|
||||
o_hash_t *hash;
|
||||
|
||||
/* The bucket in HASH in which the node sits. */
|
||||
o_hash_bucket_t *bucket;
|
||||
|
||||
/* These hold the BUCKET linked list together. */
|
||||
o_hash_node_t *next_in_bucket;
|
||||
o_hash_node_t *prev_in_bucket;
|
||||
|
||||
/* For enumerating over the whole hash table. These make
|
||||
* enumerating much quicker. They also make it safer. */
|
||||
o_hash_node_t *next_in_hash;
|
||||
o_hash_node_t *prev_in_hash;
|
||||
|
||||
/* What the node is holding for us. Its raison d'etre. */
|
||||
const void *element;
|
||||
};
|
||||
|
||||
/* Private type for holding chains of nodes. */
|
||||
struct _o_hash_bucket
|
||||
{
|
||||
/* The number of nodes in this bucket. For internal consistency checks. */
|
||||
size_t node_count;
|
||||
|
||||
/* The number of elements in this bucket. (This had *better* be
|
||||
* the same as NODE_COUNT, or something's wrong.) */
|
||||
size_t element_count;
|
||||
|
||||
/* The head of this bucket's linked list of nodes. */
|
||||
o_hash_node_t *first_node;
|
||||
};
|
||||
|
||||
/* The hash table type. */
|
||||
struct _o_hash
|
||||
{
|
||||
/* All structures have these...
|
||||
* And all structures have them in the same order. */
|
||||
int magic_number;
|
||||
size_t serial_number;
|
||||
NSString *name;
|
||||
const void *extra;
|
||||
o_callbacks_t extra_callbacks;
|
||||
|
||||
/* Callbacks for the elements of the hash. */
|
||||
o_callbacks_t callbacks;
|
||||
|
||||
/* Internal counters. Mainly for consistency's sake. */
|
||||
size_t bucket_count; /* How many types of items? */
|
||||
size_t node_count; /* How many items? */
|
||||
size_t element_count; /* How many elements? */
|
||||
|
||||
/* Places to start looking for elements. */
|
||||
o_hash_bucket_t *buckets; /* Organized as a hash. */
|
||||
o_hash_node_t *first_node; /* Organized as a linked list.
|
||||
* (For enumerating...) */
|
||||
};
|
||||
|
||||
/* Type for enumerating the elements of a hash table. */
|
||||
struct _o_hash_enumerator
|
||||
{
|
||||
o_hash_t *hash; /* To which hash do I belong? */
|
||||
o_hash_node_t *node; /* Which node is next? */
|
||||
};
|
||||
|
||||
/**** Function Prototypes ****************************************************/
|
||||
|
||||
/** Basics... **/
|
||||
|
||||
/* All the structures (hashes, maps, lists, and arrays) have
|
||||
* the same basic ideas behind them. */
|
||||
|
||||
#include <base/o_hash_bas.h>
|
||||
#include <base/o_hash_cbs.h>
|
||||
|
||||
/** Callbacks... **/
|
||||
|
||||
/* Returns a collection of callbacks for use with hash tables. */
|
||||
o_callbacks_t
|
||||
o_callbacks_for_hash(void);
|
||||
|
||||
/** Creating... **/
|
||||
|
||||
/* Allocate a hash table in the default zone. */
|
||||
o_hash_t *
|
||||
o_hash_alloc(void);
|
||||
|
||||
/* Allocate a hash table in the memory block ZONE. */
|
||||
o_hash_t *
|
||||
o_hash_alloc_with_zone(NSZone *zone);
|
||||
|
||||
/* Create an empty hash table in the memory block ZONE. The returned
|
||||
* hash table has a "reasonable" default capacity, but will need to
|
||||
* be resized to suit your specific needs if more than a couple of
|
||||
* dozen elements will be placed within it. */
|
||||
o_hash_t *
|
||||
o_hash_with_zone_with_callbacks(NSZone *zone,
|
||||
o_callbacks_t callbacks);
|
||||
|
||||
/* Like calling 'o_hash_with_zone_with_callbacks(zone,
|
||||
* o_callbacks_standard())'. */
|
||||
o_hash_t *
|
||||
o_hash_with_zone(NSZone *zone);
|
||||
|
||||
/* Like calling 'o_hash_with_zone_with_callbacks(0, callbacks)'. */
|
||||
o_hash_t *
|
||||
o_hash_with_callbacks(o_callbacks_t callbacks);
|
||||
|
||||
/* These are just shortcuts for ease of use. */
|
||||
o_hash_t *o_hash_of_char_p(void);
|
||||
o_hash_t *o_hash_of_non_owned_void_p(void);
|
||||
o_hash_t *o_hash_of_owned_void_p(void);
|
||||
o_hash_t *o_hash_of_int(void);
|
||||
o_hash_t *o_hash_of_int_p(void);
|
||||
o_hash_t *o_hash_of_id(void);
|
||||
|
||||
/** Initializing... **/
|
||||
|
||||
/* Initializes HASH with a "reasonable" capacity, with the
|
||||
* callbacks obtained from 'o_callbacks_standard()'. */
|
||||
o_hash_t *
|
||||
o_hash_init(o_hash_t *hash);
|
||||
|
||||
/* Initializes HASH with a "reasonable" capacity and
|
||||
* with element callbacks CALLBACKS. */
|
||||
o_hash_t *
|
||||
o_hash_init_with_callbacks(o_hash_t *hash,
|
||||
o_callbacks_t callbacks);
|
||||
|
||||
/* Initializes HASH with the capacity, callbacks, and contents
|
||||
* of OTHER_HASH. NOTE: This is (as it must be) a "shallow" copying.
|
||||
* See 'o_hash_copy_with_zone()', below. */
|
||||
o_hash_t *
|
||||
o_hash_init_with_hash(o_hash_t *hash,
|
||||
o_hash_t *other_hash);
|
||||
|
||||
/** Copying... **/
|
||||
|
||||
/* Creates a (shallow) copy of HASH in the memory block ZONE. WARNING:
|
||||
* If the elements of HASH are pointers to mutable items, it is the
|
||||
* programmer's responsibility to deepen the copy returned by this
|
||||
* function call (using, for example, `o_hash_map_elements()'). */
|
||||
o_hash_t *
|
||||
o_hash_copy_with_zone(o_hash_t *hash, NSZone *zone);
|
||||
|
||||
/* Create a (shallow) copy of HASH in the default zone. WARNING: See the
|
||||
* above function for an important caveat about copying. */
|
||||
o_hash_t *
|
||||
o_hash_copy(o_hash_t *old_hash);
|
||||
|
||||
/** Mapping... **/
|
||||
|
||||
/* WARNING: The mapping function FCN must be one-to-one on elements of
|
||||
* HASH. I.e., for reasons of efficiency, `o_hash_map_elements()'
|
||||
* makes no provision for the possibility that FCN maps two unequal
|
||||
* elements of HASH to the same (or "equal") elements. The better way
|
||||
* to handle functions that aren't one-to-one is to create a new hash
|
||||
* and transform the elements of the first to create the elements of
|
||||
* the second (by manual enumeration). */
|
||||
o_hash_t *
|
||||
o_hash_map_elements(o_hash_t *hash,
|
||||
const void *(*fcn)(const void *, const void *),
|
||||
const void *user_data);
|
||||
|
||||
/** Destroying... **/
|
||||
|
||||
/* Releases all the elements of HASH, and then frees up the space
|
||||
* HASH used. HASH is no longer a (pointer to a) valid hash
|
||||
* table structure after this call. */
|
||||
void
|
||||
o_hash_dealloc(o_hash_t *hash);
|
||||
|
||||
/** Comparing... **/
|
||||
|
||||
/* Returns 'true' if every element of OTHER_HASH is also
|
||||
* a member of HASH. Otherwise, returns 'false'. */
|
||||
int
|
||||
o_hash_contains_hash(o_hash_t *hash,
|
||||
o_hash_t *other_hash);
|
||||
|
||||
/* Returns 'true' if some element of HASH is also
|
||||
* a member of OTHER_HASH. Otherwise, returns 'false'. */
|
||||
int
|
||||
o_hash_intersects_hash(o_hash_t *hash,
|
||||
o_hash_t *other_hash);
|
||||
|
||||
/* Returns 'true' if HASH and OTHER_HASH have the same number of elements,
|
||||
* HASH contains OTHER_HASH, and OTHER_HASH contains HASH. Otheraise, returns 'false'. */
|
||||
int
|
||||
o_hash_is_equal_to_hash(o_hash_t *hash,
|
||||
o_hash_t *other_hash);
|
||||
|
||||
/** Adding... **/
|
||||
|
||||
/* Adds ELEMENT to HASH. If ELEMENT is "equal" to an item already in HASH,
|
||||
* then we abort. If ELEMENT is the "not an element marker" for HASH,
|
||||
* then we abort. [NOTE: This abortive behaviour will be changed in a
|
||||
* future revision.] */
|
||||
const void *
|
||||
o_hash_add_element_known_absent(o_hash_t *hash,
|
||||
const void *element);
|
||||
|
||||
/* Adds ELEMENT to HASH. If ELEMENT is "equal" to an item already in HASH,
|
||||
* then that older item is released using the 'release()' callback function
|
||||
* that was specified when HASH was created. (If ELEMENT is the "not an
|
||||
* element marker" for HASH, then all bets are off, and we abort.
|
||||
* [NOTE: This abortive behaviour will be changed in a future revision.]) */
|
||||
const void *
|
||||
o_hash_add_element(o_hash_t *hash, const void *element);
|
||||
|
||||
/* If (any item "equal" to) ELEMENT is in HASH, then that member of HASH is
|
||||
* returned. Otherwise, the "not an element marker" for HASH is returned
|
||||
* and ELEMENT is added to HASH. If ELEMENT is the "not an element marker"
|
||||
* for HASH, then we abort. [NOTE: This abortive behaviour will be changed
|
||||
* in a future revision.] */
|
||||
const void *
|
||||
o_hash_add_element_if_absent(o_hash_t *hash, const void *element);
|
||||
|
||||
/** Replacing... **/
|
||||
|
||||
/* If (some item "equal" to) ELEMENT is an element of HASH, then ELEMENT is
|
||||
* substituted for it. The old element is released. (This is rather
|
||||
* like the non-existant but perfectly reasonable function
|
||||
* 'o_hash_add_element_if_present()'.) */
|
||||
void
|
||||
o_hash_replace_element(o_hash_t *hash,
|
||||
const void *element);
|
||||
|
||||
/** Removing... **/
|
||||
|
||||
/* Removes the element (if any) of HASH which is "equal" to ELEMENT,
|
||||
* according to HASH's element callbacks. It is not an error to
|
||||
* remove ELEMENT from HASH, if no element of HASH is "equal" to ELEMENT. */
|
||||
void
|
||||
o_hash_remove_element(o_hash_t *hash, const void *element);
|
||||
|
||||
/** Emptying... **/
|
||||
|
||||
/* Empties HASH, releasing all of its elements while retaining
|
||||
* its current "capacity". */
|
||||
void
|
||||
o_hash_empty(o_hash_t *hash);
|
||||
|
||||
/** Searching... **/
|
||||
|
||||
/* Returns a "random" element of HASH, for your viewing enjoyment. */
|
||||
void *
|
||||
o_hash_any_element(o_hash_t *hash);
|
||||
|
||||
/* Returns `true' if some element of HASH is "equal" to ELEMENT,
|
||||
* according to HASH's element callbacks. */
|
||||
int
|
||||
o_hash_contains_element(o_hash_t *hash, const void *element);
|
||||
|
||||
/* Returns the element of HASH (or the appropriate `not an element
|
||||
* marker' if there is none) which is "equal" to ELEMENT. */
|
||||
const void *
|
||||
o_hash_element(o_hash_t *hash, const void *element);
|
||||
|
||||
/* Returns an array with all the elements of HASH, terminated
|
||||
* by HASH's "not an element marker". It is your responsibility
|
||||
* to free the returned array. [NOTE: this responsibility may
|
||||
* shift from your shoulders in a later revision.] */
|
||||
const void **
|
||||
o_hash_all_elements(o_hash_t *hash);
|
||||
|
||||
/** Enumerating... **/
|
||||
|
||||
/* Returns an enumerator for HASH's elements. WARNING: DO NOT ALTER
|
||||
* A HASH DURING AN ENUMERATION. DOING SO WILL PROBABLY LEAVE YOUR ENUMERATION
|
||||
* IN AN INDETERMINATE STATE. If you are hell-bent on ignoring the above
|
||||
* warning, please check out the source code for some more specific
|
||||
* information about when and how one can get away with it. */
|
||||
o_hash_enumerator_t
|
||||
o_hash_enumerator_for_hash(o_hash_t *hash);
|
||||
|
||||
/* Returns `false' if the enumeration is complete, `true' otherwise.
|
||||
* If ELEMENT is non-zero, the next element of ENUMERATOR's hash table
|
||||
* is returned by reference. */
|
||||
int
|
||||
o_hash_enumerator_next_element(o_hash_enumerator_t *enumerator,
|
||||
const void **element);
|
||||
|
||||
/** Statistics... **/
|
||||
|
||||
/* Returns `true' if HASH contains no elements. */
|
||||
int
|
||||
o_hash_is_empty(o_hash_t *hash);
|
||||
|
||||
/* Returns the number of elements HASH is currently holding. So long as no
|
||||
* additions or removals occur, you may take this number to be accurate. */
|
||||
size_t
|
||||
o_hash_count(o_hash_t *hash);
|
||||
|
||||
/* Returns a number which represents (to some degree) HASH's current ability
|
||||
* to hold stuff. Do not, however, rely on this for precision. Treat as
|
||||
* a (reasonable) estimate. */
|
||||
size_t
|
||||
o_hash_capacity(o_hash_t *hash);
|
||||
|
||||
/* Performs an internal consistency check on HASH. Useful only
|
||||
* for debugging. */
|
||||
int
|
||||
o_hash_check(o_hash_t *hash);
|
||||
|
||||
/** Resizing... **/
|
||||
|
||||
/* Resizes HASH to be ready to contain (at least) NEW_CAPACITY many elements.
|
||||
* However, as far as you are concerned, it is indeterminate what exactly
|
||||
* this means. After receiving and successfully processing this call,
|
||||
* you are *not* guaranteed that HASH has actually set aside space for
|
||||
* NEW_CAPACITY elements, for example. All that you are guaranteed is that,
|
||||
* to the best of its ability, HASH will incur no loss in efficiency so long
|
||||
* as it contains no more than NEW_CAPACITY elements. */
|
||||
size_t
|
||||
o_hash_resize(o_hash_t *hash, size_t new_capacity);
|
||||
|
||||
/* Shrinks (or grows) HASH to be comfortable with the number of elements
|
||||
* it contains. In all likelyhood, after this call, HASH is more efficient
|
||||
* in terms of its speed of search vs. use of space balance. */
|
||||
size_t
|
||||
o_hash_rightsize(o_hash_t *hash);
|
||||
|
||||
/** Describing... **/
|
||||
|
||||
/* Returns a string describing (the contents of) HASH. */
|
||||
NSString *
|
||||
o_hash_description(o_hash_t *hash);
|
||||
|
||||
/** Set theoretic operations... **/
|
||||
|
||||
/* Removes from HASH all of its elements which are not also
|
||||
* elements of OTHER_HASH. Returns HASH as a courtesy. */
|
||||
o_hash_t *
|
||||
o_hash_intersect_hash(o_hash_t *hash, o_hash_t *other_hash);
|
||||
|
||||
/* Removes from HASH all of its elements which are also
|
||||
* elements of OTHER_HASH. Returns HASH as a courtesy. */
|
||||
o_hash_t *
|
||||
o_hash_minus_hash(o_hash_t *hash, o_hash_t *other_hash);
|
||||
|
||||
/* Adds to HASH all elements of OTHER_HASH which are not
|
||||
* already members of HASH. Returns HASH as a courtesy. */
|
||||
o_hash_t *
|
||||
o_hash_union_hash(o_hash_t *hash, o_hash_t *other_hash);
|
||||
|
||||
#endif /* __hash_h_GNUSTEP_BASE_INCLUDE */
|
||||
|
|
@ -1,345 +0,0 @@
|
|||
/* A list structure.
|
||||
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Tue Sep 5 17:25:59 EDT 1995
|
||||
* Updated: Sun Mar 10 23:24:49 EST 1996
|
||||
* Serial: 96.03.10.02
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#ifndef __list_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __list_h_GNUSTEP_BASE_INCLUDE 1
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <Foundation/NSZone.h>
|
||||
#include <base/o_cbs.h>
|
||||
#include <base/o_hash.h>
|
||||
#include <base/o_array.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
typedef struct _o_list o_list_t;
|
||||
typedef struct _o_list_node o_list_node_t;
|
||||
typedef struct _o_list_enumerator o_list_enumerator_t;
|
||||
|
||||
struct _o_list_node
|
||||
{
|
||||
o_list_t *list;
|
||||
|
||||
o_list_node_t *next_in_list;
|
||||
o_list_node_t *prev_in_list;
|
||||
|
||||
const void *element;
|
||||
};
|
||||
|
||||
struct _o_list
|
||||
{
|
||||
/* Container identifiers */
|
||||
int magic_number;
|
||||
size_t serial_number;
|
||||
NSString *name;
|
||||
const void *extra;
|
||||
o_callbacks_t extra_callbacks;
|
||||
|
||||
/* Element callbacks */
|
||||
o_callbacks_t callbacks;
|
||||
|
||||
/* Internal counters */
|
||||
size_t node_count;
|
||||
size_t element_count;
|
||||
|
||||
/* Databanks */
|
||||
o_list_node_t *first_node;
|
||||
o_list_node_t *last_node;
|
||||
};
|
||||
|
||||
struct _o_list_enumerator
|
||||
{
|
||||
o_list_t *list;
|
||||
o_list_node_t *node;
|
||||
size_t forward;
|
||||
};
|
||||
|
||||
|
||||
/**** Function Prototypes ****************************************************/
|
||||
|
||||
/** Basics **/
|
||||
|
||||
#include <base/o_list_bas.h>
|
||||
#include <base/o_list_cbs.h>
|
||||
|
||||
/** Creating **/
|
||||
|
||||
o_list_t *
|
||||
o_list_alloc(void);
|
||||
|
||||
o_list_t *
|
||||
o_list_alloc_with_zone(NSZone *zone);
|
||||
|
||||
o_list_t *
|
||||
o_list_with_zone(NSZone *zone);
|
||||
|
||||
o_list_t *
|
||||
o_list_with_callbacks(o_callbacks_t callbacks);
|
||||
|
||||
o_list_t *
|
||||
o_list_with_zone_with_callbacks(NSZone *zone,
|
||||
o_callbacks_t callbacks);
|
||||
|
||||
o_list_t *
|
||||
o_list_of_char_p(void);
|
||||
|
||||
o_list_t *
|
||||
o_list_of_non_owned_void_p(void);
|
||||
|
||||
o_list_t *
|
||||
o_list_of_owned_void_p(void);
|
||||
|
||||
o_list_t *
|
||||
o_list_of_int(void);
|
||||
|
||||
o_list_t *
|
||||
o_list_of_int_p(void);
|
||||
|
||||
o_list_t *
|
||||
o_list_of_id(void);
|
||||
|
||||
/** Initializing **/
|
||||
|
||||
o_list_t *
|
||||
o_list_init(o_list_t *list);
|
||||
|
||||
o_list_t *
|
||||
o_list_init_with_callbacks(o_list_t *list,
|
||||
o_callbacks_t callbacks);
|
||||
|
||||
/** Copying **/
|
||||
|
||||
o_list_t *
|
||||
o_list_copy(o_list_t *old_list);
|
||||
|
||||
o_list_t *
|
||||
o_list_copy_with_zone(o_list_t *old_list,
|
||||
NSZone *zone);
|
||||
|
||||
/** Destroying **/
|
||||
|
||||
void
|
||||
o_list_dealloc(o_list_t *list);
|
||||
|
||||
/** Comparing **/
|
||||
|
||||
int
|
||||
o_list_is_equal_to_list(o_list_t *list,
|
||||
o_list_t *other_list);
|
||||
|
||||
/** Concatenating **/
|
||||
|
||||
o_list_t *
|
||||
o_list_append_list(o_list_t *base_list,
|
||||
o_list_t *suffix_list);
|
||||
|
||||
o_list_t *
|
||||
o_list_prepend_list(o_list_t *base_list,
|
||||
o_list_t *prefix_list);
|
||||
|
||||
o_list_t *
|
||||
o_list_at_index_insert_list(o_list_t *base_list,
|
||||
long int n,
|
||||
o_list_t *infix_list);
|
||||
|
||||
/** Permuting **/
|
||||
|
||||
o_list_t *
|
||||
o_list_roll_to_nth_element(o_list_t *list, long int n);
|
||||
|
||||
o_list_t *
|
||||
o_list_roll_to_element(o_list_t *list, const void *element);
|
||||
|
||||
o_list_t *
|
||||
o_list_roll_to_nth_occurrance_of_element(o_list_t *list,
|
||||
long int n,
|
||||
const void *element);
|
||||
|
||||
o_list_t *
|
||||
o_list_invert(o_list_t *list);
|
||||
|
||||
o_list_t *
|
||||
o_list_swap_elements_at_indices(o_list_t *list,
|
||||
long int m,
|
||||
long int n);
|
||||
|
||||
/** Adding **/
|
||||
|
||||
const void *
|
||||
o_list_append_element(o_list_t *list, const void *element);
|
||||
|
||||
const void *
|
||||
o_list_append_element_if_absent(o_list_t *list,
|
||||
const void *element);
|
||||
|
||||
const void *
|
||||
o_list_prepend_element(o_list_t *list, const void *element);
|
||||
|
||||
const void *
|
||||
o_list_prepend_element_if_absent(o_list_t *list,
|
||||
const void *element);
|
||||
|
||||
const void *
|
||||
o_list_at_index_insert_element(o_list_t *list,
|
||||
long int n,
|
||||
const void *element);
|
||||
|
||||
const void *
|
||||
o_list_at_index_insert_element_if_absent(o_list_t *list,
|
||||
long int n,
|
||||
const void *element);
|
||||
|
||||
const void *
|
||||
o_list_queue_push_element(o_list_t *list, const void *element);
|
||||
|
||||
const void *
|
||||
o_list_stack_push_element(o_list_t *list, const void *element);
|
||||
|
||||
/** Replacing **/
|
||||
|
||||
void
|
||||
o_list_replace_nth_occurrance_of_element(o_list_t *list,
|
||||
long int n,
|
||||
const void *old_element,
|
||||
const void *new_element);
|
||||
|
||||
void
|
||||
o_list_replace_element(o_list_t *list,
|
||||
const void *old_element,
|
||||
const void *new_element);
|
||||
|
||||
void
|
||||
o_list_replace_nth_element(o_list_t *list,
|
||||
long int n,
|
||||
const void *new_element);
|
||||
|
||||
void
|
||||
o_list_replace_first_element(o_list_t *list,
|
||||
const void *new_element);
|
||||
|
||||
void
|
||||
o_list_replace_last_element(o_list_t *list,
|
||||
const void *new_element);
|
||||
|
||||
/** Removing **/
|
||||
|
||||
void
|
||||
o_list_remove_nth_occurrence_of_element(o_list_t *list,
|
||||
long int n,
|
||||
const void *element);
|
||||
|
||||
void
|
||||
o_list_remove_element(o_list_t *list, const void *element);
|
||||
|
||||
void
|
||||
o_list_remove_nth_element(o_list_t *list, long int n);
|
||||
|
||||
void
|
||||
o_list_remove_first_element(o_list_t *list);
|
||||
|
||||
void
|
||||
o_list_remove_last_element(o_list_t *list);
|
||||
|
||||
void
|
||||
o_list_queue_pop_element(o_list_t *list);
|
||||
|
||||
void
|
||||
o_list_queue_pop_nth_element(o_list_t *list, long int n);
|
||||
|
||||
void
|
||||
o_list_stack_pop_element(o_list_t *list);
|
||||
|
||||
void
|
||||
o_list_stack_pop_nth_element(o_list_t *list, long int n);
|
||||
|
||||
/** Emptying **/
|
||||
|
||||
void
|
||||
o_list_empty(o_list_t *list);
|
||||
|
||||
/** Searching **/
|
||||
|
||||
int
|
||||
o_list_contains_element(o_list_t *list, const void *element);
|
||||
|
||||
const void *
|
||||
o_list_element(o_list_t *list, const void *element);
|
||||
|
||||
const void *
|
||||
o_list_nth_element(o_list_t *list, long int n);
|
||||
|
||||
const void *
|
||||
o_list_first_element(o_list_t *list);
|
||||
|
||||
const void *
|
||||
o_list_last_element(o_list_t *list);
|
||||
|
||||
const void **
|
||||
o_list_all_elements(o_list_t *list);
|
||||
|
||||
/** Enumerating **/
|
||||
|
||||
o_list_enumerator_t
|
||||
o_list_enumerator(o_list_t *list);
|
||||
|
||||
o_list_enumerator_t
|
||||
o_list_forward_enumerator(o_list_t *list);
|
||||
|
||||
o_list_enumerator_t
|
||||
o_list_reverse_enumerator(o_list_t *list);
|
||||
|
||||
int
|
||||
o_list_enumerator_next_element(o_list_enumerator_t *enumerator,
|
||||
const void **element);
|
||||
|
||||
/** Mapping **/
|
||||
|
||||
/* NO WARNING: The mapping function FCN need not be one-to-one on the
|
||||
* elements of LIST. In fact, FCN may do whatever it likes. */
|
||||
o_list_t *
|
||||
o_list_map_elements(o_list_t *list,
|
||||
const void *(*fcn)(const void *, void *),
|
||||
void *user_data);
|
||||
|
||||
/** Statistics **/
|
||||
|
||||
int
|
||||
o_list_is_empty(o_list_t *list);
|
||||
|
||||
size_t
|
||||
o_list_count(o_list_t *list);
|
||||
|
||||
size_t
|
||||
o_list_capacity(o_list_t *list);
|
||||
|
||||
int
|
||||
o_list_check(o_list_t *list);
|
||||
|
||||
/** Miscellaneous **/
|
||||
|
||||
o_hash_t *
|
||||
o_hash_init_from_list(o_hash_t *hash, o_list_t *list);
|
||||
|
||||
#endif /* __list_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,428 +0,0 @@
|
|||
/* A map table.
|
||||
* Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: ??? ??? ?? ??:??:?? ??? 1993
|
||||
* Updated: Thu Mar 21 00:05:43 EST 1996
|
||||
* Serial: 96.03.20.04
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#ifndef __map_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __map_h_GNUSTEP_BASE_INCLUDE 1
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <Foundation/NSZone.h>
|
||||
#include <base/o_cbs.h>
|
||||
#include <base/o_hash.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
/* Need these up here because of their interdependence. */
|
||||
typedef struct _o_map o_map_t;
|
||||
typedef struct _o_map_bucket o_map_bucket_t;
|
||||
typedef struct _o_map_node o_map_node_t;
|
||||
typedef struct _o_map_enumerator o_map_enumerator_t;
|
||||
|
||||
/* Important structures... */
|
||||
|
||||
/* Private type for elemental holding. */
|
||||
struct _o_map_node
|
||||
{
|
||||
/* The map table with which the node is associated. */
|
||||
o_map_t *map;
|
||||
|
||||
/* The bucket in MAP in which the node sits. */
|
||||
o_map_bucket_t *bucket;
|
||||
|
||||
/* These hold the BUCKET linked list together. */
|
||||
o_map_node_t *next_in_bucket;
|
||||
o_map_node_t *prev_in_bucket;
|
||||
|
||||
/* For enumerating over the whole map table. These make
|
||||
* enumerating much quicker. They also make it safer. */
|
||||
o_map_node_t *next_in_map;
|
||||
o_map_node_t *prev_in_map;
|
||||
|
||||
const void *key;
|
||||
const void *value;
|
||||
};
|
||||
|
||||
/* Private type for holding chains of nodes. */
|
||||
struct _o_map_bucket
|
||||
{
|
||||
/* The number of nodes in this bucket. For internal consistency checks. */
|
||||
size_t node_count;
|
||||
|
||||
/* The number of elements in this bucket. (This had *better* be
|
||||
* the same as NODE_COUNT, or something's wrong.) */
|
||||
size_t element_count;
|
||||
|
||||
/* The head of this bucket's linked list of nodes. */
|
||||
o_map_node_t *first_node;
|
||||
};
|
||||
|
||||
/* The map table type. */
|
||||
struct _o_map
|
||||
{
|
||||
/* All structures have these...
|
||||
* And all structures have them in the same order. */
|
||||
int magic_number;
|
||||
size_t serial_number;
|
||||
NSString *name;
|
||||
const void *extra;
|
||||
o_callbacks_t extra_callbacks;
|
||||
|
||||
/* For keys...And Values. */
|
||||
o_callbacks_t key_callbacks;
|
||||
o_callbacks_t value_callbacks;
|
||||
|
||||
/* Internal counters */
|
||||
size_t bucket_count;
|
||||
size_t node_count;
|
||||
size_t element_count;
|
||||
|
||||
/* Places to start looking for elements. */
|
||||
o_map_bucket_t *buckets; /* Organized as a hash. */
|
||||
o_map_node_t *first_node; /* Organized as a linked list.
|
||||
* (For enumerating...) */
|
||||
};
|
||||
|
||||
/* Type for enumerating the elements of a map table. */
|
||||
struct _o_map_enumerator
|
||||
{
|
||||
o_map_t *map; /* To which hash do I belong? */
|
||||
o_map_node_t *node; /* Which node is next? */
|
||||
};
|
||||
|
||||
/**** Function Prototypes ****************************************************/
|
||||
|
||||
/** Basics... **/
|
||||
|
||||
/* All the structures (hashes, maps, lists, and arrays) have
|
||||
* the same basic ideas behind them. */
|
||||
|
||||
#include <base/o_map_bas.h>
|
||||
#include <base/o_map_cbs.h>
|
||||
|
||||
/** Callbacks... **/
|
||||
|
||||
/* Returns a collection of callbacks for use with hash tables. */
|
||||
o_callbacks_t
|
||||
o_callbacks_for_map(void);
|
||||
|
||||
/** Creating... **/
|
||||
|
||||
/* Allocate a hash table in the default zone. */
|
||||
o_map_t *
|
||||
o_map_alloc(void);
|
||||
|
||||
/* Allocate a hash table in the memory block ZONE. */
|
||||
o_map_t *
|
||||
o_map_alloc_with_zone(NSZone *zone);
|
||||
|
||||
/* Create an empty map table in the memory block ZONE. The returned
|
||||
* hash table has a "reasonable" default capacity, but will need to
|
||||
* be resized to suit your specific needs if more than a couple of
|
||||
* dozen key/value pairs will be placed within it. */
|
||||
o_map_t *
|
||||
o_map_with_zone_with_callbacks(NSZone *zone,
|
||||
o_callbacks_t key_callbacks,
|
||||
o_callbacks_t value_callbacks);
|
||||
|
||||
/* Like calling 'o_map_with_zone_with_callbacks(0, key_callbacks,
|
||||
* value_callbacks)'. */
|
||||
o_map_t *
|
||||
o_map_with_callbacks(o_callbacks_t key_callbacks,
|
||||
o_callbacks_t value_callbacks);
|
||||
|
||||
/* Like calling 'o_map_with_zone_with_callbacks(0,
|
||||
* o_callbacks_standard(), o_callbacks_standard())'. */
|
||||
o_map_t *
|
||||
o_map_with_zone(NSZone *zone);
|
||||
|
||||
/* Shortcuts... */
|
||||
o_map_t *o_map_of_int(void);
|
||||
o_map_t *o_map_of_int_to_char_p(void);
|
||||
o_map_t *o_map_of_int_to_non_owned_void_p(void);
|
||||
o_map_t *o_map_of_int_to_id(void);
|
||||
o_map_t *o_map_of_char_p(void);
|
||||
o_map_t *o_map_of_char_p_to_int(void);
|
||||
o_map_t *o_map_of_char_p_to_non_owned_void_p(void);
|
||||
o_map_t *o_map_of_char_p_to_id(void);
|
||||
o_map_t *o_map_of_non_owned_void_p(void);
|
||||
o_map_t *o_map_of_non_owned_void_p_to_int(void);
|
||||
o_map_t *o_map_of_non_owned_void_p_to_char_p(void);
|
||||
o_map_t *o_map_of_non_owned_void_p_to_id(void);
|
||||
o_map_t *o_map_of_id(void);
|
||||
|
||||
/** Initializing... **/
|
||||
|
||||
o_map_t *
|
||||
o_map_init(o_map_t *map);
|
||||
|
||||
o_map_t *
|
||||
o_map_init_with_callbacks(o_map_t *map,
|
||||
o_callbacks_t key_callbacks,
|
||||
o_callbacks_t value_callbacks);
|
||||
|
||||
o_map_t *
|
||||
object_map_init_from_map(o_map_t *map, o_map_t *old_map);
|
||||
|
||||
/** Destroying... **/
|
||||
|
||||
/* Releases all the keys and values of MAP, and then
|
||||
* deallocates MAP itself. */
|
||||
void
|
||||
o_map_dealloc(o_map_t *map);
|
||||
|
||||
/** Gathering statistics on a map... **/
|
||||
|
||||
/* Returns the number of key/value pairs in MAP. */
|
||||
size_t
|
||||
o_map_count(o_map_t *map);
|
||||
|
||||
/* Returns some (inexact) measure of how many key/value pairs
|
||||
* MAP can comfortably hold without resizing. */
|
||||
size_t
|
||||
o_map_capacity(o_map_t *map);
|
||||
|
||||
/* Performs an internal consistency check, returns 'true' if
|
||||
* everything is OK, 'false' otherwise. Really useful only
|
||||
* for debugging. */
|
||||
int
|
||||
o_map_check(o_map_t *map);
|
||||
|
||||
/** Finding elements in a map... **/
|
||||
|
||||
/* Returns 'true' if and only if some key in MAP is equal
|
||||
* (in the sense of the key callbacks of MAP) to KEY. */
|
||||
int
|
||||
o_map_contains_key(o_map_t *map, const void *key);
|
||||
|
||||
/* Returns 'true' if and only if some value in MAP is equal
|
||||
* (in the sense of the value callbacks of MAP) to VALUE. */
|
||||
/* WARNING: This is rather inefficient. Not to be used lightly. */
|
||||
int
|
||||
o_map_contains_value(o_map_t *map, const void *value);
|
||||
|
||||
/* If KEY is in MAP, then the following three things happen:
|
||||
* (1) 'true' is returned;
|
||||
* (2) if OLD_KEY is non-zero, then the key in MAP
|
||||
* equal to KEY is placed there;
|
||||
* (3) if VALUE is non-zero, then the value in MAP
|
||||
* mapped to by KEY is placed there.
|
||||
* If KEY is not in MAP, then the following three things happen:
|
||||
* (1) 'false' is returned;
|
||||
* (2) if OLD_KEY is non-zero, then the "not a key marker"
|
||||
* for MAP is placed there;
|
||||
* (3) if VALUE is non-zero, then the the "not a value marker"
|
||||
* for MAP is placed there. */
|
||||
int
|
||||
o_map_key_and_value_at_key(o_map_t *map,
|
||||
const void **old_key,
|
||||
const void **value,
|
||||
const void *key);
|
||||
|
||||
/* If KEY is in MAP, then the key of MAP which is equal to KEY
|
||||
* is returned. Otherwise, the "not a key marker" for MAP is returned. */
|
||||
const void *
|
||||
o_map_key_at_key(o_map_t *map, const void *key);
|
||||
|
||||
/* If KEY is in MAP, then the value of MAP which to which KEY maps
|
||||
* is returned. Otherwise, the "not a value marker" for MAP is returned. */
|
||||
const void *
|
||||
o_map_value_at_key(o_map_t *map, const void *key);
|
||||
|
||||
/** Enumerating the nodes and elements of a map... **/
|
||||
|
||||
o_map_enumerator_t
|
||||
o_map_enumerator_for_map(o_map_t *map);
|
||||
|
||||
int
|
||||
o_map_enumerator_next_key_and_value(o_map_enumerator_t *enumerator,
|
||||
const void **key,
|
||||
const void **value);
|
||||
|
||||
int
|
||||
o_map_enumerator_next_key(o_map_enumerator_t *enumerator,
|
||||
const void **key);
|
||||
|
||||
int
|
||||
o_map_enumerator_next_value(o_map_enumerator_t *enumerator,
|
||||
const void **value);
|
||||
|
||||
/** Obtaining an array of the elements of a map... **/
|
||||
|
||||
const void **
|
||||
o_map_all_keys_and_values(o_map_t *map);
|
||||
|
||||
const void **
|
||||
o_map_all_keys(o_map_t *map);
|
||||
|
||||
const void **
|
||||
o_map_all_values(o_map_t *map);
|
||||
|
||||
/** Removing... **/
|
||||
|
||||
/* Removes the key/value pair (if any) from MAP whose key is KEY. */
|
||||
void
|
||||
o_map_remove_key(o_map_t *map, const void *key);
|
||||
|
||||
/* Releases all of the keys and values of MAP without
|
||||
* altering MAP's capacity. */
|
||||
void
|
||||
o_map_empty(o_map_t *map);
|
||||
|
||||
/** Adding... **/
|
||||
|
||||
const void *
|
||||
o_map_at_key_put_value_known_absent(o_map_t *map,
|
||||
const void *key,
|
||||
const void *value);
|
||||
|
||||
const void *
|
||||
o_map_at_key_put_value(o_map_t *map,
|
||||
const void *key,
|
||||
const void *value);
|
||||
|
||||
const void *
|
||||
o_map_at_key_put_value_if_absent(o_map_t *map,
|
||||
const void *key,
|
||||
const void *value);
|
||||
|
||||
/** Replacing... **/
|
||||
|
||||
void
|
||||
o_map_replace_key(o_map_t *map, const void *key);
|
||||
|
||||
/** Comparing... **/
|
||||
|
||||
/* Returns 'true' if every key/value pair of MAP2 is also a key/value pair
|
||||
* of MAP1. Otherwise, returns 'false'. */
|
||||
int
|
||||
o_map_contains_map(o_map_t *map1, o_map_t *map2);
|
||||
|
||||
/* Returns 'true' if MAP1 and MAP2 have the same number of key/value pairs,
|
||||
* MAP1 contains MAP2, and MAP2 contains MAP1. Otherwise, returns 'false'. */
|
||||
int
|
||||
o_map_is_equal_to_map(o_map_t *map1, o_map_t *map2);
|
||||
|
||||
/* Returns 'true' iff every key of MAP2 is a key of MAP1. */
|
||||
int
|
||||
o_map_keys_contain_keys_of_map(o_map_t *map1, o_map_t *map2);
|
||||
|
||||
/* Returns 'true' if MAP1 and MAP2 have the same number of key/value pairs,
|
||||
* MAP1 contains every key of MAP2, and MAP2 contains every key of MAP1.
|
||||
* Otherwise, returns 'false'. */
|
||||
int
|
||||
o_map_keys_are_equal_to_keys_of_map(o_map_t *map1,
|
||||
o_map_t *map2);
|
||||
|
||||
/* Returns 'true' iff some key/value pair of MAP1 if also
|
||||
* a key/value pair of MAP2. */
|
||||
int
|
||||
o_map_intersects_map(o_map_t *map1, o_map_t *map2);
|
||||
|
||||
/* Returns 'true' iff some key of MAP1 if also a key of MAP2. */
|
||||
int
|
||||
o_map_keys_intersect_keys_of_map(o_map_t *map1,
|
||||
o_map_t *map2);
|
||||
/** Copying... **/
|
||||
|
||||
/* Returns a copy of OLD_MAP in ZONE. Remember that, as far as what
|
||||
* (if anything) OLD_MAP's keys and values point to, this copy is
|
||||
* shallow. If, for example, OLD_MAP is a map from int to int, then
|
||||
* you've got nothing more to worry about. If, however, OLD_MAP is a
|
||||
* map from id to id, and you want the copy of OLD_MAP to be "deep",
|
||||
* you'll need to use the mapping functions below to make copies of
|
||||
* all of the returned map's elements. */
|
||||
o_map_t *
|
||||
o_map_copy_with_zone(o_map_t *old_map, NSZone *zone);
|
||||
|
||||
/* Just like 'o_map_copy_with_zone()', but returns a copy of
|
||||
* OLD_MAP in the default zone. */
|
||||
o_map_t *
|
||||
o_map_copy(o_map_t *old_map);
|
||||
|
||||
/** Mapping... **/
|
||||
|
||||
/* Iterates through MAP, replacing each key with the result of
|
||||
* '(*kfcn)(key, user_data)'. Useful for deepening copied maps
|
||||
* and other uniform (and one-to-one) transformations of map keys. */
|
||||
/* WARNING: The mapping function KFCN *must* be one-to-one on the
|
||||
* (equivalence classes of) keys of MAP. I.e., for efficiency's sake,
|
||||
* `o_map_map_keys()' makes no provision for the possibility
|
||||
* that KFCN maps two unequal keys of MAP to the same (or equal) keys. */
|
||||
o_map_t *
|
||||
o_map_map_keys(o_map_t *map,
|
||||
const void *(*kfcn)(const void *, void *),
|
||||
void *user_data);
|
||||
|
||||
/* Iterates through MAP, replacing each value with the result of
|
||||
* '(*vfcn)(value, user_data)'. Useful for deepening copied maps
|
||||
* and other uniform transformations of map keys. */
|
||||
/* NO WARNING: The mapping function VFCN need not be one-to-one on
|
||||
* (the equivalence classes of) values. */
|
||||
o_map_t *
|
||||
o_map_map_values(o_map_t *map,
|
||||
const void *(*vfcn)(const void *, void *),
|
||||
void *user_data);
|
||||
|
||||
/** Resizing... **/
|
||||
|
||||
/* Resizes MAP to be ready to contain (at least) NEW_CAPACITY many elements.
|
||||
* However, as far as you are concerned, it is indeterminate what exactly
|
||||
* this means. After receiving and successfully processing this call,
|
||||
* you are *not* guaranteed that MAP has actually set aside space for
|
||||
* NEW_CAPACITY elements, for example. All that you are guaranteed is that,
|
||||
* to the best of its ability, MAP will incur no loss in efficiency so long
|
||||
* as it contains no more than NEW_CAPACITY elements. */
|
||||
size_t
|
||||
o_map_resize(o_map_t *map, size_t new_capacity);
|
||||
|
||||
/* Shrinks (or grows) MAP to be comfortable with the number of elements
|
||||
* it contains. In all likelyhood, after this call, MAP is more efficient
|
||||
* in terms of its speed of search vs. use of space balance. */
|
||||
size_t
|
||||
o_map_rightsize(o_map_t *map);
|
||||
|
||||
/** Describing... **/
|
||||
|
||||
/* Returns a string describing (the contents of) MAP. */
|
||||
NSString *
|
||||
o_map_description(o_map_t *map);
|
||||
|
||||
/** Set theoretic operations... **/
|
||||
|
||||
o_map_t *
|
||||
o_map_intersect_map(o_map_t *map, o_map_t *other_map);
|
||||
|
||||
o_map_t *
|
||||
o_map_minus_map(o_map_t *map, o_map_t *other_map);
|
||||
|
||||
o_map_t *
|
||||
o_map_union_map(o_map_t *map, o_map_t *other_map);
|
||||
|
||||
o_hash_t *
|
||||
o_hash_init_from_map_keys(o_hash_t *hash, o_map_t *map);
|
||||
|
||||
o_hash_t *
|
||||
o_hash_init_from_map_values(o_hash_t *hash, o_map_t *map);
|
||||
|
||||
#endif /* __map_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,126 +0,0 @@
|
|||
/* Basic functions for @XX@ structures.
|
||||
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Mon Dec 11 01:24:48 EST 1995
|
||||
* Updated: Mon Mar 11 00:54:50 EST 1996
|
||||
* Serial: 96.03.11.03
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#ifndef __@XX@_bas_h_OBJECTS_INCLUDE
|
||||
#define __@XX@_bas_h_OBJECTS_INCLUDE 1
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <Foundation/NSZone.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <base/numbers.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
#define __@XX@__ 1
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
/** Magic numbers... **/
|
||||
|
||||
/* Returns XX's magic number. */
|
||||
int
|
||||
o_@XX@_magic_number(o_@XX@_t *xx);
|
||||
|
||||
/** Zones... **/
|
||||
|
||||
/* Returns the allocs used to create and maintain XX. */
|
||||
NSZone *
|
||||
o_@XX@_zone(o_@XX@_t *xx);
|
||||
|
||||
/** Names... **/
|
||||
|
||||
/* Returns the name that was given to XX. */
|
||||
NSString *
|
||||
o_@XX@_name(o_@XX@_t *xx);
|
||||
|
||||
/* Gives XX a name. */
|
||||
void
|
||||
o_@XX@_set_name(o_@XX@_t *xx, NSString *name);
|
||||
|
||||
/* Takes away XX's name. */
|
||||
void
|
||||
o_@XX@_unset_name(o_@XX@_t *xx);
|
||||
|
||||
/** Serial numbers... **/
|
||||
|
||||
/* Returns the (process-wide) unique number given to the Libfn
|
||||
* structure XX. See <gnustep/base/numbers.h> for more info. */
|
||||
size_t
|
||||
o_@XX@_serial_number(o_@XX@_t *xx);
|
||||
|
||||
/* Gives XX a new (process-wide) unique number. Numbers are not
|
||||
* reused. See <gnustep/base/numbers.h> for more info. */
|
||||
size_t
|
||||
_o_@XX@_set_serial_number(o_@XX@_t *xx);
|
||||
|
||||
/** Extras... **/
|
||||
|
||||
/* Sets the callbacks associated with XX's ``extra''. NOTE: This must
|
||||
* be done before calling `o_@XX@_set_extra()', as these callbacks
|
||||
* are used in that routine. */
|
||||
o_callbacks_t
|
||||
o_@XX@_set_extra_callbacks(o_@XX@_t *xx,
|
||||
o_callbacks_t callbacks);
|
||||
|
||||
/* Returns the callbacks associated with XX's ``extra''. */
|
||||
o_callbacks_t
|
||||
o_@XX@_extra_callbacks(o_@XX@_t *xx);
|
||||
|
||||
/* Returns XX's ``extra'', a little extra space that each
|
||||
* structure carries around with it. Its use is
|
||||
* implementation-dependent. */
|
||||
const void *
|
||||
o_@XX@_extra(o_@XX@_t *xx);
|
||||
|
||||
/* Sets XX's ``extra'', a little extra space that each structure
|
||||
* carries around with it. Its use is implementation-dependent. */
|
||||
const void *
|
||||
o_@XX@_set_extra(o_@XX@_t *xx, const void *extra);
|
||||
|
||||
/* Resets XX's ``extra''. */
|
||||
void
|
||||
o_@XX@_unset_extra(o_@XX@_t *xx);
|
||||
|
||||
/** Low-level Creation and Destruction **/
|
||||
|
||||
/* Handles the universal, low-level allocation of structures. */
|
||||
o_@XX@_t *
|
||||
_o_@XX@_alloc_with_zone(NSZone *zone);
|
||||
|
||||
/* Handles the universal, low-level deallocation of structures. */
|
||||
void
|
||||
_o_@XX@_dealloc(o_@XX@_t *xx);
|
||||
|
||||
/* Handles the low-level copying of structures. */
|
||||
o_@XX@_t *
|
||||
_o_@XX@_copy_with_zone(o_@XX@_t *xx, NSZone *zone);
|
||||
|
||||
/* Returns a low-level description of XX. */
|
||||
NSString *
|
||||
_o_@XX@_description(o_@XX@_t *xx);
|
||||
|
||||
#endif /* __@XX@_bas_h_OBJECTS_INCLUDE */
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
/* Getting callbacks from @YY@ structures.
|
||||
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Mon Dec 11 03:41:00 EST 1995
|
||||
* Updated: Mon Mar 11 00:54:20 EST 1996
|
||||
* Serial: 96.03.11.02
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#ifndef __@YY@_cbs_h_OBJECTS_INCLUDE
|
||||
#define __@YY@_cbs_h_OBJECTS_INCLUDE 1
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <base/o_cbs.h>
|
||||
#include <base/o_@YY@.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
#define __@YY@__ 1
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
#ifdef __map__
|
||||
|
||||
/** Callbacks **/
|
||||
|
||||
/* Returns the callbacks associated with YY's keys. */
|
||||
o_callbacks_t o_@YY@_key_callbacks (o_@YY@_t *yy);
|
||||
|
||||
/* Returns the ``bogus'' marker associated with YY's keys. */
|
||||
const void *o_@YY@_not_a_key_marker (o_@YY@_t *yy);
|
||||
|
||||
/* Returns the callbacks associated with YY's values. */
|
||||
o_callbacks_t
|
||||
o_@YY@_value_callbacks (o_@YY@_t *yy);
|
||||
|
||||
/* Returns the ``bogus'' marker associated with YY's values. */
|
||||
const void *o_@YY@_not_a_value_marker (o_@YY@_t *yy);
|
||||
|
||||
#else /* !__map__ */
|
||||
|
||||
/** Callbacks **/
|
||||
|
||||
/* Returns the callbacks associated with YY's elements. */
|
||||
o_callbacks_t o_@YY@_element_callbacks (o_@YY@_t *yy);
|
||||
|
||||
/* Returns the ``bogus'' marker associated with YY's elements. */
|
||||
const void *o_@YY@_not_an_element_marker (o_@YY@_t *yy);
|
||||
|
||||
#endif /* __map__ */
|
||||
|
||||
#endif /* __@YY@_cbs_h_OBJECTS_INCLUDE */
|
||||
|
|
@ -97,24 +97,6 @@ GSCompatibility.m \
|
|||
GSLocale.m \
|
||||
Unicode.m \
|
||||
behavior.m \
|
||||
o_array.m \
|
||||
o_array_bas.m \
|
||||
o_array_cbs.m \
|
||||
o_cbs.m \
|
||||
o_cbs_char_p.m \
|
||||
o_cbs_id.m \
|
||||
o_cbs_int.m \
|
||||
o_cbs_int_p.m \
|
||||
o_cbs_void_p.m \
|
||||
o_hash.m \
|
||||
o_hash_bas.m \
|
||||
o_hash_cbs.m \
|
||||
o_list.m \
|
||||
o_list_bas.m \
|
||||
o_list_cbs.m \
|
||||
o_map.m \
|
||||
o_map_bas.m \
|
||||
o_map_cbs.m \
|
||||
preface.m \
|
||||
mframe.m
|
||||
|
||||
|
@ -139,10 +121,6 @@ numbers.c \
|
|||
o_vscanf.c
|
||||
|
||||
GNU_OTHER_SRCFILES = \
|
||||
o_x_bas.m.in \
|
||||
o_x_cbs.m.in \
|
||||
Foundation/o_x_bas.h.in \
|
||||
Foundation/o_x_cbs.h.in \
|
||||
md5.h \
|
||||
win32-entry.m \
|
||||
win32-def.top \
|
||||
|
@ -158,19 +136,6 @@ Unicode.h \
|
|||
UnixFileHandle.h \
|
||||
behavior.h \
|
||||
numbers.h \
|
||||
o_array.h \
|
||||
o_array_bas.h \
|
||||
o_array_cbs.h \
|
||||
o_cbs.h \
|
||||
o_hash.h \
|
||||
o_hash_bas.h \
|
||||
o_hash_cbs.h \
|
||||
o_list.h \
|
||||
o_list_bas.h \
|
||||
o_list_cbs.h \
|
||||
o_map.h \
|
||||
o_map_bas.h \
|
||||
o_map_cbs.h \
|
||||
objc-gnu2next.h \
|
||||
preface.h
|
||||
|
||||
|
@ -389,10 +354,6 @@ HEADERS_INSTALL = $(GNU_HEADERS) \
|
|||
GENERATED_HFILES = \
|
||||
dynamic-load.h \
|
||||
$(HEADER_DIR)/preface.h \
|
||||
$(HEADER_DIR)/o_array.h \
|
||||
$(HEADER_DIR)/o_hash.h \
|
||||
$(HEADER_DIR)/o_list.h \
|
||||
$(HEADER_DIR)/o_map.h \
|
||||
$(GNUSTEP_TARGET_DIR)/mframe.h \
|
||||
$(GNUSTEP_TARGET_DIR)/config.h \
|
||||
$(GNUSTEP_TARGET_DIR)/GSConfig.h
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <Foundation/NSByteOrder.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSDate.h>
|
||||
#include <Foundation/NSHashTable.h>
|
||||
#include <Foundation/NSHost.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
#include <Foundation/NSPortMessage.h>
|
||||
|
@ -1814,7 +1813,18 @@ static Class tcpPortClass;
|
|||
DO_UNLOCK(myLock);
|
||||
if (handle == nil)
|
||||
{
|
||||
NSLog(@"No handle for event on descriptor %d", desc);
|
||||
const char *t;
|
||||
|
||||
if (type == ET_RDESC) t = "rdesc";
|
||||
else if (type == ET_WDESC) t = "wdesc";
|
||||
else if (type == ET_EDESC) t = "edesc";
|
||||
else if (type == ET_RPORT) t = "rport";
|
||||
else t = "unknown";
|
||||
NSLog(@"No handle for event %s on descriptor %d", t, desc);
|
||||
[[runLoopClass currentRunLoop] removeEvent: extra
|
||||
type: type
|
||||
forMode: mode
|
||||
all: YES];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -103,7 +103,7 @@ after-uninstall::
|
|||
# Things to do after distcleaning
|
||||
after-distclean::
|
||||
rm -f mframe/mframe.h Foundation \
|
||||
NSNumber[0-9]*.m GSValue[0-9]*.m o_*_bas.m
|
||||
NSNumber[0-9]*.m GSValue[0-9]*.m
|
||||
rm -rf $(GNUSTEP_TARGET_DIR)/config.h
|
||||
rm -rf $(GNUSTEP_TARGET_DIR)/mframe.h
|
||||
rm -rf $(GNUSTEP_TARGET_DIR)/GSConfig.h
|
||||
|
@ -152,27 +152,6 @@ $(GNUSTEP_TARGET_DIR)/mframe.h: mframe/config.status
|
|||
-mv mframe/mframe.h $(GNUSTEP_TARGET_DIR)
|
||||
-touch $(GNUSTEP_TARGET_DIR)/mframe.h
|
||||
|
||||
$(HEADER_DIR)/o_%_bas.h: $(HEADER_DIR)/o_x_bas.h.in
|
||||
sed -e "s/@XX@/$*/g" $< > $@
|
||||
|
||||
$(HEADER_DIR)/o_%_cbs.h: $(HEADER_DIR)/o_x_cbs.h.in
|
||||
sed -e "s/@YY@/$*/g" $< > $@
|
||||
|
||||
o_%_bas.m: o_x_bas.m.in $(HEADER_DIR)/o_%.h
|
||||
sed -e "s/@XX@/$*/g" $< > $@
|
||||
|
||||
o_%_cbs.m: o_x_cbs.m.in $(HEADER_DIR)/o_%.h
|
||||
sed -e "s/@YY@/$*/g" $< > $@
|
||||
|
||||
$(GNUSTEP_OBJ_DIR)/o_array.o: o_array.m $(HEADER_DIR)/o_array.h
|
||||
$(HEADER_DIR)/o_array.h: $(HEADER_DIR)/o_array_bas.h $(HEADER_DIR)/o_array_cbs.h $(HEADER_DIR)/o_hash.h
|
||||
$(GNUSTEP_OBJ_DIR)/o_hash.o: o_hash.m $(HEADER_DIR)/o_hash.h
|
||||
$(HEADER_DIR)/o_hash.h: $(HEADER_DIR)/o_hash_bas.h $(HEADER_DIR)/o_hash_cbs.h
|
||||
$(GNUSTEP_OBJ_DIR)/o_list.o: o_list.m $(HEADER_DIR)/o_list.h
|
||||
$(HEADER_DIR)/o_list.h: $(HEADER_DIR)/o_list_bas.h $(HEADER_DIR)/o_list_cbs.h $(HEADER_DIR)/o_array.h $(HEADER_DIR)/o_hash.h
|
||||
$(GNUSTEP_OBJ_DIR)/o_map.o: o_map.m $(HEADER_DIR)/o_map.h
|
||||
$(HEADER_DIR)/o_map.h: $(HEADER_DIR)/o_map_bas.h $(HEADER_DIR)/o_map_cbs.h $(HEADER_DIR)/o_hash.h
|
||||
|
||||
#
|
||||
# Files that include mframe.h will need a rebuild if it is changed.
|
||||
#
|
||||
|
|
|
@ -37,11 +37,11 @@
|
|||
|
||||
/** For `int's **/
|
||||
|
||||
unsigned int _NS_int_hash(void *table, int i);
|
||||
BOOL _NS_int_is_equal(void *table, int i, int j);
|
||||
void _NS_int_retain(void *table, int i);
|
||||
void _NS_int_release(void *table, int i);
|
||||
NSString *_NS_int_describe(void *table, int i);
|
||||
unsigned int _NS_int_hash(void *table, void* i);
|
||||
BOOL _NS_int_is_equal(void *table, void* i, void* j);
|
||||
void _NS_int_retain(void *table, void* i);
|
||||
void _NS_int_release(void *table, void* i);
|
||||
NSString *_NS_int_describe(void *table, void* i);
|
||||
|
||||
/** For owned `void *' **/
|
||||
|
||||
|
|
|
@ -41,31 +41,31 @@
|
|||
/** For `int's **/
|
||||
|
||||
unsigned int
|
||||
_NS_int_hash(void *table, int i)
|
||||
_NS_int_hash(void *table, void* i)
|
||||
{
|
||||
return (unsigned int) i;
|
||||
}
|
||||
|
||||
BOOL
|
||||
_NS_int_is_equal(void *table, int i, int j)
|
||||
_NS_int_is_equal(void *table, void* i, void* j)
|
||||
{
|
||||
return (i == j) ? YES : NO;
|
||||
}
|
||||
|
||||
void
|
||||
_NS_int_retain(void *table, int i)
|
||||
_NS_int_retain(void *table, void* i)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
_NS_int_release(void *table, int i)
|
||||
_NS_int_release(void *table, void* i)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
_NS_int_describe(void *table, int i)
|
||||
_NS_int_describe(void *table, void* i)
|
||||
{
|
||||
return [NSString stringWithFormat: @"%d", i];
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/** NSHashTable implementation for GNUStep.
|
||||
* Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1994, 1995, 1996, 1997, 2002 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
|
||||
* Rewrite by: Richard Frith-Macdonald <rfm@gnu.org>
|
||||
*
|
||||
* This file is part of the GNUstep Base Library.
|
||||
*
|
||||
|
@ -21,9 +22,9 @@
|
|||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
<title>NSHashTable class reference</title>
|
||||
$Date$ $Revision$
|
||||
*
|
||||
* <title>NSHashTable class reference</title>
|
||||
* $Date$ $Revision$
|
||||
*/
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
@ -34,335 +35,350 @@
|
|||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSHashTable.h>
|
||||
#include <base/o_hash.h>
|
||||
#include "NSCallBacks.h"
|
||||
|
||||
/** Macros... **/
|
||||
|
||||
#define NSHT_CALLBACKS(T) \
|
||||
(*((NSHashTableCallBacks *)(o_hash_extra((o_hash_t *)(T)))))
|
||||
#define GSI_NEW 1
|
||||
/*
|
||||
* The 'Fastmap' stuff provides an inline implementation of a hash
|
||||
* table - for maximum performance.
|
||||
*/
|
||||
#define GSI_MAP_HAS_VALUE 0
|
||||
#define GSI_MAP_EXTRA NSHashTableCallBacks
|
||||
#define GSI_MAP_KTYPES GSUNION_PTR
|
||||
#define GSI_MAP_HASH(M, X)\
|
||||
(M->extra.hash)((NSHashTable*)M, X.ptr)
|
||||
#define GSI_MAP_EQUAL(M, X, Y)\
|
||||
(M->extra.isEqual)((NSHashTable*)M, X.ptr, Y.ptr)
|
||||
#define GSI_MAP_RELEASE_KEY(M, X)\
|
||||
(M->extra.release)((NSHashTable*)M, X.ptr)
|
||||
#define GSI_MAP_RETAIN_KEY(M, X)\
|
||||
(M->extra.retain)((NSHashTable*)M, X.ptr)
|
||||
#define GSI_MAP_ENUMERATOR NSHashEnumerator
|
||||
|
||||
#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);
|
||||
}
|
||||
#include <base/GSIMap.h>
|
||||
|
||||
/**
|
||||
* Returns an array of all the objects in the table.
|
||||
* NB. The table <em>must</em> contain objects, not pointers or integers.
|
||||
*/
|
||||
NSArray *
|
||||
NSAllHashTableObjects (NSHashTable *table)
|
||||
NSAllHashTableObjects(NSHashTable *table)
|
||||
{
|
||||
NSMutableArray *array;
|
||||
NSHashEnumerator enumerator;
|
||||
id element;
|
||||
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)];
|
||||
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;
|
||||
{
|
||||
[array addObject: element];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Enumerating **/
|
||||
/**
|
||||
* Compares the two hash tables for equality.
|
||||
* If the tables are different sizes, returns NO.
|
||||
* Otherwise, compares the values in the two tables
|
||||
* and returns NO if they differ.<br />
|
||||
* The GNUstep implementation enumerates the values in table1
|
||||
* and uses the hash and isEqual functions of table2 for comparison.
|
||||
*/
|
||||
BOOL
|
||||
NSCompareHashTables(NSHashTable *table1, NSHashTable *table2)
|
||||
{
|
||||
GSIMapTable t1 = (GSIMapTable)table1;
|
||||
GSIMapTable t2 = (GSIMapTable)table2;
|
||||
|
||||
if (t1->nodeCount != t2->nodeCount)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
GSIMapNode n = t1->firstNode;
|
||||
|
||||
while (n != 0)
|
||||
{
|
||||
if (GSIMapNodeForKey(t2, n->key) == 0)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
n = n->nextInMap;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the supplied map table creating the new table in the specified zone.
|
||||
*/
|
||||
NSHashTable *
|
||||
NSCopyHashTableWithZone(NSHashTable *table, NSZone *zone)
|
||||
{
|
||||
GSIMapTable t;
|
||||
GSIMapNode n;
|
||||
|
||||
t = (GSIMapTable)NSZoneMalloc(zone, sizeof(GSIMapTable_t));
|
||||
GSIMapInitWithZoneAndCapacity(t, zone, ((GSIMapTable)table)->nodeCount);
|
||||
t->extra = ((GSIMapTable)table)->extra;
|
||||
n = ((GSIMapTable)table)->firstNode;
|
||||
while (n != 0)
|
||||
{
|
||||
GSIMapAddKey(t, n->key);
|
||||
n = n->nextInMap;
|
||||
}
|
||||
|
||||
return (NSHashTable*)t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of objects in the table.
|
||||
*/
|
||||
unsigned int
|
||||
NSCountHashTable(NSHashTable *table)
|
||||
{
|
||||
return ((GSIMapTable)table)->nodeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new hash table by calling NSCreateHashTableWithZone() using
|
||||
* NSDefaultMallocZone().
|
||||
*/
|
||||
NSHashTable *
|
||||
NSCreateHashTable(
|
||||
NSHashTableCallBacks callBacks,
|
||||
unsigned int capacity)
|
||||
{
|
||||
return NSCreateHashTableWithZone(callBacks, capacity, NSDefaultMallocZone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new hash table using the supplied callbacks structure.
|
||||
* If any functions in the callback structure is null the default
|
||||
* values are used ... as for non-owned pointers.
|
||||
* The table will be created with the specified capacity ... ie ready
|
||||
* to hold at lest that many items.
|
||||
*/
|
||||
NSHashTable *
|
||||
NSCreateHashTableWithZone(
|
||||
NSHashTableCallBacks callBacks,
|
||||
unsigned int capacity,
|
||||
NSZone *zone)
|
||||
{
|
||||
GSIMapTable table;
|
||||
|
||||
table = (GSIMapTable)NSZoneMalloc(zone, sizeof(GSIMapTable_t));
|
||||
GSIMapInitWithZoneAndCapacity(table, zone, capacity);
|
||||
table->extra = callBacks;
|
||||
|
||||
if (table->extra.hash == 0)
|
||||
table->extra.hash = NSNonOwnedPointerHashCallBacks.hash;
|
||||
if (table->extra.isEqual == 0)
|
||||
table->extra.isEqual = NSNonOwnedPointerHashCallBacks.isEqual;
|
||||
if (table->extra.retain == 0)
|
||||
table->extra.retain = NSNonOwnedPointerHashCallBacks.retain;
|
||||
if (table->extra.release == 0)
|
||||
table->extra.release = NSNonOwnedPointerHashCallBacks.release;
|
||||
if (table->extra.describe == 0)
|
||||
table->extra.describe = NSNonOwnedPointerHashCallBacks.describe;
|
||||
|
||||
return (NSHashTable*)table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to be called when finished with the enumerator.
|
||||
* Not required in GNUstep ... just provided for MacOS-X compatibility.
|
||||
*/
|
||||
void
|
||||
NSEndHashTableEnumeration(NSHashEnumerator *enumerator)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an enumerator for stepping through a map table using the
|
||||
* NSNextHashEnumeratorPair() function.
|
||||
*/
|
||||
NSHashEnumerator
|
||||
NSEnumerateHashTable(NSHashTable *table)
|
||||
{
|
||||
return o_hash_enumerator_for_hash(table);
|
||||
return GSIMapEnumeratorForMap((GSIMapTable)table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the hash table and relase its contents.
|
||||
*/
|
||||
void
|
||||
NSFreeHashTable(NSHashTable *table)
|
||||
{
|
||||
NSZone *z = ((GSIMapTable)table)->zone;
|
||||
|
||||
GSIMapEmptyMap((GSIMapTable)table);
|
||||
NSZoneFree(z, table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value for the specified element, or a nul pointer if the
|
||||
* element is not found in the table.
|
||||
*/
|
||||
void *
|
||||
NSNextHashEnumeratorItem(NSHashEnumerator *enumerator)
|
||||
NSHashGet(NSHashTable *table, const void *element)
|
||||
{
|
||||
const void *element;
|
||||
GSIMapNode n = GSIMapNodeForKey((GSIMapTable)table, (GSIMapKey)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: %@",
|
||||
NSHT_DESCRIBE(table, element)];
|
||||
}
|
||||
if (n == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
o_hash_add_element_known_absent(table, element);
|
||||
}
|
||||
|
||||
/* OpenStep doesn't care for any return value, so... */
|
||||
return;
|
||||
{
|
||||
return n->key.ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the element to table.<br />
|
||||
* If an equal element is already in table, replaces it with the new one.<br />
|
||||
* If element is nul raises an NSInvalidArgumentException.
|
||||
*/
|
||||
void
|
||||
NSHashInsert(NSHashTable *table, const void *element)
|
||||
{
|
||||
GSIMapTable t = (GSIMapTable)table;
|
||||
|
||||
if (element == 0)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Attempt to place nul in hash table"];
|
||||
}
|
||||
GSIMapAddKey(t, (GSIMapKey)element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the element to table and returns nul.<br />
|
||||
* If an equal element is already in table, returns the old element
|
||||
* instead of adding the new one.<br />
|
||||
* If element is nul, raises an NSInvalidArgumentException.
|
||||
*/
|
||||
void *
|
||||
NSHashInsertIfAbsent(NSHashTable *table, const void *element)
|
||||
{
|
||||
const void *old_element;
|
||||
GSIMapTable t = (GSIMapTable)table;
|
||||
GSIMapNode n;
|
||||
|
||||
/* 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;
|
||||
if (element == 0)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Attempt to place nul in hash table"];
|
||||
}
|
||||
n = GSIMapNodeForKey(t, (GSIMapKey)element);
|
||||
if (n == 0)
|
||||
{
|
||||
GSIMapAddKey(t, (GSIMapKey)element);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return n->key.ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/** Removing **/
|
||||
/**
|
||||
* Adds the element to table and returns nul.<br />
|
||||
* If an equal element is already present, raises NSInvalidArgumentException.
|
||||
* <br />If element is nul raises an NSInvalidArgumentException.
|
||||
*/
|
||||
void
|
||||
NSHashInsertKnownAbsent(NSHashTable *table, const void *element)
|
||||
{
|
||||
GSIMapTable t = (GSIMapTable)table;
|
||||
GSIMapNode n;
|
||||
|
||||
if (element == 0)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Attempt to place nul in hash table"];
|
||||
}
|
||||
n = GSIMapNodeForKey(t, (GSIMapKey)element);
|
||||
if (n == 0)
|
||||
{
|
||||
GSIMapAddKey(t, (GSIMapKey)element);
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"NSHashInsertKnownAbsent ... element not absent"];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified element from the table.
|
||||
*/
|
||||
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;
|
||||
GSIMapRemoveKey((GSIMapTable)table, (GSIMapKey)element);
|
||||
}
|
||||
|
||||
/** Describing **/
|
||||
/**
|
||||
* Step through the hash table ... return the next item or
|
||||
* return nulif we hit the of the table.
|
||||
*/
|
||||
void *
|
||||
NSNextHashEnumeratorItem(NSHashEnumerator *enumerator)
|
||||
{
|
||||
GSIMapNode n = GSIMapEnumeratorNextNode((GSIMapEnumerator)enumerator);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return n->key.ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the hash table, but preserve its capacity.
|
||||
*/
|
||||
void
|
||||
NSResetHashTable(NSHashTable *table)
|
||||
{
|
||||
GSIMapCleanMap((GSIMapTable)table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string describing the table contents.<br />
|
||||
* For each item, a string of the form "value;\n"
|
||||
* is appended. The appropriate describe function is used to generate
|
||||
* the strings for each item.
|
||||
*/
|
||||
NSString *
|
||||
NSStringFromHashTable(NSHashTable *table)
|
||||
{
|
||||
NSMutableString *string;
|
||||
NSHashEnumerator enumerator;
|
||||
const void *pointer;
|
||||
GSIMapTable t = (GSIMapTable)table;
|
||||
NSMutableString *string;
|
||||
NSHashEnumerator enumerator;
|
||||
const void *element;
|
||||
|
||||
/* This will be our string. */
|
||||
string = [NSMutableString stringWithCapacity:0];
|
||||
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:@"%@;\n", NSHT_DESCRIBE(table, pointer)];
|
||||
|
||||
/* STRING is already autoreleased. */
|
||||
return (NSString *) string;
|
||||
while ((element = NSNextHashEnumeratorItem(&enumerator)) != 0)
|
||||
{
|
||||
[string appendFormat: @"%@;\n", (t->extra.describe)(table, element)];
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/** NSMapTable implementation for GNUStep.
|
||||
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1994, 1995, 1996, 2002 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>
|
||||
*
|
||||
* This file is part of the GNUstep Base Library.
|
||||
*
|
||||
|
@ -21,9 +22,9 @@
|
|||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
<title>NSMapTable class reference</title>
|
||||
$Date$ $Revision$
|
||||
*
|
||||
* <title>NSMapTable class reference</title>
|
||||
* $Date$ $Revision$
|
||||
*/
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
@ -35,423 +36,450 @@
|
|||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSZone.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
#include <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);
|
||||
}
|
||||
typedef struct {
|
||||
NSMapTableKeyCallBacks k;
|
||||
NSMapTableValueCallBacks v;
|
||||
} extraData;
|
||||
|
||||
int
|
||||
_NSMT_key_compare (const void *element1, const void *element2,
|
||||
const void *table)
|
||||
{
|
||||
return !(NSMT_KEY_CALLBACKS(table).isEqual((NSMapTable *)table,
|
||||
element1,
|
||||
element2));
|
||||
}
|
||||
#define GSI_NEW 1
|
||||
|
||||
int
|
||||
_NSMT_key_is_equal (const void *element1, const void *element2,
|
||||
const void *table)
|
||||
{
|
||||
return NSMT_KEY_CALLBACKS(table).isEqual((NSMapTable *) table,
|
||||
element1,
|
||||
element2);
|
||||
}
|
||||
/*
|
||||
* 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
|
||||
|
||||
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
|
||||
};
|
||||
#include <base/GSIMap.h>
|
||||
|
||||
/**** 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
NSMutableArray *keyArray;
|
||||
NSMapEnumerator enumerator;
|
||||
id key = nil;
|
||||
|
||||
/* Create our mutable key array. */
|
||||
keyArray = [NSMutableArray arrayWithCapacity:NSCountMapTable(table)];
|
||||
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];
|
||||
|
||||
{
|
||||
[keyArray addObject: key];
|
||||
}
|
||||
return keyArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
NSMapEnumerator enumerator;
|
||||
NSMutableArray *valueArray;
|
||||
id value = nil;
|
||||
NSMapEnumerator enumerator;
|
||||
NSMutableArray *valueArray;
|
||||
id value = nil;
|
||||
|
||||
/* Create our mutable value array. */
|
||||
valueArray = [NSMutableArray arrayWithCapacity:NSCountMapTable(table)];
|
||||
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];
|
||||
|
||||
{
|
||||
[valueArray addObject: value];
|
||||
}
|
||||
return valueArray;
|
||||
}
|
||||
|
||||
/** Adding items to an NSMapTable... **/
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
GSIMapTable t1 = (GSIMapTable)table1;
|
||||
GSIMapTable t2 = (GSIMapTable)table2;
|
||||
|
||||
if (t1->nodeCount != t2->nodeCount)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
GSIMapNode n = t1->firstNode;
|
||||
|
||||
while (n != 0)
|
||||
{
|
||||
if (GSIMapNodeForKey(t2, n->key) == 0)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
n = n->nextInMap;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the supplied map table creating the new table in the specified zone.
|
||||
*/
|
||||
NSMapTable *
|
||||
NSCopyMapTableWithZone(NSMapTable *table, NSZone *zone)
|
||||
{
|
||||
GSIMapTable t;
|
||||
GSIMapNode n;
|
||||
|
||||
t = (GSIMapTable)NSZoneMalloc(zone, sizeof(GSIMapTable_t));
|
||||
GSIMapInitWithZoneAndCapacity(t, zone, ((GSIMapTable)table)->nodeCount);
|
||||
t->extra.k = ((GSIMapTable)table)->extra.k;
|
||||
t->extra.v = ((GSIMapTable)table)->extra.v;
|
||||
n = ((GSIMapTable)table)->firstNode;
|
||||
while (n != 0)
|
||||
{
|
||||
GSIMapAddPair(t, n->key, n->value);
|
||||
n = n->nextInMap;
|
||||
}
|
||||
|
||||
return (NSMapTable*)t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of keys in the table.
|
||||
*/
|
||||
unsigned int
|
||||
NSCountMapTable(NSMapTable *table)
|
||||
{
|
||||
return ((GSIMapTable)table)->nodeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new map table by calling NSCreateMapTableWithZone() using
|
||||
* NSDefaultMallocZone().
|
||||
*/
|
||||
NSMapTable *
|
||||
NSCreateMapTable(
|
||||
NSMapTableKeyCallBacks keyCallBacks,
|
||||
NSMapTableValueCallBacks valueCallBacks,
|
||||
unsigned int capacity)
|
||||
{
|
||||
return NSCreateMapTableWithZone(keyCallBacks, valueCallBacks,
|
||||
capacity, NSDefaultMallocZone());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* The table will be created with the specified capacity ... ie ready
|
||||
* to hold at lest that many items.
|
||||
*/
|
||||
NSMapTable *
|
||||
NSCreateMapTableWithZone(
|
||||
NSMapTableKeyCallBacks keyCallBacks,
|
||||
NSMapTableValueCallBacks valueCallBacks,
|
||||
unsigned capacity,
|
||||
NSZone *zone)
|
||||
{
|
||||
GSIMapTable table;
|
||||
|
||||
table = (GSIMapTable)NSZoneMalloc(zone, sizeof(GSIMapTable_t));
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to be called when finished with the enumerator.
|
||||
* Not required in GNUstep ... just provided for MacOS-X compatibility.
|
||||
*/
|
||||
void
|
||||
NSEndMapTableEnumeration(NSMapEnumerator *enumerator)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an enumerator for stepping through a map table using the
|
||||
* NSNextMapEnumeratorPair() function.
|
||||
*/
|
||||
NSMapEnumerator
|
||||
NSEnumerateMapTable(NSMapTable *table)
|
||||
{
|
||||
return GSIMapEnumeratorForMap((GSIMapTable)table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the map table and relase its contents.
|
||||
*/
|
||||
void
|
||||
NSFreeMapTable(NSMapTable *table)
|
||||
{
|
||||
NSZone *z = ((GSIMapTable)table)->zone;
|
||||
|
||||
GSIMapEmptyMap((GSIMapTable)table);
|
||||
NSZoneFree(z, table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value for the specified key, or a nul pointer if the
|
||||
* key is not found in the table.
|
||||
*/
|
||||
void *
|
||||
NSMapGet(NSMapTable *table, const void *key)
|
||||
{
|
||||
GSIMapNode n = GSIMapNodeForKey((GSIMapTable)table, (GSIMapKey)key);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return n->value.ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 itsself.<br />
|
||||
* If key is equal to the notAKeyMarker field of the tables
|
||||
* NSMapTableKeyCallBacks, raises an NSInvalidArgumentException.
|
||||
*/
|
||||
void
|
||||
NSMapInsert(NSMapTable *table, const void *key, const void *value)
|
||||
{
|
||||
/* Put KEY -> VALUE into TABLE. */
|
||||
o_map_at_key_put_value(table, key, value);
|
||||
GSIMapTable t = (GSIMapTable)table;
|
||||
|
||||
return;
|
||||
if (key == t->extra.k.notAKeyMarker)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Attempt to place notAKeyMarker in map table"];
|
||||
}
|
||||
GSIMapAddPair(t, (GSIMapKey)key, (GSIMapVal)value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 tables
|
||||
* NSMapTableKeyCallBacks, raises an NSInvalidArgumentException.
|
||||
*/
|
||||
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);
|
||||
GSIMapTable t = (GSIMapTable)table;
|
||||
GSIMapNode n;
|
||||
|
||||
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
|
||||
{
|
||||
/* Put KEY -> VALUE into TABLE. */
|
||||
o_map_at_key_put_value_known_absent (table, key, value);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
return n->key.ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 tables
|
||||
* NSMapTableKeyCallBacks, raises an NSInvalidArgumentException.
|
||||
*/
|
||||
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: %@ -> %@",
|
||||
NSMT_DESCRIBE_KEY(table, key),
|
||||
NSMT_DESCRIBE_VALUE(table, value)];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Well, we know it's not there, so... */
|
||||
o_map_at_key_put_value_known_absent (table, key, value);
|
||||
}
|
||||
GSIMapTable t = (GSIMapTable)table;
|
||||
GSIMapNode n;
|
||||
|
||||
/* Yah-hoo! */
|
||||
return;
|
||||
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"];
|
||||
}
|
||||
}
|
||||
|
||||
/** Removing items from an NSMapTable **/
|
||||
/**
|
||||
* 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 nul pointers, and only updates them if non-null.
|
||||
*/
|
||||
BOOL
|
||||
NSMapMember(NSMapTable *table, const void *key,
|
||||
void **originalKey, void **value)
|
||||
{
|
||||
GSIMapNode 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified key from the table.
|
||||
*/
|
||||
void
|
||||
NSMapRemove(NSMapTable *table, const void *key)
|
||||
{
|
||||
o_map_remove_key (table, key);
|
||||
return;
|
||||
GSIMapRemoveKey((GSIMapTable)table, (GSIMapKey)key);
|
||||
}
|
||||
|
||||
/** Getting an NSString representation of an NSMapTable **/
|
||||
/**
|
||||
* 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 GNUstep implementation permits either key or value to be a
|
||||
* nul pointer, and refrains from attempting to return the appropriate
|
||||
* result in that case.
|
||||
*/
|
||||
BOOL
|
||||
NSNextMapEnumeratorPair(NSMapEnumerator *enumerator,
|
||||
void **key, void **value)
|
||||
{
|
||||
GSIMapNode n = GSIMapEnumeratorNextNode((GSIMapEnumerator)enumerator);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (key != 0)
|
||||
{
|
||||
*key = n->key.ptr;
|
||||
}
|
||||
if (value != 0)
|
||||
{
|
||||
*value = n->value.ptr;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the map table, but preserve its capacity.
|
||||
*/
|
||||
void
|
||||
NSResetMapTable(NSMapTable *table)
|
||||
{
|
||||
GSIMapCleanMap((GSIMapTable)table);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
NSMutableString *string;
|
||||
NSMapEnumerator enumerator;
|
||||
NSMapTableKeyCallBacks keyCallBacks;
|
||||
NSMapTableValueCallBacks valueCallBacks;
|
||||
void *key, *value;
|
||||
GSIMapTable t = (GSIMapTable)table;
|
||||
NSMutableString *string;
|
||||
NSMapEnumerator enumerator;
|
||||
void *key;
|
||||
void *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. */
|
||||
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))
|
||||
[string appendFormat:@"%@ = %@;",
|
||||
(keyCallBacks.describe)(table, key),
|
||||
(valueCallBacks.describe)(table, value)];
|
||||
|
||||
/* Note that this string'll need to be `retain'ed. */
|
||||
/*
|
||||
* 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)];
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <Foundation/NSInvocation.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <base/o_map.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSPortCoder.h>
|
||||
|
@ -45,6 +44,9 @@
|
|||
#include <Foundation/NSObjCRuntime.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define REFCNT_LOCAL 0
|
||||
|
||||
|
||||
#ifndef NeXT_RUNTIME
|
||||
extern BOOL __objc_responds_to(id, SEL);
|
||||
#endif
|
||||
|
@ -223,69 +225,86 @@ NSDecrementExtraRefCountWasZero(id anObject)
|
|||
|
||||
#else
|
||||
|
||||
#define GSI_NEW
|
||||
#define GSI_MAP_EQUAL(M, X, Y) (X.obj == Y.obj)
|
||||
#define GSI_MAP_HASH(M, X) (X.ptr >> 2)
|
||||
#define GSI_MAP_RETAIN_KEY(M, X)
|
||||
#define GSI_MAP_RELEASE_KEY(M, X)
|
||||
#define GSI_MAP_RETAIN_VAL(M, X)
|
||||
#define GSI_MAP_RELEASE_VAL(M, X)
|
||||
#define GSI_MAP_KTYPES GSUNION_OBJ
|
||||
#define GSI_MAP_VTYPES GSUNION_INT
|
||||
|
||||
#include <base/GSIMap.h>
|
||||
|
||||
/* The maptable of retain counts on objects */
|
||||
static o_map_t *retain_counts = NULL;
|
||||
static GSIMapTable_t retain_counts;
|
||||
|
||||
void
|
||||
NSIncrementExtraRefCount (id anObject)
|
||||
{
|
||||
o_map_node_t *node;
|
||||
extern o_map_node_t *o_map_node_for_key(o_map_t *m, const void *k);
|
||||
GSIMapNode node;
|
||||
|
||||
if (retain_counts_gate != 0)
|
||||
{
|
||||
objc_mutex_lock(retain_counts_gate);
|
||||
node = o_map_node_for_key (retain_counts, anObject);
|
||||
if (node)
|
||||
((int)(node->value))++;
|
||||
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
|
||||
if (node != 0)
|
||||
{
|
||||
(node->value.uint)++;
|
||||
}
|
||||
else
|
||||
o_map_at_key_put_value_known_absent (retain_counts, anObject, (void*)1);
|
||||
{
|
||||
GSIMapAddPair(&retain_count, (GSIMapKey)anObject, (GSIMapKey)1);
|
||||
}
|
||||
objc_mutex_unlock(retain_counts_gate);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = o_map_node_for_key (retain_counts, anObject);
|
||||
if (node)
|
||||
((int)(node->value))++;
|
||||
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
|
||||
if (node != 0)
|
||||
{
|
||||
(node->value.uint)++;
|
||||
}
|
||||
else
|
||||
o_map_at_key_put_value_known_absent (retain_counts, anObject, (void*)1);
|
||||
{
|
||||
GSIMapAddPair(&retain_count, (GSIMapKey)anObject, (GSIMapKey)1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
NSDecrementExtraRefCountWasZero (id anObject)
|
||||
{
|
||||
o_map_node_t *node;
|
||||
extern o_map_node_t *o_map_node_for_key (o_map_t *m, const void *k);
|
||||
extern void o_map_remove_node (o_map_node_t *node);
|
||||
GSIMapNode node;
|
||||
|
||||
if (retain_counts_gate != 0)
|
||||
{
|
||||
objc_mutex_lock(retain_counts_gate);
|
||||
node = o_map_node_for_key (retain_counts, anObject);
|
||||
if (!node)
|
||||
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
|
||||
if (node == 0)
|
||||
{
|
||||
objc_mutex_unlock(retain_counts_gate);
|
||||
return YES;
|
||||
}
|
||||
NSCAssert((int)(node->value) > 0, NSInternalInconsistencyException);
|
||||
if (!--((int)(node->value)))
|
||||
NSCAssert(node->value.uint > 0, NSInternalInconsistencyException);
|
||||
if (--(node->value.uint) == 0)
|
||||
{
|
||||
o_map_remove_node (node);
|
||||
GSIMapRemoveKey((GSIMapTable)&retain_counts, (GSIMapKey)anObject);
|
||||
}
|
||||
objc_mutex_unlock(retain_counts_gate);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = o_map_node_for_key (retain_counts, anObject);
|
||||
if (!node)
|
||||
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
|
||||
if (node == 0)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
NSCAssert((int)(node->value) > 0, NSInternalInconsistencyException);
|
||||
if (!--((int)(node->value)))
|
||||
NSCAssert(node->value.uint > 0, NSInternalInconsistencyException);
|
||||
if (--(node->value.uint) == 0)
|
||||
{
|
||||
o_map_remove_node (node);
|
||||
GSIMapRemoveKey((GSIMapTable)&retain_counts, (GSIMapKey)anObject);
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
|
@ -294,27 +313,34 @@ NSDecrementExtraRefCountWasZero (id anObject)
|
|||
unsigned
|
||||
NSExtraRefCount (id anObject)
|
||||
{
|
||||
unsigned ret;
|
||||
GSIMapNode node;
|
||||
unsigned ret;
|
||||
|
||||
if (retain_counts_gate != 0)
|
||||
{
|
||||
objc_mutex_lock(retain_counts_gate);
|
||||
ret = (unsigned) o_map_value_at_key(retain_counts, anObject);
|
||||
if (ret == (unsigned)o_map_not_a_key_marker(retain_counts)
|
||||
|| ret == (unsigned)o_map_not_a_value_marker(retain_counts))
|
||||
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
|
||||
if (node == 0)
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = node->value.uint;
|
||||
}
|
||||
objc_mutex_unlock(retain_counts_gate);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = (unsigned) o_map_value_at_key(retain_counts, anObject);
|
||||
if (ret == (unsigned)o_map_not_a_key_marker(retain_counts)
|
||||
|| ret == (unsigned)o_map_not_a_value_marker(retain_counts))
|
||||
node = GSIMapNodeForKey(&retain_counts, (GSIMapKey)anObject);
|
||||
if (node == 0)
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = node->value.uint;
|
||||
}
|
||||
}
|
||||
return ret; /* ExtraRefCount + 1 */
|
||||
}
|
||||
|
@ -610,8 +636,7 @@ static BOOL double_release_check_enabled = NO;
|
|||
fastMallocClass = [_FastMallocBuffer class];
|
||||
#if GS_WITH_GC == 0
|
||||
#if !defined(REFCNT_LOCAL)
|
||||
retain_counts = o_map_with_callbacks (o_callbacks_for_non_owned_void_p,
|
||||
o_callbacks_for_int);
|
||||
GSIMapInitWithZoneAndCapacity(&retain-count, NSDefaultMallocZone(), 1024);
|
||||
#endif
|
||||
fastMallocOffset = fastMallocClass->instance_size % ALIGN;
|
||||
#else
|
||||
|
|
|
@ -753,45 +753,44 @@ static IMP wRelImp;
|
|||
static IMP wRetImp;
|
||||
|
||||
static void
|
||||
wRelease(void* t, id w)
|
||||
wRelease(NSMapTable* t, const void* w)
|
||||
{
|
||||
(*wRelImp)(w, wRelSel);
|
||||
(*wRelImp)((id)w, wRelSel);
|
||||
}
|
||||
|
||||
static id
|
||||
wRetain(void* t, id w)
|
||||
static void
|
||||
wRetain(NSMapTable* t, const void* w)
|
||||
{
|
||||
return (*wRetImp)(w, wRetSel);
|
||||
(*wRetImp)((id)w, wRetSel);
|
||||
}
|
||||
|
||||
const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
||||
{
|
||||
(NSMT_retain_func_t) wRetain,
|
||||
(NSMT_release_func_t) wRelease,
|
||||
(NSMT_describe_func_t) 0
|
||||
wRetain,
|
||||
wRelease,
|
||||
0
|
||||
};
|
||||
#else
|
||||
#define WatcherMapValueCallBacks NSOwnedPointerMapValueCallBacks
|
||||
#endif
|
||||
|
||||
static void*
|
||||
aRetain(void* t, GSIArray a)
|
||||
static void
|
||||
aRetain(NSMapTable* t, const void* a)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
static void
|
||||
aRelease(void* t, GSIArray a)
|
||||
aRelease(NSMapTable* t, const void* a)
|
||||
{
|
||||
GSIArrayEmpty(a);
|
||||
NSZoneFree(a->zone, (void*)a);
|
||||
GSIArrayEmpty((GSIArray)a);
|
||||
NSZoneFree(((GSIArray)a)->zone, (void*)a);
|
||||
}
|
||||
|
||||
const NSMapTableValueCallBacks ArrayMapValueCallBacks =
|
||||
{
|
||||
(NSMT_retain_func_t) aRetain,
|
||||
(NSMT_release_func_t) aRelease,
|
||||
(NSMT_describe_func_t) 0
|
||||
aRetain,
|
||||
aRelease,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
|
@ -1137,7 +1136,7 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
|
|||
printf ("\tNSRunLoop limit date past, returning\n");
|
||||
_current_mode = saved_mode;
|
||||
RELEASE(arp);
|
||||
return;
|
||||
NS_VOIDRETURN;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1317,7 +1316,7 @@ const NSMapTableValueCallBacks ArrayMapValueCallBacks =
|
|||
[self _checkPerformers];
|
||||
_current_mode = saved_mode;
|
||||
RELEASE(arp);
|
||||
return;
|
||||
NS_VOIDRETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
131
Source/externs.m
131
Source/externs.m
|
@ -532,8 +532,15 @@ GSBuildStrings()
|
|||
|
||||
|
||||
|
||||
/* Standard MapTable callbacks */
|
||||
/* 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 *, const void *);
|
||||
typedef NSString *(*NSMT_describe_func_t)(NSMapTable *, const void *);
|
||||
|
||||
|
||||
/* Standard MapTable callbacks */
|
||||
const NSMapTableKeyCallBacks NSIntMapKeyCallBacks =
|
||||
{
|
||||
(NSMT_hash_func_t) _NS_int_hash,
|
||||
|
@ -541,7 +548,7 @@ const NSMapTableKeyCallBacks NSIntMapKeyCallBacks =
|
|||
(NSMT_retain_func_t) _NS_int_retain,
|
||||
(NSMT_release_func_t) _NS_int_release,
|
||||
(NSMT_describe_func_t) _NS_int_describe,
|
||||
0
|
||||
NSNotAnIntMapKey
|
||||
};
|
||||
|
||||
const NSMapTableKeyCallBacks NSNonOwnedPointerMapKeyCallBacks =
|
||||
|
@ -551,7 +558,7 @@ const NSMapTableKeyCallBacks NSNonOwnedPointerMapKeyCallBacks =
|
|||
(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,
|
||||
0
|
||||
NSNotAPointerMapKey
|
||||
};
|
||||
|
||||
const NSMapTableKeyCallBacks NSNonOwnedPointerOrNullMapKeyCallBacks =
|
||||
|
@ -561,10 +568,7 @@ const NSMapTableKeyCallBacks NSNonOwnedPointerOrNullMapKeyCallBacks =
|
|||
(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,
|
||||
/* FIXME: Oh my. Is this really ok? I did it in a moment of
|
||||
* weakness. A fit of madness, I say! And if this is wrong, what
|
||||
* *should* it be?!? */
|
||||
(const void *)-1
|
||||
NSNotAPointerMapKey
|
||||
};
|
||||
|
||||
const NSMapTableKeyCallBacks NSNonRetainedObjectMapKeyCallBacks =
|
||||
|
@ -574,7 +578,7 @@ const NSMapTableKeyCallBacks NSNonRetainedObjectMapKeyCallBacks =
|
|||
(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,
|
||||
0
|
||||
NSNotAPointerMapKey
|
||||
};
|
||||
|
||||
const NSMapTableKeyCallBacks NSObjectMapKeyCallBacks =
|
||||
|
@ -584,7 +588,7 @@ const NSMapTableKeyCallBacks NSObjectMapKeyCallBacks =
|
|||
(NSMT_retain_func_t) _NS_id_retain,
|
||||
(NSMT_release_func_t) _NS_id_release,
|
||||
(NSMT_describe_func_t) _NS_id_describe,
|
||||
0
|
||||
NSNotAPointerMapKey
|
||||
};
|
||||
|
||||
const NSMapTableKeyCallBacks NSOwnedPointerMapKeyCallBacks =
|
||||
|
@ -594,7 +598,7 @@ const NSMapTableKeyCallBacks NSOwnedPointerMapKeyCallBacks =
|
|||
(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,
|
||||
0
|
||||
NSNotAPointerMapKey
|
||||
};
|
||||
|
||||
const NSMapTableValueCallBacks NSIntMapValueCallBacks =
|
||||
|
@ -632,6 +636,14 @@ const NSMapTableValueCallBacks NSOwnedPointerMapValueCallBacks =
|
|||
(NSMT_describe_func_t) _NS_owned_void_p_describe
|
||||
};
|
||||
|
||||
/* These are to increase readabilty locally. */
|
||||
typedef unsigned int (*NSHT_hash_func_t)(NSHashTable *, const void *);
|
||||
typedef BOOL (*NSHT_isEqual_func_t)(NSHashTable *, const void *, const void *);
|
||||
typedef void (*NSHT_retain_func_t)(NSHashTable *, const void *);
|
||||
typedef void (*NSHT_release_func_t)(NSHashTable *, const void *);
|
||||
typedef NSString *(*NSHT_describe_func_t)(NSHashTable *, const void *);
|
||||
|
||||
/**** Function Prototypes ****************************************************/
|
||||
/** Standard NSHashTable callbacks... **/
|
||||
|
||||
const NSHashTableCallBacks NSIntHashCallBacks =
|
||||
|
@ -688,102 +700,3 @@ const NSHashTableCallBacks NSPointerToStructHashCallBacks =
|
|||
(NSHT_describe_func_t) _NS_int_p_describe
|
||||
};
|
||||
|
||||
/* Callbacks for (NUL-terminated) arrays of `char'. */
|
||||
|
||||
/* FIXME: Is this right?!? */
|
||||
#define _OBJECTS_NOT_A_CHAR_P_MARKER (const void *)(-1)
|
||||
|
||||
const void *o_not_a_char_p_marker = _OBJECTS_NOT_A_CHAR_P_MARKER;
|
||||
|
||||
const o_callbacks_t o_callbacks_for_char_p =
|
||||
{
|
||||
(o_hash_func_t) o_char_p_hash,
|
||||
(o_compare_func_t) o_char_p_compare,
|
||||
(o_is_equal_func_t) o_char_p_is_equal,
|
||||
(o_retain_func_t) o_char_p_retain,
|
||||
(o_release_func_t) o_char_p_release,
|
||||
(o_describe_func_t) o_char_p_describe,
|
||||
_OBJECTS_NOT_A_CHAR_P_MARKER
|
||||
};
|
||||
|
||||
/* Callbacks for `int' (and smaller) things. */
|
||||
|
||||
/* FIXME: This isn't right. Fix it. */
|
||||
#define _OBJECTS_NOT_AN_INT_MARKER (const void *)(-1)
|
||||
|
||||
const void *o_not_an_int_marker = _OBJECTS_NOT_AN_INT_MARKER;
|
||||
|
||||
const o_callbacks_t o_callbacks_for_int =
|
||||
{
|
||||
(o_hash_func_t) o_int_hash,
|
||||
(o_compare_func_t) o_int_compare,
|
||||
(o_is_equal_func_t) o_int_is_equal,
|
||||
(o_retain_func_t) o_int_retain,
|
||||
(o_release_func_t) o_int_release,
|
||||
(o_describe_func_t) o_int_describe,
|
||||
_OBJECTS_NOT_AN_INT_MARKER
|
||||
};
|
||||
|
||||
/* Callbacks for the Objective-C object type. */
|
||||
|
||||
/* FIXME: Is this right?!? */
|
||||
#define _OBJECTS_NOT_AN_ID_MARKER (const void *)(-1)
|
||||
|
||||
const void *o_not_an_id_marker = _OBJECTS_NOT_AN_ID_MARKER;
|
||||
|
||||
const o_callbacks_t o_callbacks_for_id =
|
||||
{
|
||||
(o_hash_func_t) o_id_hash,
|
||||
(o_compare_func_t) o_id_compare,
|
||||
(o_is_equal_func_t) o_id_is_equal,
|
||||
(o_retain_func_t) o_id_retain,
|
||||
(o_release_func_t) o_id_release,
|
||||
(o_describe_func_t) o_id_describe,
|
||||
_OBJECTS_NOT_AN_ID_MARKER
|
||||
};
|
||||
|
||||
/* Callbacks for pointers to `int'. */
|
||||
|
||||
/* FIXME: Is this right?!? */
|
||||
#define _OBJECTS_NOT_AN_INT_P_MARKER (const void *)(-1)
|
||||
|
||||
const void *o_not_an_int_p_marker = _OBJECTS_NOT_AN_INT_P_MARKER;
|
||||
|
||||
const o_callbacks_t o_callbacks_for_int_p =
|
||||
{
|
||||
(o_hash_func_t) o_int_p_hash,
|
||||
(o_compare_func_t) o_int_p_compare,
|
||||
(o_is_equal_func_t) o_int_p_is_equal,
|
||||
(o_retain_func_t) o_int_p_retain,
|
||||
(o_release_func_t) o_int_p_release,
|
||||
(o_describe_func_t) o_int_p_describe,
|
||||
_OBJECTS_NOT_AN_INT_P_MARKER
|
||||
};
|
||||
|
||||
/* Callbacks for pointers to `void'. */
|
||||
|
||||
/* FIXME: Is this right?!? */
|
||||
#define _OBJECTS_NOT_A_VOID_P_MARKER (const void *)(-1)
|
||||
|
||||
const void *o_not_a_void_p_marker = _OBJECTS_NOT_A_VOID_P_MARKER;
|
||||
|
||||
const o_callbacks_t o_callbacks_for_non_owned_void_p =
|
||||
{
|
||||
(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) o_non_owned_void_p_retain,
|
||||
(o_release_func_t) o_non_owned_void_p_release,
|
||||
_OBJECTS_NOT_A_VOID_P_MARKER
|
||||
};
|
||||
|
||||
const o_callbacks_t o_callbacks_for_owned_void_p =
|
||||
{
|
||||
(o_hash_func_t) o_owned_void_p_hash,
|
||||
(o_compare_func_t) o_owned_void_p_compare,
|
||||
(o_is_equal_func_t) o_owned_void_p_is_equal,
|
||||
(o_retain_func_t) o_owned_void_p_retain,
|
||||
(o_release_func_t) o_owned_void_p_release,
|
||||
_OBJECTS_NOT_A_VOID_P_MARKER
|
||||
};
|
||||
|
||||
|
|
912
Source/o_array.m
912
Source/o_array.m
|
@ -1,912 +0,0 @@
|
|||
/** A (pretty good) implementation of a sparse array.
|
||||
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Thu Mar 2 02:28:50 EST 1994
|
||||
* Updated: Tue Mar 12 02:42:33 EST 1996
|
||||
* Serial: 96.03.12.13
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <Foundation/NSZone.h>
|
||||
#include <base/o_cbs.h>
|
||||
#include <base/o_array.h>
|
||||
#include <base/o_hash.h>
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
/** Background functions **/
|
||||
|
||||
static inline size_t
|
||||
_o_array_fold_index(size_t index, size_t slot_count)
|
||||
{
|
||||
return (slot_count ? (index % slot_count) : 0);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
_o_array_internal_index(o_array_t *array, size_t index)
|
||||
{
|
||||
return _o_array_fold_index (index, array->slot_count);
|
||||
}
|
||||
|
||||
static inline o_array_slot_t *
|
||||
_o_array_slot_for_index(o_array_t *array, size_t index)
|
||||
{
|
||||
return (array->slots + _o_array_internal_index (array, index));
|
||||
}
|
||||
|
||||
static inline o_array_bucket_t *
|
||||
_o_array_bucket_for_index (o_array_t *array, size_t index)
|
||||
{
|
||||
o_array_slot_t *slot;
|
||||
o_array_bucket_t *bucket;
|
||||
|
||||
/* First, we translate the index into a bucket index to find our
|
||||
* candidate for the bucket. */
|
||||
slot = _o_array_slot_for_index (array, index);
|
||||
bucket = *slot;
|
||||
|
||||
/* But we need to check to see whether this is really the bucket we
|
||||
* wanted. */
|
||||
if (bucket != 0 && bucket->index == index)
|
||||
/* Bucket `index' exists, and we've got it, so... */
|
||||
return bucket;
|
||||
else
|
||||
/* Either no bucket or some other bucket is where bucket `index'
|
||||
* would be, if it existed. So... */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline o_array_bucket_t *
|
||||
_o_array_new_bucket (o_array_t *array, size_t index, const void *element)
|
||||
{
|
||||
o_array_bucket_t *bucket;
|
||||
|
||||
bucket = (o_array_bucket_t *) NSZoneMalloc(o_array_zone(array),
|
||||
sizeof(o_array_bucket_t));
|
||||
if (bucket != 0)
|
||||
{
|
||||
o_retain(o_array_element_callbacks(array), element, array);
|
||||
bucket->index = index;
|
||||
bucket->element = element;
|
||||
}
|
||||
return bucket;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_o_array_free_bucket(o_array_t *array,
|
||||
o_array_bucket_t *bucket)
|
||||
{
|
||||
if (bucket != 0)
|
||||
{
|
||||
o_release(o_array_element_callbacks (array),
|
||||
(void *)(bucket->element),
|
||||
array);
|
||||
NSZoneFree(o_array_zone(array), bucket);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static inline o_array_slot_t *
|
||||
_o_array_new_slots(o_array_t *array, size_t slot_count)
|
||||
{
|
||||
return (o_array_slot_t *) NSZoneCalloc(o_array_zone(array),
|
||||
slot_count,
|
||||
sizeof(o_array_slot_t));
|
||||
}
|
||||
|
||||
static inline void
|
||||
_o_array_free_slots(o_array_t *array,
|
||||
o_array_slot_t *slots)
|
||||
{
|
||||
if (slots != 0)
|
||||
NSZoneFree(o_array_zone(array), slots);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_o_array_empty_slot (o_array_t *array, o_array_slot_t * slot)
|
||||
{
|
||||
if (*slot != 0)
|
||||
{
|
||||
/* Get rid of the bucket. */
|
||||
_o_array_free_bucket (array, *slot);
|
||||
|
||||
/* Mark the slot as empty. */
|
||||
*slot = 0;
|
||||
|
||||
/* Keep the element count accurate */
|
||||
--(array->element_count);
|
||||
}
|
||||
|
||||
/* And return. */
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_o_array_insert_bucket(o_array_t *array,
|
||||
o_array_bucket_t * bucket)
|
||||
{
|
||||
o_array_slot_t *slot;
|
||||
|
||||
slot = _o_array_slot_for_index (array, bucket->index);
|
||||
|
||||
/* We're adding a bucket, so the current set of sorted slots is now
|
||||
* invalidated. */
|
||||
if (array->sorted_slots != 0)
|
||||
{
|
||||
_o_array_free_slots (array, array->sorted_slots);
|
||||
array->sorted_slots = 0;
|
||||
}
|
||||
|
||||
if ((*slot) == 0)
|
||||
{
|
||||
/* There's nothing there, so we can put `bucket' there. */
|
||||
*slot = bucket;
|
||||
|
||||
/* Increment the array's bucket counter. */
|
||||
++(array->element_count);
|
||||
return;
|
||||
}
|
||||
if ((*slot)->index == bucket->index)
|
||||
{
|
||||
/* There's a bucket there, and it has the same index as `bucket'.
|
||||
* So we get rid of the old one, and put the new one in its
|
||||
* place. */
|
||||
_o_array_free_bucket (array, *slot);
|
||||
*slot = bucket;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Now we get to fiddle around with things to make the world a
|
||||
* better place... */
|
||||
|
||||
size_t new_slot_count;
|
||||
o_array_slot_t *new_slots; /* This guy holds the buckets while we
|
||||
* muck about with them. */
|
||||
size_t d; /* Just a counter */
|
||||
|
||||
/* FIXME: I *really* wish I had a way of generating
|
||||
* statistically better initial values for this variable. So
|
||||
* I'll run a few tests and see... And is there a better
|
||||
* algorithm, e.g., a better collection of sizes in the sense
|
||||
* that the likelyhood of fitting everything in earlier is
|
||||
* high? Well, enough mumbling. */
|
||||
/* At any rate, we're guaranteed to need at least this many. */
|
||||
new_slot_count = array->element_count + 1;
|
||||
|
||||
do
|
||||
{
|
||||
/* First we make a new pile of slots for the buckets. */
|
||||
new_slots = _o_array_new_slots (array, new_slot_count);
|
||||
|
||||
if (new_slots == 0)
|
||||
/* FIXME: Make this a *little* more friendly. */
|
||||
abort();
|
||||
|
||||
/* Then we put the new bucket in the pile. */
|
||||
new_slots[_o_array_fold_index (bucket->index,
|
||||
new_slot_count)] = bucket;
|
||||
|
||||
/* Now loop and try to place the others. Upon collision
|
||||
* with a previously inserted bucket, try again with more
|
||||
* `new_slots'. */
|
||||
for (d = 0; d < array->slot_count; ++d)
|
||||
{
|
||||
if (array->slots[d] != 0)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
i = _o_array_fold_index (array->slots[d]->index,
|
||||
new_slot_count);
|
||||
|
||||
if (new_slots[i] == 0)
|
||||
{
|
||||
new_slots[i] = array->slots[d];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A collision. Clean up and try again. */
|
||||
|
||||
/* Free the current set of new buckets. */
|
||||
_o_array_free_slots (array, new_slots);
|
||||
|
||||
/* Bump up the number of new buckets. */
|
||||
++new_slot_count;
|
||||
|
||||
/* Break out of the `for' loop. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (d < array->slot_count);
|
||||
|
||||
if (array->slots != 0)
|
||||
_o_array_free_slots (array, array->slots);
|
||||
|
||||
array->slots = new_slots;
|
||||
array->slot_count = new_slot_count;
|
||||
++(array->element_count);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
_o_array_compare_slots (const o_array_slot_t *slot1,
|
||||
const o_array_slot_t *slot2)
|
||||
{
|
||||
if (slot1 == slot2)
|
||||
return 0;
|
||||
if (*slot1 == 0)
|
||||
return 1;
|
||||
if (*slot2 == 0)
|
||||
return -1;
|
||||
|
||||
if ((*slot1)->index < (*slot2)->index)
|
||||
return -1;
|
||||
else if ((*slot1)->index > (*slot2)->index)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef int (*qsort_compare_func_t) (const void *, const void *);
|
||||
|
||||
static inline void
|
||||
_o_array_make_sorted_slots (o_array_t *array)
|
||||
{
|
||||
o_array_slot_t *new_slots;
|
||||
|
||||
/* If there're already some sorted slots, then they're valid, and
|
||||
* we're done. */
|
||||
if (array->sorted_slots != 0)
|
||||
return;
|
||||
|
||||
/* Make some new slots. */
|
||||
new_slots = _o_array_new_slots (array, array->slot_count);
|
||||
|
||||
/* Copy the pointers to buckets into the new slots. */
|
||||
memcpy (new_slots, array->slots, (array->slot_count
|
||||
* sizeof (o_array_slot_t)));
|
||||
|
||||
/* Sort the new slots. */
|
||||
qsort (new_slots, array->slot_count, sizeof (o_array_slot_t),
|
||||
(qsort_compare_func_t) _o_array_compare_slots);
|
||||
|
||||
/* Put the newly sorted slots in the `sorted_slots' element of the
|
||||
* array structure. */
|
||||
array->sorted_slots = new_slots;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static inline o_array_bucket_t *
|
||||
_o_array_enumerator_next_bucket (o_array_enumerator_t *enumerator)
|
||||
{
|
||||
if (enumerator->is_sorted)
|
||||
{
|
||||
if (enumerator->is_ascending)
|
||||
{
|
||||
if (enumerator->array->sorted_slots == 0)
|
||||
return 0;
|
||||
|
||||
if (enumerator->index < enumerator->array->element_count)
|
||||
{
|
||||
o_array_bucket_t *bucket;
|
||||
|
||||
bucket = enumerator->array->sorted_slots[enumerator->index];
|
||||
++(enumerator->index);
|
||||
return bucket;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (enumerator->array->sorted_slots == 0)
|
||||
return 0;
|
||||
|
||||
if (enumerator->index > 0)
|
||||
{
|
||||
o_array_bucket_t *bucket;
|
||||
|
||||
--(enumerator->index);
|
||||
bucket = enumerator->array->sorted_slots[enumerator->index];
|
||||
return bucket;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
o_array_bucket_t *bucket;
|
||||
|
||||
if (enumerator->array->slots == 0)
|
||||
return 0;
|
||||
|
||||
for (bucket = 0;
|
||||
(enumerator->index < enumerator->array->slot_count
|
||||
&& bucket == 0);
|
||||
++(enumerator->index))
|
||||
{
|
||||
bucket = enumerator->array->slots[enumerator->index];
|
||||
}
|
||||
|
||||
return bucket;
|
||||
}
|
||||
}
|
||||
|
||||
/** Statistics **/
|
||||
|
||||
size_t
|
||||
o_array_count(o_array_t *array)
|
||||
{
|
||||
return array->element_count;
|
||||
}
|
||||
|
||||
size_t
|
||||
o_array_capacity (o_array_t *array)
|
||||
{
|
||||
return array->slot_count;
|
||||
}
|
||||
|
||||
int
|
||||
o_array_check(o_array_t *array)
|
||||
{
|
||||
/* FIXME: Code this. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
o_array_is_empty(o_array_t *array)
|
||||
{
|
||||
return o_array_count (array) != 0;
|
||||
}
|
||||
|
||||
/** Emptying **/
|
||||
|
||||
void
|
||||
o_array_empty(o_array_t *array)
|
||||
{
|
||||
size_t c;
|
||||
|
||||
/* Just empty each slot out, one by one. */
|
||||
for (c = 0; c < array->slot_count; ++c)
|
||||
_o_array_empty_slot (array, array->slots + c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Creating **/
|
||||
|
||||
o_array_t *
|
||||
o_array_alloc_with_zone(NSZone *zone)
|
||||
{
|
||||
o_array_t *array;
|
||||
|
||||
/* Get a new array. */
|
||||
array = _o_array_alloc_with_zone(zone);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
o_array_t *
|
||||
o_array_alloc(void)
|
||||
{
|
||||
return o_array_alloc_with_zone(NSDefaultMallocZone());
|
||||
}
|
||||
|
||||
o_array_t *
|
||||
o_array_with_zone(NSZone *zone)
|
||||
{
|
||||
return o_array_init(o_array_alloc_with_zone(zone));
|
||||
}
|
||||
|
||||
o_array_t *
|
||||
o_array_with_zone_with_callbacks(NSZone *zone,
|
||||
o_callbacks_t callbacks)
|
||||
{
|
||||
return o_array_init_with_callbacks(o_array_alloc_with_zone(zone),
|
||||
callbacks);
|
||||
}
|
||||
|
||||
o_array_t *
|
||||
o_array_with_callbacks(o_callbacks_t callbacks)
|
||||
{
|
||||
return o_array_init_with_callbacks(o_array_alloc(), callbacks);
|
||||
}
|
||||
|
||||
o_array_t *
|
||||
o_array_of_char_p(void)
|
||||
{
|
||||
return o_array_with_callbacks(o_callbacks_for_char_p);
|
||||
}
|
||||
|
||||
o_array_t *
|
||||
o_array_of_non_owned_void_p(void)
|
||||
{
|
||||
return o_array_with_callbacks(o_callbacks_for_non_owned_void_p);
|
||||
}
|
||||
|
||||
o_array_t *
|
||||
o_array_of_owned_void_p(void)
|
||||
{
|
||||
return o_array_with_callbacks(o_callbacks_for_owned_void_p);
|
||||
}
|
||||
|
||||
o_array_t *
|
||||
o_array_of_int(void)
|
||||
{
|
||||
return o_array_with_callbacks(o_callbacks_for_int);
|
||||
}
|
||||
|
||||
o_array_t *
|
||||
o_array_of_id(void)
|
||||
{
|
||||
return o_array_with_callbacks(o_callbacks_for_id);
|
||||
}
|
||||
|
||||
/** Initializing **/
|
||||
|
||||
o_array_t *
|
||||
o_array_init_with_callbacks(o_array_t *array,
|
||||
o_callbacks_t callbacks)
|
||||
{
|
||||
if (array != 0)
|
||||
{
|
||||
/* The default capacity is 15. */
|
||||
size_t capacity = 15;
|
||||
|
||||
/* Record the element callbacks. */
|
||||
array->callbacks = o_callbacks_standardize(callbacks);
|
||||
|
||||
/* Initialize ARRAY's information. */
|
||||
array->element_count = 0;
|
||||
array->slot_count = capacity + 1;
|
||||
|
||||
/* Make some new slots. */
|
||||
array->slots = _o_array_new_slots(array, capacity + 1);
|
||||
|
||||
/* Get the sorted slots ready for later use. */
|
||||
array->sorted_slots = 0;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
o_array_t *
|
||||
o_array_init (o_array_t *array)
|
||||
{
|
||||
return o_array_init_with_callbacks (array,
|
||||
o_callbacks_standard());
|
||||
}
|
||||
|
||||
o_array_t *
|
||||
o_array_init_from_array (o_array_t *array, o_array_t *old_array)
|
||||
{
|
||||
o_array_enumerator_t enumerator;
|
||||
size_t index;
|
||||
const void *element;
|
||||
|
||||
/* Initialize ARRAY in the usual way. */
|
||||
o_array_init_with_callbacks (array,
|
||||
o_array_element_callbacks (old_array));
|
||||
|
||||
/* Get an enumerator for OLD_ARRAY. */
|
||||
enumerator = o_array_enumerator (old_array);
|
||||
|
||||
/* Step through OLD_ARRAY's elements, putting them at the proper
|
||||
* index in ARRAY. */
|
||||
while (o_array_enumerator_next_index_and_element (&enumerator,
|
||||
&index, &element))
|
||||
{
|
||||
o_array_at_index_put_element (array, index, element);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Destroying **/
|
||||
|
||||
void
|
||||
o_array_dealloc(o_array_t *array)
|
||||
{
|
||||
if (array != 0)
|
||||
{
|
||||
/* Empty out ARRAY. */
|
||||
o_array_empty (array);
|
||||
|
||||
/* Free up its slots. */
|
||||
_o_array_free_slots (array, array->slots);
|
||||
|
||||
/* FIXME: What about ARRAY's sorted slots? */
|
||||
|
||||
/* Free up ARRAY itself. */
|
||||
_o_array_dealloc (array);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Searching **/
|
||||
|
||||
const void *
|
||||
o_array_element_at_index (o_array_t *array, size_t index)
|
||||
{
|
||||
o_array_bucket_t *bucket = _o_array_bucket_for_index (array, index);
|
||||
|
||||
if (bucket != 0)
|
||||
return bucket->element;
|
||||
else
|
||||
/* If `bucket' is 0, then the requested index is unused. */
|
||||
/* There's no bucket, so... */
|
||||
return o_array_not_an_element_marker (array);
|
||||
}
|
||||
|
||||
size_t
|
||||
o_array_index_of_element (o_array_t *array, const void *element)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < array->slot_count; ++i)
|
||||
{
|
||||
o_array_bucket_t *bucket = array->slots[i];
|
||||
|
||||
if (bucket != 0)
|
||||
if (o_is_equal (o_array_element_callbacks (array),
|
||||
bucket->element,
|
||||
element,
|
||||
array))
|
||||
return bucket->index;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
o_array_contains_element (o_array_t *array, const void *element)
|
||||
{
|
||||
/* Note that this search is quite inefficient. */
|
||||
return o_array_index_of_element (array, element) < (array->slot_count);
|
||||
}
|
||||
|
||||
const void **
|
||||
o_array_all_elements (o_array_t *array)
|
||||
{
|
||||
o_array_enumerator_t enumerator;
|
||||
const void **elements;
|
||||
size_t count, i;
|
||||
|
||||
count = o_array_count (array);
|
||||
|
||||
/* Set aside space to hold the elements. */
|
||||
elements = (const void **)NSZoneCalloc(o_array_zone(array),
|
||||
count + 1,
|
||||
sizeof(const void *));
|
||||
|
||||
enumerator = o_array_enumerator(array);
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
o_array_enumerator_next_element (&enumerator, elements + i);
|
||||
|
||||
elements[i] = o_array_not_an_element_marker(array);
|
||||
|
||||
/* We're done, so heave it back. */
|
||||
return elements;
|
||||
}
|
||||
|
||||
const void **
|
||||
o_array_all_elements_ascending (o_array_t *array)
|
||||
{
|
||||
o_array_enumerator_t enumerator;
|
||||
const void **elements;
|
||||
size_t count, i;
|
||||
|
||||
count = o_array_count (array);
|
||||
|
||||
/* Set aside space to hold the elements. */
|
||||
elements = (const void **)NSZoneCalloc(o_array_zone(array),
|
||||
count + 1,
|
||||
sizeof(const void *));
|
||||
|
||||
enumerator = o_array_ascending_enumerator (array);
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
o_array_enumerator_next_element (&enumerator, elements + i);
|
||||
|
||||
elements[i] = o_array_not_an_element_marker (array);
|
||||
|
||||
/* We're done, so heave it back. */
|
||||
return elements;
|
||||
}
|
||||
|
||||
const void **
|
||||
o_array_all_elements_descending (o_array_t *array)
|
||||
{
|
||||
o_array_enumerator_t enumerator;
|
||||
const void **elements;
|
||||
size_t count, i;
|
||||
|
||||
count = o_array_count (array);
|
||||
|
||||
/* Set aside space to hold the elements. */
|
||||
elements = (const void **)NSZoneCalloc(o_array_zone(array),
|
||||
count + 1,
|
||||
sizeof(const void *));
|
||||
|
||||
enumerator = o_array_descending_enumerator (array);
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
o_array_enumerator_next_element (&enumerator, elements + i);
|
||||
|
||||
elements[i] = o_array_not_an_element_marker (array);
|
||||
|
||||
/* We're done, so heave it back. */
|
||||
return elements;
|
||||
}
|
||||
|
||||
/** Removing **/
|
||||
|
||||
void
|
||||
o_array_remove_element_at_index (o_array_t *array, size_t index)
|
||||
{
|
||||
o_array_bucket_t *bucket;
|
||||
|
||||
/* Get the bucket that might be there. */
|
||||
bucket = _o_array_bucket_for_index (array, index);
|
||||
|
||||
/* If there's a bucket at the index, then we empty its slot out. */
|
||||
if (bucket != 0)
|
||||
_o_array_empty_slot (array, _o_array_slot_for_index (array, index));
|
||||
|
||||
/* Finally, we return. */
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
o_array_remove_element_known_present (o_array_t *array,
|
||||
const void *element)
|
||||
{
|
||||
o_array_remove_element_at_index (array,
|
||||
o_array_index_of_element (array,
|
||||
element));
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
o_array_remove_element (o_array_t *array, const void *element)
|
||||
{
|
||||
if (o_array_contains_element (array, element))
|
||||
o_array_remove_element_known_present (array, element);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Adding **/
|
||||
|
||||
const void *
|
||||
o_array_at_index_put_element (o_array_t *array,
|
||||
size_t index,
|
||||
const void *element)
|
||||
{
|
||||
o_array_bucket_t *bucket;
|
||||
|
||||
/* Clean out anything that's already there. */
|
||||
o_array_remove_element_at_index (array, index);
|
||||
|
||||
/* Make a bucket for our information. */
|
||||
bucket = _o_array_new_bucket (array, index, element);
|
||||
|
||||
/* Put our bucket in the array. */
|
||||
_o_array_insert_bucket (array, bucket);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/** Enumerating **/
|
||||
|
||||
o_array_enumerator_t
|
||||
o_array_ascending_enumerator (o_array_t *array)
|
||||
{
|
||||
o_array_enumerator_t enumerator;
|
||||
|
||||
enumerator.array = array;
|
||||
enumerator.is_sorted = 1;
|
||||
enumerator.is_ascending = 1;
|
||||
enumerator.index = 0;
|
||||
|
||||
_o_array_make_sorted_slots (array);
|
||||
|
||||
return enumerator;
|
||||
}
|
||||
|
||||
o_array_enumerator_t
|
||||
o_array_descending_enumerator (o_array_t *array)
|
||||
{
|
||||
o_array_enumerator_t enumerator;
|
||||
|
||||
enumerator.array = array;
|
||||
enumerator.is_sorted = 1;
|
||||
enumerator.is_ascending = 0;
|
||||
/* The `+ 1' is so that we have `0' as a known ending condition.
|
||||
* See `_o_array_enumerator_next_bucket()'. */
|
||||
enumerator.index = array->element_count + 1;
|
||||
|
||||
_o_array_make_sorted_slots (array);
|
||||
|
||||
return enumerator;
|
||||
}
|
||||
|
||||
o_array_enumerator_t
|
||||
o_array_enumerator (o_array_t *array)
|
||||
{
|
||||
o_array_enumerator_t enumerator;
|
||||
|
||||
enumerator.array = array;
|
||||
enumerator.is_sorted = 0;
|
||||
enumerator.is_ascending = 0;
|
||||
enumerator.index = 0;
|
||||
|
||||
return enumerator;
|
||||
}
|
||||
|
||||
int
|
||||
o_array_enumerator_next_index_and_element (o_array_enumerator_t * enumerator,
|
||||
size_t * index,
|
||||
const void **element)
|
||||
{
|
||||
o_array_bucket_t *bucket;
|
||||
|
||||
bucket = _o_array_enumerator_next_bucket (enumerator);
|
||||
|
||||
if (bucket != 0)
|
||||
{
|
||||
if (element != 0)
|
||||
*element = bucket->element;
|
||||
if (index != 0)
|
||||
*index = bucket->index;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (element != 0)
|
||||
*element = o_array_not_an_element_marker (enumerator->array);
|
||||
if (index != 0)
|
||||
*index = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
o_array_enumerator_next_element (o_array_enumerator_t * enumerator,
|
||||
const void **element)
|
||||
{
|
||||
return o_array_enumerator_next_index_and_element (enumerator,
|
||||
0,
|
||||
element);
|
||||
}
|
||||
|
||||
int
|
||||
o_array_enumerator_next_index (o_array_enumerator_t * enumerator,
|
||||
size_t * index)
|
||||
{
|
||||
return o_array_enumerator_next_index_and_element (enumerator,
|
||||
index,
|
||||
0);
|
||||
}
|
||||
|
||||
/** Comparing **/
|
||||
|
||||
int
|
||||
o_array_is_equal_to_array (o_array_t *array1, o_array_t *array2)
|
||||
{
|
||||
size_t a, b;
|
||||
const void *m, *n;
|
||||
o_array_enumerator_t e, f;
|
||||
|
||||
a = o_array_count (array1);
|
||||
b = o_array_count (array2);
|
||||
|
||||
if (a < b)
|
||||
return (b - a);
|
||||
if (a > b)
|
||||
return (a - b);
|
||||
|
||||
/* Get ascending enumerators for each of the two arrays. */
|
||||
e = o_array_ascending_enumerator (array1);
|
||||
e = o_array_ascending_enumerator (array1);
|
||||
|
||||
while (o_array_enumerator_next_index_and_element (&e, &a, &m)
|
||||
&& o_array_enumerator_next_index_and_element (&f, &b, &n))
|
||||
{
|
||||
int c, d;
|
||||
|
||||
if (a < b)
|
||||
return (b - a);
|
||||
if (a > b)
|
||||
return (a - b);
|
||||
|
||||
c = o_compare (o_array_element_callbacks (array1), m, n, array1);
|
||||
if (c != 0)
|
||||
return c;
|
||||
|
||||
d = o_compare (o_array_element_callbacks (array2), n, m, array2);
|
||||
if (d != 0)
|
||||
return d;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Mapping **/
|
||||
|
||||
o_array_t *
|
||||
o_array_map_elements(o_array_t *array,
|
||||
const void *(*fcn) (const void *, const void *),
|
||||
const void *user_data)
|
||||
{
|
||||
/* FIXME: Code this. */
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Miscellaneous **/
|
||||
|
||||
o_hash_t *
|
||||
o_hash_init_from_array (o_hash_t * hash, o_array_t *array)
|
||||
{
|
||||
o_array_enumerator_t enumerator;
|
||||
const void *element;
|
||||
|
||||
/* NOTE: If ARRAY contains multiple elements of the same equivalence
|
||||
* class, it is indeterminate which will end up in HASH. This
|
||||
* shouldn't matter, though. */
|
||||
enumerator = o_array_enumerator (array);
|
||||
|
||||
/* Just walk through ARRAY's elements and add them to HASH. */
|
||||
while (o_array_enumerator_next_element (&enumerator, &element))
|
||||
o_hash_add_element (hash, element);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
// o_chash_t *
|
||||
// o_chash_init_from_array (o_chash_t * chash, o_array_t *array)
|
||||
// {
|
||||
// o_array_enumerator_t enumerator;
|
||||
// const void *element;
|
||||
//
|
||||
// /* NOTE: If ARRAY contains multiple elements of the same equivalence
|
||||
// * class, it is indeterminate which will end up in CHASH. This
|
||||
// * shouldn't matter, though. */
|
||||
// enumerator = o_array_enumerator (array);
|
||||
//
|
||||
// /* Just walk through ARRAY's elements and add them to CHASH. */
|
||||
// while (o_array_enumerator_next_element (&enumerator, &element))
|
||||
// o_chash_add_element (chash, element);
|
||||
//
|
||||
// return chash;
|
||||
// }
|
||||
|
152
Source/o_cbs.m
152
Source/o_cbs.m
|
@ -1,152 +0,0 @@
|
|||
/* Handling various types in a uniform manner.
|
||||
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Sun Oct 9 13:14:41 EDT 1994
|
||||
* Updated: Mon Mar 11 02:17:32 EST 1996
|
||||
* Serial: 96.03.11.08
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <config.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <base/o_cbs.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
/* WARNING: Don't change this unless you know what you're getting into! */
|
||||
static o_callbacks_t ___o_callbacks_standard =
|
||||
{
|
||||
(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) o_non_owned_void_p_retain,
|
||||
(o_release_func_t) o_non_owned_void_p_release,
|
||||
(o_describe_func_t) o_non_owned_void_p_describe,
|
||||
0
|
||||
};
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
/** Getting the standard callbacks... **/
|
||||
|
||||
o_callbacks_t
|
||||
o_callbacks_standard(void)
|
||||
{
|
||||
return ___o_callbacks_standard;
|
||||
}
|
||||
|
||||
/** Standardizing callbacks... **/
|
||||
|
||||
o_callbacks_t
|
||||
o_callbacks_standardize(o_callbacks_t callbacks)
|
||||
{
|
||||
if (callbacks.hash == 0)
|
||||
callbacks.hash = o_callbacks_standard().hash;
|
||||
|
||||
if (callbacks.compare == 0 && callbacks.is_equal == 0)
|
||||
{
|
||||
callbacks.compare = o_callbacks_standard().compare;
|
||||
callbacks.is_equal = o_callbacks_standard().is_equal;
|
||||
}
|
||||
|
||||
if (callbacks.retain == 0)
|
||||
callbacks.retain = o_callbacks_standard().retain;
|
||||
|
||||
if (callbacks.release == 0)
|
||||
callbacks.release = o_callbacks_standard().release;
|
||||
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
/** Using callbacks... **/
|
||||
|
||||
size_t
|
||||
o_hash(o_callbacks_t callbacks,
|
||||
const void *thing,
|
||||
void *user_data)
|
||||
{
|
||||
if (callbacks.hash != 0)
|
||||
return callbacks.hash(thing, user_data);
|
||||
else
|
||||
return o_callbacks_standard().hash(thing, user_data);
|
||||
}
|
||||
|
||||
int
|
||||
o_compare(o_callbacks_t callbacks,
|
||||
const void *thing1,
|
||||
const void *thing2,
|
||||
void *user_data)
|
||||
{
|
||||
if (callbacks.compare != 0)
|
||||
return callbacks.compare(thing1, thing2, user_data);
|
||||
else if (callbacks.is_equal != 0)
|
||||
return !(callbacks.is_equal(thing1, thing2, user_data));
|
||||
else
|
||||
return o_callbacks_standard().compare(thing1, thing2, user_data);
|
||||
}
|
||||
|
||||
int
|
||||
o_is_equal(o_callbacks_t callbacks,
|
||||
const void *thing1,
|
||||
const void *thing2,
|
||||
void *user_data)
|
||||
{
|
||||
if (callbacks.is_equal != 0)
|
||||
return callbacks.is_equal(thing1, thing2, user_data);
|
||||
else if (callbacks.compare != 0)
|
||||
return !(callbacks.compare(thing1, thing2, user_data));
|
||||
else
|
||||
return o_callbacks_standard().is_equal(thing1, thing2, user_data);
|
||||
}
|
||||
|
||||
const void *
|
||||
o_retain(o_callbacks_t callbacks,
|
||||
const void *thing,
|
||||
void *user_data)
|
||||
{
|
||||
if (callbacks.retain != 0)
|
||||
return callbacks.retain(thing, user_data);
|
||||
else
|
||||
return o_callbacks_standard().retain(thing, user_data);
|
||||
}
|
||||
|
||||
void
|
||||
o_release(o_callbacks_t callbacks,
|
||||
void *thing,
|
||||
void *user_data)
|
||||
{
|
||||
if (callbacks.release != 0)
|
||||
callbacks.release (thing, user_data);
|
||||
else
|
||||
o_callbacks_standard().release(thing, user_data);
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
o_describe(o_callbacks_t callbacks,
|
||||
const void *thing,
|
||||
void *user_data)
|
||||
{
|
||||
if (callbacks.release != 0)
|
||||
return callbacks.describe(thing, user_data);
|
||||
else
|
||||
return o_callbacks_standard().describe(thing, user_data);
|
||||
}
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
/* Callbacks for (NUL-terminated) arrays of `char'.
|
||||
* Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Sat Feb 10 22:04:38 EST 1996
|
||||
* Updated: Mon Mar 11 03:09:33 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include <Foundation/NSString.h>
|
||||
#include <base/o_cbs.h>
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
size_t
|
||||
o_char_p_hash(const char *cptr)
|
||||
{
|
||||
register const char *s = cptr;
|
||||
register size_t h = 0;
|
||||
register size_t c = 0;
|
||||
|
||||
while (*s != '\0')
|
||||
h ^= *(s++) << (c++);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
int
|
||||
o_char_p_compare(const char *cptr, const char *dptr)
|
||||
{
|
||||
register const char *s = (char *) cptr;
|
||||
register const char *t = (char *) dptr;
|
||||
|
||||
if (s == t)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
register char c;
|
||||
register char d;
|
||||
|
||||
while ((c = *(s++)) == (d = *(s++)))
|
||||
if (c == '\0')
|
||||
return 0;
|
||||
|
||||
return (c - d);
|
||||
}
|
||||
}
|
||||
|
||||
/* Determines whether or not CPTR is the same (`NUL'-terminated)
|
||||
* character string as DPTR. Returns true if CPTR and DPTR are the same,
|
||||
* and false otherwise. Note that we are performing no
|
||||
* internationalization here. CPTR and DPTR are taken to be C strings
|
||||
* in the default (seven or) eight bit character encoding. */
|
||||
int
|
||||
o_char_p_is_equal(const char *cptr, const char *dptr)
|
||||
{
|
||||
register const char *s = cptr;
|
||||
register const char *t = dptr;
|
||||
|
||||
if (s == t)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
register char c;
|
||||
register char d;
|
||||
|
||||
while ((c = *(s++)) == (d = *(t++)))
|
||||
if (c == '\0')
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const void *
|
||||
o_char_p_retain(const char *cptr)
|
||||
{
|
||||
return (const void *)cptr;
|
||||
}
|
||||
|
||||
void
|
||||
o_char_p_release(char *cptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
o_char_p_describe(const char *cptr)
|
||||
{
|
||||
/* FIXME: Code this. */
|
||||
return nil;
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
/* Callbacks for the Objective-C object type. */
|
||||
/* Copyright (C) 1996 Free Software Foundation, Inc. */
|
||||
|
||||
/* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Sat Feb 10 15:55:51 EST 1996
|
||||
* Updated: Sun Feb 11 01:42:20 EST 1996
|
||||
* Serial: 96.02.11.05
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include <Foundation/NSObject.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <base/o_cbs.h>
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
/* FIXME: It sure would be nice if we had a way of checking whether
|
||||
* or not these objects responded to the messages we're sending them here.
|
||||
* We need a way that is independent of whether we have GNUStep objects,
|
||||
* NEXTSTEP objects, or GNU objects. We could certainly just use the
|
||||
* same trick that the `respondsToSelector:' method itself uses, but I'd hoped
|
||||
* that there was already a built-in call to do this sort of thing. */
|
||||
|
||||
size_t
|
||||
o_id_hash(id obj)
|
||||
{
|
||||
return (size_t)[obj hash];
|
||||
}
|
||||
|
||||
int
|
||||
o_id_compare(id obj, id jbo)
|
||||
{
|
||||
return (int)[obj compare:jbo];
|
||||
}
|
||||
|
||||
int
|
||||
o_id_is_equal(id obj, id jbo)
|
||||
{
|
||||
return (int)[obj isEqual:jbo];
|
||||
}
|
||||
|
||||
const void *
|
||||
o_id_retain(id obj)
|
||||
{
|
||||
return (const void *)[obj retain];
|
||||
}
|
||||
|
||||
void
|
||||
o_id_release(id obj)
|
||||
{
|
||||
[obj release];
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
o_id_describe(id obj)
|
||||
{
|
||||
return [obj description];
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/* Callbacks for `int' (and smaller) things. */
|
||||
/* Copyright (C) 1996 Free Software Foundation, Inc. */
|
||||
|
||||
/* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Sat Feb 10 15:55:51 EST 1996
|
||||
* Updated: Mon Mar 11 00:23:10 EST 1996
|
||||
* Serial: 96.03.11.01
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include <Foundation/NSString.h>
|
||||
#include <base/o_cbs.h>
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
/* FIXME: We (like OpenStep) make the big assumption here that
|
||||
* 'sizeof(int) <= sizeof(void *)'....This is probably not a good thing,
|
||||
* but what can I do? */
|
||||
|
||||
size_t
|
||||
o_int_hash(int i)
|
||||
{
|
||||
return (size_t)i;
|
||||
}
|
||||
|
||||
int
|
||||
o_int_compare(int i, int j)
|
||||
{
|
||||
return i - j;
|
||||
}
|
||||
|
||||
int
|
||||
o_int_is_equal(int i, int j)
|
||||
{
|
||||
return i == j;
|
||||
}
|
||||
|
||||
const void *
|
||||
o_int_retain(int i)
|
||||
{
|
||||
return (const void *)i;
|
||||
}
|
||||
|
||||
void
|
||||
o_int_release(int i)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
o_int_describe(int i)
|
||||
{
|
||||
/* FIXME: Code this. */
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/* Callbacks for pointers to `int'.
|
||||
* Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Sat Feb 10 15:55:51 EST 1996
|
||||
* Updated: Sun Feb 11 01:49:55 EST 1996
|
||||
* Serial: 96.02.11.04
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include <Foundation/NSString.h>
|
||||
#include <base/o_cbs.h>
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
size_t
|
||||
o_int_p_hash(const int *iptr)
|
||||
{
|
||||
return (size_t)(iptr) / 4;
|
||||
}
|
||||
|
||||
int
|
||||
o_int_p_compare(const int *iptr, const int *jptr)
|
||||
{
|
||||
if (iptr < jptr)
|
||||
return -1;
|
||||
else if (iptr > jptr)
|
||||
return 1;
|
||||
else /* (iptr == jptr) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
o_int_p_is_equal(const int *iptr, const int *jptr)
|
||||
{
|
||||
/* FIXME: Is this right? If not, what else could it be? */
|
||||
return iptr == jptr;
|
||||
}
|
||||
|
||||
const void *
|
||||
o_int_p_retain(const int *iptr)
|
||||
{
|
||||
return (const void *)iptr;
|
||||
}
|
||||
|
||||
void
|
||||
o_int_p_release(int *iptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
o_int_p_describe(const int *iptr)
|
||||
{
|
||||
/* FIXME: Code this. */
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
/* Callbacks for pointers to `void'.
|
||||
* Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Sat Feb 10 22:04:38 EST 1996
|
||||
* Updated: Mon Mar 11 02:03:13 EST 1996
|
||||
* Serial: 96.03.11.04
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include <Foundation/NSString.h>
|
||||
#include <base/o_cbs.h>
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
size_t
|
||||
o_non_owned_void_p_hash(register const void *cptr)
|
||||
{
|
||||
return ((size_t) cptr)/4;
|
||||
}
|
||||
|
||||
int
|
||||
o_non_owned_void_p_compare(register const void *cptr,
|
||||
register const void *dptr)
|
||||
{
|
||||
if (cptr == dptr)
|
||||
return 0;
|
||||
else if (cptr < dptr)
|
||||
return -1;
|
||||
else /* if (cptr > dptr) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
o_non_owned_void_p_is_equal(register const void *cptr,
|
||||
register const void *dptr)
|
||||
{
|
||||
return (cptr == dptr);
|
||||
}
|
||||
|
||||
const void *
|
||||
o_non_owned_void_p_retain(const void *cptr)
|
||||
{
|
||||
return cptr;
|
||||
}
|
||||
|
||||
void
|
||||
o_non_owned_void_p_release(void *cptr)
|
||||
{
|
||||
/* We don't own CPTR, so we don't release it. */
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
o_non_owned_void_p_describe(const void *cptr)
|
||||
{
|
||||
/* FIXME: Code this. */
|
||||
return nil;
|
||||
}
|
||||
|
||||
size_t
|
||||
o_owned_void_p_hash(register const void *cptr)
|
||||
{
|
||||
/* We divide by 4 because many machines align
|
||||
* memory on word boundaries. */
|
||||
return ((size_t) cptr)/4;
|
||||
}
|
||||
|
||||
int
|
||||
o_owned_void_p_compare(register const void *cptr,
|
||||
register const void *dptr)
|
||||
{
|
||||
if (cptr == dptr)
|
||||
return 0;
|
||||
else if (cptr < dptr)
|
||||
return -1;
|
||||
else /* if (cptr > dptr) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
o_owned_void_p_is_equal(register const void *cptr,
|
||||
register const void *dptr)
|
||||
{
|
||||
return (cptr == dptr);
|
||||
}
|
||||
|
||||
const void *
|
||||
o_owned_void_p_retain(const void *cptr)
|
||||
{
|
||||
return cptr;
|
||||
}
|
||||
|
||||
void
|
||||
o_owned_void_p_release(void *cptr)
|
||||
{
|
||||
free((void *)cptr);
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
o_owned_void_p_describe(const void *obj)
|
||||
{
|
||||
/* FIXME: Code this. */
|
||||
return nil;
|
||||
}
|
||||
|
1131
Source/o_hash.m
1131
Source/o_hash.m
File diff suppressed because it is too large
Load diff
907
Source/o_list.m
907
Source/o_list.m
|
@ -1,907 +0,0 @@
|
|||
/* A (pretty good) list implementation.
|
||||
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Tue Sep 5 17:23:50 EDT 1995
|
||||
* Updated: Wed Mar 20 20:48:39 EST 1996
|
||||
* Serial: 96.03.20.04
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <config.h>
|
||||
#include <Foundation/NSZone.h>
|
||||
#include <base/o_cbs.h>
|
||||
#include <base/o_list.h>
|
||||
#include <base/o_hash.h>
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
/** Background functions **/
|
||||
|
||||
static inline void
|
||||
_o_list_remove_node_from_its_list (o_list_node_t * node)
|
||||
{
|
||||
if (node->list->first_node == node)
|
||||
node->list->first_node = node->next_in_list;
|
||||
if (node->list->last_node == node)
|
||||
node->list->last_node = node->prev_in_list;
|
||||
if (node->next_in_list != 0)
|
||||
node->next_in_list->prev_in_list = node->prev_in_list;
|
||||
if (node->prev_in_list != 0)
|
||||
node->prev_in_list->next_in_list = node->next_in_list;
|
||||
|
||||
node->list->node_count -= 1;
|
||||
node->list->element_count -= 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static inline o_list_node_t *
|
||||
_o_list_new_node (o_list_t *list, const void *element)
|
||||
{
|
||||
o_list_node_t *node;
|
||||
|
||||
node = NSZoneMalloc(o_list_zone(list), sizeof(o_list_node_t));
|
||||
|
||||
if (node != 0)
|
||||
{
|
||||
node->list = list;
|
||||
node->next_in_list = 0;
|
||||
node->prev_in_list = 0;
|
||||
o_retain (o_list_element_callbacks (list), element, list);
|
||||
node->element = element;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
_o_list_free_node (o_list_t *list, o_list_node_t * node)
|
||||
{
|
||||
o_release (o_list_element_callbacks (node->list),
|
||||
(void*)node->element,
|
||||
node->list);
|
||||
NSZoneFree(o_list_zone(list), node);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline o_list_node_t *
|
||||
_o_list_nth_node (o_list_t *list, long int n)
|
||||
{
|
||||
o_list_node_t *node;
|
||||
|
||||
if (n < 0)
|
||||
{
|
||||
node = list->last_node;
|
||||
++n;
|
||||
|
||||
while (node != 0 && n != 0)
|
||||
{
|
||||
node = node->prev_in_list;
|
||||
++n;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* (n >= 0) */
|
||||
{
|
||||
node = list->first_node;
|
||||
|
||||
while (node != 0 && n != 0)
|
||||
{
|
||||
node = node->next_in_list;
|
||||
--n;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static inline o_list_node_t *
|
||||
_o_list_nth_node_for_element (o_list_t *list,
|
||||
long int n,
|
||||
const void *element)
|
||||
{
|
||||
o_list_node_t *node;
|
||||
|
||||
if (n < 0)
|
||||
{
|
||||
node = list->last_node;
|
||||
|
||||
++n;
|
||||
|
||||
while (node != 0 && n != 0)
|
||||
{
|
||||
if (o_is_equal (o_list_element_callbacks (list), element, node->element, list))
|
||||
++n;
|
||||
if (n != 0)
|
||||
node = node->prev_in_list;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
node = list->first_node;
|
||||
|
||||
while (node != 0 && n != 0)
|
||||
{
|
||||
if (o_is_equal (o_list_element_callbacks (list), element, node->element, list))
|
||||
--n;
|
||||
if (n != 0)
|
||||
node = node->next_in_list;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static inline o_list_node_t *
|
||||
_o_list_enumerator_next_node (o_list_enumerator_t *enumerator)
|
||||
{
|
||||
o_list_node_t *node;
|
||||
|
||||
/* Remember ENUMERATOR's current node. */
|
||||
node = enumerator->node;
|
||||
|
||||
/* If NODE is a real node, then we need to increment ENUMERATOR's
|
||||
* current node to the next node in ENUMERATOR's list. */
|
||||
if (node != 0)
|
||||
{
|
||||
if (enumerator->forward)
|
||||
enumerator->node = enumerator->node->next_in_list;
|
||||
else /* (!enumerator->forward) */
|
||||
enumerator->node = enumerator->node->prev_in_list;
|
||||
}
|
||||
|
||||
/* Send back NODE. */
|
||||
return node;
|
||||
}
|
||||
|
||||
/** Gathering statistics **/
|
||||
|
||||
size_t
|
||||
o_list_count (o_list_t *list)
|
||||
{
|
||||
return list->element_count;
|
||||
}
|
||||
|
||||
size_t
|
||||
o_list_capacity (o_list_t *list)
|
||||
{
|
||||
return list->element_count;
|
||||
}
|
||||
|
||||
int
|
||||
o_list_check (o_list_t *list)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
o_list_contains_element (o_list_t *list, const void *element)
|
||||
{
|
||||
o_list_enumerator_t enumerator;
|
||||
const void *member;
|
||||
|
||||
o_list_enumerator (list);
|
||||
|
||||
while (o_list_enumerator_next_element (&enumerator, &member))
|
||||
if (o_compare (o_list_element_callbacks (list), element, member, list))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
o_list_is_empty (o_list_t *list)
|
||||
{
|
||||
return o_list_count (list) == 0;
|
||||
}
|
||||
|
||||
/** Enumerating **/
|
||||
|
||||
o_list_enumerator_t
|
||||
o_list_enumerator (o_list_t *list)
|
||||
{
|
||||
return o_list_forward_enumerator (list);
|
||||
}
|
||||
|
||||
o_list_enumerator_t
|
||||
o_list_forward_enumerator (o_list_t *list)
|
||||
{
|
||||
o_list_enumerator_t enumerator;
|
||||
|
||||
/* Make sure ENUMERATOR knows its list. */
|
||||
enumerator.list = list;
|
||||
|
||||
/* Start ENUMERATOR at LIST's first node. */
|
||||
enumerator.node = list->first_node;
|
||||
|
||||
/* ENUMERATOR walks forward. */
|
||||
enumerator.forward = 1;
|
||||
|
||||
return enumerator;
|
||||
}
|
||||
|
||||
o_list_enumerator_t
|
||||
o_list_reverse_enumerator (o_list_t *list)
|
||||
{
|
||||
o_list_enumerator_t enumerator;
|
||||
|
||||
/* Make sure ENUMERATOR knows its list. */
|
||||
enumerator.list = list;
|
||||
|
||||
/* Start ENUMERATOR at LIST's first node. */
|
||||
enumerator.node = list->last_node;
|
||||
|
||||
/* ENUMERATOR walks backward. */
|
||||
enumerator.forward = 0;
|
||||
|
||||
return enumerator;
|
||||
}
|
||||
|
||||
int
|
||||
o_list_enumerator_next_element (o_list_enumerator_t *enumerator,
|
||||
const void **element)
|
||||
{
|
||||
o_list_node_t *node;
|
||||
|
||||
/* Try and get the next node in the enumeration represented by
|
||||
* ENUMERATOR. */
|
||||
node = _o_list_enumerator_next_node (enumerator);
|
||||
|
||||
if (node != 0)
|
||||
{
|
||||
/* If NODE is real, then return the element it contains. */
|
||||
if (element != 0)
|
||||
*element = node->element;
|
||||
|
||||
/* Indicate that the enumeration continues. */
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If NODE isn't real, then we return the ``bogus'' indicator. */
|
||||
if (element != 0)
|
||||
*element = o_list_not_an_element_marker (enumerator->list);
|
||||
|
||||
/* Indicate that the enumeration is over. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Searching **/
|
||||
|
||||
const void *
|
||||
o_list_element (o_list_t *list, const void *element)
|
||||
{
|
||||
o_list_node_t *node;
|
||||
|
||||
node = _o_list_nth_node_for_element (list, 0, element);
|
||||
|
||||
if (node != 0)
|
||||
return node->element;
|
||||
else
|
||||
return o_list_not_an_element_marker (list);
|
||||
}
|
||||
|
||||
const void *
|
||||
o_list_nth_element (o_list_t *list, long int n)
|
||||
{
|
||||
o_list_node_t *node;
|
||||
|
||||
node = _o_list_nth_node (list, n);
|
||||
|
||||
if (node != 0)
|
||||
return node->element;
|
||||
else
|
||||
return o_list_not_an_element_marker (list);
|
||||
}
|
||||
|
||||
const void *
|
||||
o_list_first_element (o_list_t *list)
|
||||
{
|
||||
if (list->first_node != 0)
|
||||
return list->first_node->element;
|
||||
else
|
||||
return o_list_not_an_element_marker (list);
|
||||
}
|
||||
|
||||
const void *
|
||||
o_list_last_element (o_list_t *list)
|
||||
{
|
||||
if (list->last_node != 0)
|
||||
return list->last_node->element;
|
||||
else
|
||||
return o_list_not_an_element_marker (list);
|
||||
}
|
||||
|
||||
/** Obtaining elements **/
|
||||
|
||||
const void **
|
||||
o_list_all_elements (o_list_t *list)
|
||||
{
|
||||
o_list_enumerator_t enumerator;
|
||||
const void **array;
|
||||
size_t i;
|
||||
|
||||
array = NSZoneCalloc(o_list_zone(list),
|
||||
o_list_count(list) + 1,
|
||||
sizeof(const void *));
|
||||
|
||||
for (i = 0; o_list_enumerator_next_element (&enumerator, array + i); ++i);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Adding elements **/
|
||||
|
||||
const void *
|
||||
o_list_append_element (o_list_t *list, const void *element)
|
||||
{
|
||||
return o_list_at_index_insert_element (list, -1, element);
|
||||
}
|
||||
|
||||
const void *
|
||||
o_list_append_element_if_absent (o_list_t *list, const void *element)
|
||||
{
|
||||
return o_list_at_index_insert_element_if_absent (list, -1, element);
|
||||
}
|
||||
|
||||
const void *
|
||||
o_list_prepend_element (o_list_t *list, const void *element)
|
||||
{
|
||||
return o_list_at_index_insert_element (list, 0, element);
|
||||
}
|
||||
|
||||
const void *
|
||||
o_list_prepend_element_if_absent (o_list_t *list, const void *element)
|
||||
{
|
||||
return o_list_at_index_insert_element_if_absent (list, 0, element);
|
||||
}
|
||||
|
||||
const void *
|
||||
o_list_at_index_insert_element(o_list_t *list,
|
||||
long int n,
|
||||
const void *element)
|
||||
{
|
||||
o_list_node_t *anode, *bnode, *new_node, *node;
|
||||
|
||||
node = _o_list_nth_node (list, n);
|
||||
new_node = _o_list_new_node (list, element);
|
||||
|
||||
if (new_node == 0)
|
||||
/* FIXME: Make this a *little* more graceful, for goodness' sake! */
|
||||
abort();
|
||||
|
||||
if (n < 0)
|
||||
{
|
||||
if (node == 0)
|
||||
{
|
||||
anode = 0;
|
||||
bnode = list->first_node;
|
||||
}
|
||||
else
|
||||
/* (node != 0) */
|
||||
{
|
||||
anode = node;
|
||||
bnode = node->next_in_list;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* (n >= 0) */
|
||||
{
|
||||
if (node == 0)
|
||||
{
|
||||
anode = list->last_node;
|
||||
bnode = 0;
|
||||
}
|
||||
else
|
||||
/* (node != 0) */
|
||||
{
|
||||
anode = node->prev_in_list;
|
||||
bnode = node;
|
||||
}
|
||||
}
|
||||
|
||||
new_node->prev_in_list = anode;
|
||||
new_node->next_in_list = bnode;
|
||||
|
||||
if (anode != 0)
|
||||
anode->next_in_list = new_node;
|
||||
if (bnode != 0)
|
||||
bnode->prev_in_list = new_node;
|
||||
|
||||
if (list->last_node == anode)
|
||||
list->last_node = new_node;
|
||||
if (list->first_node == bnode)
|
||||
list->first_node = new_node;
|
||||
|
||||
list->node_count += 1;
|
||||
list->element_count += 1;
|
||||
|
||||
return new_node->element;
|
||||
}
|
||||
|
||||
const void *
|
||||
o_list_at_index_insert_element_if_absent (o_list_t *list,
|
||||
long int n,
|
||||
const void *element)
|
||||
{
|
||||
if (!o_list_contains_element (list, element))
|
||||
return o_list_at_index_insert_element (list, n, element);
|
||||
else
|
||||
return o_list_element (list, element);
|
||||
}
|
||||
|
||||
/** Removing elements **/
|
||||
|
||||
void
|
||||
o_list_remove_nth_occurrance_of_element (o_list_t *list,
|
||||
long int n,
|
||||
const void *element)
|
||||
{
|
||||
o_list_node_t *node;
|
||||
|
||||
node = _o_list_nth_node_for_element (list, n, element);
|
||||
|
||||
if (node != 0)
|
||||
{
|
||||
_o_list_remove_node_from_its_list (node);
|
||||
_o_list_free_node (list, node);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
o_list_remove_element (o_list_t *list, const void *element)
|
||||
{
|
||||
o_list_remove_nth_occurrance_of_element (list, 0, element);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
o_list_remove_nth_element (o_list_t *list, long int n)
|
||||
{
|
||||
o_list_node_t *node;
|
||||
|
||||
node = _o_list_nth_node (list, n);
|
||||
|
||||
if (node != 0)
|
||||
{
|
||||
_o_list_remove_node_from_its_list (node);
|
||||
_o_list_free_node (list, node);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
o_list_remove_first_element (o_list_t *list)
|
||||
{
|
||||
o_list_remove_nth_element (list, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
o_list_remove_last_element (o_list_t *list)
|
||||
{
|
||||
o_list_remove_nth_element (list, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Emptying **/
|
||||
|
||||
void
|
||||
o_list_empty (o_list_t *list)
|
||||
{
|
||||
o_list_enumerator_t enumerator;
|
||||
o_list_node_t *node;
|
||||
|
||||
enumerator = o_list_enumerator (list);
|
||||
|
||||
while ((node = _o_list_enumerator_next_node (&enumerator)) != 0)
|
||||
{
|
||||
_o_list_remove_node_from_its_list (node);
|
||||
_o_list_free_node (list, node);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Replacing **/
|
||||
|
||||
void
|
||||
o_list_replace_nth_occurrance_of_element (o_list_t *list,
|
||||
long int n,
|
||||
const void *old_element,
|
||||
const void *new_element)
|
||||
{
|
||||
o_list_node_t *node;
|
||||
|
||||
node = _o_list_nth_node_for_element (list, n, old_element);
|
||||
|
||||
if (node != 0)
|
||||
{
|
||||
o_retain (o_list_element_callbacks (list), new_element, list);
|
||||
o_release (o_list_element_callbacks (list),
|
||||
(void*)node->element,
|
||||
list);
|
||||
node->element = new_element;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
o_list_replace_element (o_list_t *list,
|
||||
const void *old_element,
|
||||
const void *new_element)
|
||||
{
|
||||
o_list_replace_nth_occurrance_of_element (list, 0, old_element, new_element);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
o_list_replace_nth_element (o_list_t *list,
|
||||
long int n,
|
||||
const void *new_element)
|
||||
{
|
||||
o_list_node_t *node;
|
||||
|
||||
node = _o_list_nth_node (list, n);
|
||||
|
||||
if (node != 0)
|
||||
{
|
||||
o_retain (o_list_element_callbacks (list), new_element, list);
|
||||
o_release (o_list_element_callbacks (list),
|
||||
(void*)node->element,
|
||||
list);
|
||||
node->element = new_element;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
o_list_replace_first_element (o_list_t *list,
|
||||
const void *new_element)
|
||||
{
|
||||
o_list_replace_nth_element (list, 0, new_element);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
o_list_replace_last_element (o_list_t *list,
|
||||
const void *new_element)
|
||||
{
|
||||
o_list_replace_nth_element (list, -1, new_element);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Creating **/
|
||||
|
||||
o_list_t *
|
||||
o_list_alloc_with_zone (NSZone *zone)
|
||||
{
|
||||
o_list_t *list;
|
||||
|
||||
list = _o_list_alloc_with_zone(zone);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_alloc (void)
|
||||
{
|
||||
return o_list_alloc_with_zone (NSDefaultMallocZone());
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list (void)
|
||||
{
|
||||
return o_list_init (o_list_alloc ());
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_with_zone (NSZone *zone)
|
||||
{
|
||||
return o_list_init (o_list_alloc_with_zone(zone));
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_with_zone_with_callbacks (NSZone *zone,
|
||||
o_callbacks_t callbacks)
|
||||
{
|
||||
return o_list_init_with_callbacks(o_list_alloc_with_zone(zone),
|
||||
callbacks);
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_with_callbacks (o_callbacks_t callbacks)
|
||||
{
|
||||
return o_list_init_with_callbacks (o_list_alloc (), callbacks);
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_of_char_p (void)
|
||||
{
|
||||
return o_list_with_callbacks (o_callbacks_for_char_p);
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_of_int (void)
|
||||
{
|
||||
return o_list_with_callbacks (o_callbacks_for_int);
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_of_non_owned_void_p (void)
|
||||
{
|
||||
return o_list_with_callbacks (o_callbacks_for_non_owned_void_p);
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_of_owned_void_p (void)
|
||||
{
|
||||
return o_list_with_callbacks (o_callbacks_for_owned_void_p);
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_of_id (void)
|
||||
{
|
||||
return o_list_with_callbacks (o_callbacks_for_id);
|
||||
}
|
||||
|
||||
/** Initializing **/
|
||||
|
||||
o_list_t *
|
||||
o_list_init (o_list_t *list)
|
||||
{
|
||||
return o_list_init_with_callbacks (list, o_callbacks_standard());
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_init_with_callbacks (o_list_t *list, o_callbacks_t callbacks)
|
||||
{
|
||||
if (list != 0)
|
||||
{
|
||||
list->callbacks = callbacks;
|
||||
list->element_count = 0;
|
||||
list->node_count = 0;
|
||||
list->first_node = 0;
|
||||
list->last_node = 0;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_init_from_list (o_list_t *list, o_list_t *old_list)
|
||||
{
|
||||
o_list_enumerator_t enumerator;
|
||||
const void *element;
|
||||
|
||||
if (list != 0)
|
||||
{
|
||||
list->callbacks = o_list_element_callbacks (old_list);
|
||||
list->element_count = 0;
|
||||
list->node_count = 0;
|
||||
list->first_node = 0;
|
||||
list->last_node = 0;
|
||||
|
||||
if (old_list != 0)
|
||||
{
|
||||
/* Get a forward enumerator for OLD_LIST. */
|
||||
enumerator = o_list_forward_enumerator (old_list);
|
||||
|
||||
/* Walk from the beginning to the end of OLD_LIST, and add each
|
||||
* element to the end of LIST. */
|
||||
while (o_list_enumerator_next_element (&enumerator, &element))
|
||||
o_list_at_index_insert_element (list, -1, element);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/** Destroying **/
|
||||
|
||||
void
|
||||
o_list_dealloc (o_list_t *list)
|
||||
{
|
||||
/* Empty LIST out. */
|
||||
o_list_empty (list);
|
||||
|
||||
/* Get rid of LIST. */
|
||||
_o_list_dealloc (list);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Comparing **/
|
||||
|
||||
int
|
||||
o_list_is_equal_to_list(o_list_t *list, o_list_t *other_list)
|
||||
{
|
||||
/* FIXME: Code this. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Concatenating **/
|
||||
|
||||
o_list_t *
|
||||
o_list_append_list (o_list_t *base_list, o_list_t *suffix_list)
|
||||
{
|
||||
return o_list_at_index_insert_list (base_list, -1, suffix_list);
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_prepend_list (o_list_t *base_list, o_list_t *prefix_list)
|
||||
{
|
||||
return o_list_at_index_insert_list (base_list, 0, prefix_list);
|
||||
}
|
||||
|
||||
/* FIXME: I was lazy when I wrote this next one. It can easily be
|
||||
* sped up. Do it. */
|
||||
o_list_t *
|
||||
o_list_at_index_insert_list(o_list_t *base_list,
|
||||
long int n,
|
||||
o_list_t *infix_list)
|
||||
{
|
||||
o_list_enumerator_t enumerator;
|
||||
const void *element;
|
||||
|
||||
if (n < 0)
|
||||
enumerator = o_list_forward_enumerator(infix_list);
|
||||
else /* (n >= 0) */
|
||||
enumerator = o_list_reverse_enumerator(infix_list);
|
||||
|
||||
while (o_list_enumerator_next_element(&enumerator, &element))
|
||||
o_list_at_index_insert_element(base_list, n, element);
|
||||
|
||||
return base_list;
|
||||
}
|
||||
|
||||
/** Copying **/
|
||||
|
||||
o_list_t *
|
||||
o_list_copy (o_list_t *old_list)
|
||||
{
|
||||
return o_list_copy_with_zone (old_list, NSDefaultMallocZone());
|
||||
}
|
||||
|
||||
o_list_t *
|
||||
o_list_copy_with_zone (o_list_t *old_list, NSZone *zone)
|
||||
{
|
||||
o_list_t *list;
|
||||
|
||||
/* Allocate a new (low-level) copy of OLD_LIST. */
|
||||
list = _o_list_copy_with_zone(old_list, zone);
|
||||
|
||||
/* Fill it in. */
|
||||
return o_list_init_from_list (list, old_list);
|
||||
}
|
||||
|
||||
/** Mapping **/
|
||||
|
||||
o_list_t *
|
||||
o_list_map_elements(o_list_t *list,
|
||||
const void *(*fcn)(const void *, void *),
|
||||
void *user_data)
|
||||
{
|
||||
o_list_enumerator_t enumerator;
|
||||
o_list_node_t *node;
|
||||
o_callbacks_t callbacks;
|
||||
|
||||
callbacks = o_list_element_callbacks(list);
|
||||
enumerator = o_list_enumerator (list);
|
||||
|
||||
while ((node = _o_list_enumerator_next_node (&enumerator)) != 0)
|
||||
{
|
||||
const void *element;
|
||||
|
||||
element = (*fcn)(node->element, user_data);
|
||||
|
||||
o_retain (callbacks, element, list);
|
||||
o_release (callbacks, (void *)(node->element), list);
|
||||
|
||||
node->element = element;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/** Creating other collections from lists **/
|
||||
|
||||
o_hash_t *
|
||||
o_hash_init_from_list (o_hash_t * hash, o_list_t *list)
|
||||
{
|
||||
if (hash != 0)
|
||||
{
|
||||
o_list_enumerator_t enumerator;
|
||||
const void *element;
|
||||
|
||||
/* Make a note of the callbacks for HASH. */
|
||||
hash->callbacks = o_list_element_callbacks (list);
|
||||
|
||||
/* Zero out the various counts. */
|
||||
hash->node_count = 0;
|
||||
hash->bucket_count = 0;
|
||||
hash->element_count = 0;
|
||||
|
||||
/* Zero out the pointers. */
|
||||
hash->first_node = 0;
|
||||
hash->buckets = 0;
|
||||
|
||||
/* Resize HASH to the given CAPACITY. */
|
||||
o_hash_resize (hash, o_list_capacity (list));
|
||||
|
||||
/* Get an element enumerator for LIST. */
|
||||
enumerator = o_list_enumerator (list);
|
||||
|
||||
/* Add LIST's elements to HASH, one at a time. Note that if LIST
|
||||
* contains multiple elements from the same equivalence class, it
|
||||
* is indeterminate which will end up in HASH. But this shouldn't
|
||||
* be a problem. */
|
||||
while (o_list_enumerator_next_element (&enumerator, &element))
|
||||
o_hash_add_element (hash, element);
|
||||
}
|
||||
|
||||
/* Return the newly initialized HASH. */
|
||||
return hash;
|
||||
}
|
||||
|
||||
// o_chash_t *
|
||||
// o_chash_init_from_list (o_chash_t * chash, o_list_t *list)
|
||||
// {
|
||||
// if (chash != 0)
|
||||
// {
|
||||
// o_list_enumerator_t enumerator;
|
||||
// const void *element;
|
||||
//
|
||||
// /* Make a note of the callbacks for CHASH. */
|
||||
// chash->callbacks = o_list_element_callbacks (list);
|
||||
//
|
||||
// /* Zero out the various counts. */
|
||||
// chash->node_count = 0;
|
||||
// chash->bucket_count = 0;
|
||||
// chash->element_count = 0;
|
||||
//
|
||||
// /* Zero out the pointers. */
|
||||
// chash->first_node = 0;
|
||||
// chash->buckets = 0;
|
||||
//
|
||||
// /* Resize CHASH to the given CAPACITY. */
|
||||
// o_chash_resize (chash, o_list_capacity (list));
|
||||
//
|
||||
// /* Get an element enumerator for LIST. */
|
||||
// enumerator = o_list_enumerator (list);
|
||||
//
|
||||
// /* Add LIST's elements to CHASH, one at a time. Note that if LIST
|
||||
// * contains multiple elements from the same equivalence class, it
|
||||
// * is indeterminate which will end up in CHASH. But this shouldn't
|
||||
// * be a problem. */
|
||||
// while (o_list_enumerator_next_element (&enumerator, &element))
|
||||
// o_chash_add_element (chash, element);
|
||||
// }
|
||||
//
|
||||
// /* Return the newly initialized CHASH. */
|
||||
// return chash;
|
||||
// }
|
||||
|
1414
Source/o_map.m
1414
Source/o_map.m
File diff suppressed because it is too large
Load diff
|
@ -1,263 +0,0 @@
|
|||
/* Basic functions for @XX@ structures.
|
||||
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Tue Dec 12 12:33:01 EST 1995
|
||||
* Updated: Mon Mar 11 00:56:35 EST 1996
|
||||
* Serial: 96.03.11.02
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <config.h>
|
||||
#include <Foundation/NSZone.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <base/numbers.h>
|
||||
#include <base/o_@XX@.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
#define __@XX@__ 1
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
/** Magic numbers... **/
|
||||
|
||||
/* Returns XX's magic number. */
|
||||
inline int
|
||||
o_@XX@_magic_number(o_@XX@_t *xx)
|
||||
{
|
||||
return xx->magic_number;
|
||||
}
|
||||
|
||||
/** Zones... **/
|
||||
|
||||
/* Returns the zone used to create and maintain XX. */
|
||||
inline NSZone *
|
||||
o_@XX@_zone(o_@XX@_t *xx)
|
||||
{
|
||||
return NSZoneFromPointer(xx);
|
||||
}
|
||||
|
||||
/** Names... **/
|
||||
|
||||
/* Returns the name that was given to XX. */
|
||||
inline NSString *
|
||||
o_@XX@_name(o_@XX@_t *xx)
|
||||
{
|
||||
return xx->name;
|
||||
}
|
||||
|
||||
/* Gives XX a name. */
|
||||
inline void
|
||||
o_@XX@_set_name(o_@XX@_t *xx, NSString *name)
|
||||
{
|
||||
[name retain];
|
||||
[xx->name release];
|
||||
xx->name = name;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Takes away XX's name. */
|
||||
inline void
|
||||
o_@XX@_unset_name(o_@XX@_t *xx)
|
||||
{
|
||||
[xx->name release];
|
||||
xx->name = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Number **/
|
||||
|
||||
/* Returns the (process-wide) unique serial number given to the
|
||||
* structure XX. See <gnustep/base/numbers.h> for more info. */
|
||||
inline size_t
|
||||
o_@XX@_serial_number(o_@XX@_t *xx)
|
||||
{
|
||||
return xx->serial_number;
|
||||
}
|
||||
|
||||
/* Gives XX a new (process-wide) unique number. Numbers are not
|
||||
* reused. See <gnustep/base/numbers.h> for more info. */
|
||||
inline size_t
|
||||
_o_@XX@_set_serial_number(o_@XX@_t *xx)
|
||||
{
|
||||
size_t old_number;
|
||||
|
||||
old_number = xx->serial_number;
|
||||
xx->serial_number = (___o_number_serialized)++;
|
||||
|
||||
return old_number;
|
||||
}
|
||||
|
||||
/** Extras **/
|
||||
|
||||
/* Sets the callbacks associated with XX's ``extra''. NOTE: This must
|
||||
* be done before calling `o_@XX@_set_extra()', as these callbacks
|
||||
* are used in that routine. */
|
||||
inline o_callbacks_t
|
||||
o_@XX@_set_extra_callbacks(o_@XX@_t *xx,
|
||||
o_callbacks_t callbacks)
|
||||
{
|
||||
o_callbacks_t old_callbacks;
|
||||
|
||||
/* Remember the old callbacks for later. */
|
||||
old_callbacks = xx->extra_callbacks;
|
||||
|
||||
/* Set the new callbacks. */
|
||||
xx->extra_callbacks = callbacks;
|
||||
|
||||
/* Release the old contents. */
|
||||
o_release(old_callbacks, (void *)(xx->extra), xx);
|
||||
|
||||
/* Set the contents to something noticible. */
|
||||
xx->extra = (xx->extra_callbacks).not_an_item_marker;
|
||||
|
||||
return old_callbacks;
|
||||
}
|
||||
|
||||
/* Returns the callbacks associated with XX's ``extra''. */
|
||||
inline o_callbacks_t
|
||||
o_@XX@_extra_callbacks(o_@XX@_t *xx)
|
||||
{
|
||||
return xx->extra_callbacks;
|
||||
}
|
||||
|
||||
/* Returns XX's ``extra'', a little extra space that each
|
||||
* structure carries around with it. Its use is
|
||||
* implementation-dependent. */
|
||||
inline const void *
|
||||
o_@XX@_extra(o_@XX@_t *xx)
|
||||
{
|
||||
return xx->extra;
|
||||
}
|
||||
|
||||
/* Sets XX's ``extra'', a little extra space that each structure
|
||||
* carries around with it. Its use is implementation-dependent. */
|
||||
inline const void *
|
||||
o_@XX@_set_extra(o_@XX@_t *xx, const void *extra)
|
||||
{
|
||||
const void *old_extra;
|
||||
|
||||
/* Out with the old, and in with the new. */
|
||||
old_extra = xx->extra;
|
||||
xx->extra = o_retain(xx->extra_callbacks, extra, xx);
|
||||
o_release(xx->extra_callbacks, (void *)old_extra, xx);
|
||||
|
||||
return old_extra;
|
||||
}
|
||||
|
||||
/* Resets XX's ``extra''. */
|
||||
inline void
|
||||
o_@XX@_unset_extra (o_@XX@_t *xx)
|
||||
{
|
||||
/* Release XX's extra. */
|
||||
o_release(xx->extra_callbacks, (void *)(xx->extra), xx);
|
||||
|
||||
/* Reset XX's extra. */
|
||||
xx->extra = (xx->extra_callbacks).not_an_item_marker;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Low-level Creation and Destruction **/
|
||||
|
||||
/* Handles the universal, low-level allocation of structures. */
|
||||
inline o_@XX@_t *
|
||||
_o_@XX@_alloc_with_zone(NSZone *zone)
|
||||
{
|
||||
o_@XX@_t *xx;
|
||||
|
||||
/* Try to allocate some space for XX. */
|
||||
xx = (o_@XX@_t *) NSZoneMalloc(zone, sizeof(o_@XX@_t));
|
||||
|
||||
/* The `o_malloc()' was successful. */
|
||||
if (xx != 0)
|
||||
{
|
||||
_o_@XX@_set_serial_number(xx);
|
||||
xx->magic_number = _OBJECTS_MAGIC_@XX@;
|
||||
xx->name = 0;
|
||||
xx->extra_callbacks = o_callbacks_for_non_owned_void_p;
|
||||
xx->extra = 0;
|
||||
|
||||
/* Increment the counter of allocated structures. */
|
||||
++(___o_number_allocated);
|
||||
}
|
||||
|
||||
return xx;
|
||||
}
|
||||
|
||||
/* Handles the universal, low-level deallocation of @XX@ structures. */
|
||||
inline void
|
||||
_o_@XX@_dealloc(o_@XX@_t *xx)
|
||||
{
|
||||
/* Make sure XX is valid. */
|
||||
if (xx != 0)
|
||||
{
|
||||
/* Free up any space we needed to keep track of XX's name. */
|
||||
if (xx->name != 0)
|
||||
NSZoneFree(o_@XX@_zone(xx), (char *)(xx->name));
|
||||
|
||||
/* Release XX's extra. */
|
||||
o_@XX@_unset_extra(xx);
|
||||
|
||||
/* Free up XX itself. */
|
||||
NSZoneFree(o_@XX@_zone(xx), xx);
|
||||
|
||||
/* Increment the counter of deallocated structures. */
|
||||
++(___o_number_deallocated);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handles the low-level copying of structures. */
|
||||
inline o_@XX@_t *
|
||||
_o_@XX@_copy_with_zone(o_@XX@_t *xx, NSZone *zone)
|
||||
{
|
||||
o_@XX@_t *new;
|
||||
|
||||
/* Create a new structure. */
|
||||
new = _o_@XX@_alloc_with_zone(zone);
|
||||
|
||||
if (new != 0)
|
||||
{
|
||||
/* Copy over XX's name. */
|
||||
o_@XX@_set_name(new, o_@XX@_name(xx));
|
||||
|
||||
/* Copy over XX's extras. */
|
||||
o_@XX@_set_extra_callbacks(new, o_@XX@_extra_callbacks(xx));
|
||||
o_@XX@_set_extra(new, o_@XX@_extra(xx));
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
inline NSString *
|
||||
_o_@XX@_description(o_@XX@_t *xx)
|
||||
{
|
||||
return [NSString
|
||||
stringWithFormat: @"magic_number = %#x;\nserial_number = %d;\n"
|
||||
@"name = %s;\nextra = %s;\nzone = %s;\n",
|
||||
o_@XX@_magic_number(xx),
|
||||
o_@XX@_serial_number(xx),
|
||||
[o_@XX@_name(xx) cString],
|
||||
[o_describe(o_@XX@_extra_callbacks(xx), o_@XX@_extra(xx), xx)
|
||||
cString],
|
||||
[NSZoneName(o_@XX@_zone(xx)) cString]];
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
/* Getting callbacks from @YY@ structures.
|
||||
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Mon Dec 11 02:44:09 EST 1995
|
||||
* Updated: Mon Mar 11 00:55:40 EST 1996
|
||||
* Serial: 96.03.11.02
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/o_cbs.h>
|
||||
#include <base/o_@YY@.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
#define __@YY@__ 1
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
#ifdef __map__
|
||||
|
||||
/** Callbacks **/
|
||||
|
||||
/* Returns the callbacks associated with YY's keys. */
|
||||
o_callbacks_t
|
||||
o_@YY@_key_callbacks(o_@YY@_t * yy)
|
||||
{
|
||||
return yy->key_callbacks;
|
||||
}
|
||||
|
||||
/* Returns the ``bogus'' marker associated with YY's keys. */
|
||||
const void *
|
||||
o_@YY@_not_a_key_marker(o_@YY@_t *yy)
|
||||
{
|
||||
return (yy->key_callbacks).not_an_item_marker;
|
||||
}
|
||||
|
||||
/* Returns the callbacks associated with YY's values. */
|
||||
o_callbacks_t
|
||||
o_@YY@_value_callbacks(o_@YY@_t *yy)
|
||||
{
|
||||
return yy->value_callbacks;
|
||||
}
|
||||
|
||||
/* Returns the ``bogus'' marker associated with YY's values. */
|
||||
const void *
|
||||
o_@YY@_not_a_value_marker(o_@YY@_t *yy)
|
||||
{
|
||||
return (yy->value_callbacks).not_an_item_marker;
|
||||
}
|
||||
|
||||
#else /* !__map__ */
|
||||
|
||||
/** Callbacks **/
|
||||
|
||||
/* Returns the callbacks associated with YY's elements. */
|
||||
o_callbacks_t
|
||||
o_@YY@_element_callbacks(o_@YY@_t *yy)
|
||||
{
|
||||
return yy->callbacks;
|
||||
}
|
||||
|
||||
/* Returns the ``bogus'' marker associated with YY's elements. */
|
||||
const void *
|
||||
o_@YY@_not_an_element_marker(o_@YY@_t *yy)
|
||||
{
|
||||
return (yy->callbacks).not_an_item_marker;
|
||||
}
|
||||
|
||||
#endif /* __map__ */
|
||||
|
Loading…
Reference in a new issue