mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-05 06:01:17 +00:00
New file.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1241 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
57f600e121
commit
2e90c4e163
24 changed files with 11364 additions and 0 deletions
85
Headers/gnustep/base/numbers.h
Normal file
85
Headers/gnustep/base/numbers.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/* Structure counters and functions for getting at them.
|
||||||
|
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||||
|
* Created: Sun Dec 3 00:28:01 EST 1995
|
||||||
|
* Updated: Mon Mar 18 14:36:49 EST 1996
|
||||||
|
* Serial: 96.03.18.03
|
||||||
|
*
|
||||||
|
* This file is part of the GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
#ifndef __numbers_h_OBJECTS_INCLUDE
|
||||||
|
#define __numbers_h_OBJECTS_INCLUDE 1
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
/** Magic numbers... **/
|
||||||
|
|
||||||
|
/* Magic numbers for the different types of structures... */
|
||||||
|
#define OBJECTS_MAGIC_ARRAY 0x1b658008 /* Thu Mar 2 02:28:50 EST 1994 */
|
||||||
|
#define OBJECTS_MAGIC_DATA 0x1b651971 /* Fri Nov 24 21:46:14 EST 1995 */
|
||||||
|
#define OBJECTS_MAGIC_HASH 0x1b653ee5 /* ??? ??? ?? ??:??:?? ??? 1993 */
|
||||||
|
#define OBJECTS_MAGIC_HEAP 0x1b65beef /* Tue Sep 5 17:21:34 EDT 1995 */
|
||||||
|
#define OBJECTS_MAGIC_LIST 0x1b65600d /* Tue Sep 5 17:23:50 EDT 1995 */
|
||||||
|
#define OBJECTS_MAGIC_MAP 0x1b65abba /* ??? ??? ?? ??:??:?? ??? 1993 */
|
||||||
|
|
||||||
|
/* WARNING: Don't use these. They are not guaranteed to remain in future
|
||||||
|
* editions of this file. They are here only as a cheap fix for an
|
||||||
|
* annoying little problem. */
|
||||||
|
/* FIXME: Get rid of these. See `x-basics.[ch].in'
|
||||||
|
* and `x-callbacks.[ch].in'. */
|
||||||
|
#define _OBJECTS_MAGIC_array OBJECTS_MAGIC_ARRAY
|
||||||
|
#define _OBJECTS_MAGIC_data OBJECTS_MAGIC_DATA
|
||||||
|
#define _OBJECTS_MAGIC_hash OBJECTS_MAGIC_HASH
|
||||||
|
#define _OBJECTS_MAGIC_heap OBJECTS_MAGIC_HEAP
|
||||||
|
#define _OBJECTS_MAGIC_list OBJECTS_MAGIC_LIST
|
||||||
|
#define _OBJECTS_MAGIC_map OBJECTS_MAGIC_MAP
|
||||||
|
|
||||||
|
/* Internal counters for the three functions below. They are placed here
|
||||||
|
* purely for your viewing pleasure. WARNING: Do not mess with these
|
||||||
|
* unless you know what you're doing. */
|
||||||
|
extern size_t ___objects_number_allocated;
|
||||||
|
extern size_t ___objects_number_deallocated;
|
||||||
|
extern size_t ___objects_number_serialized;
|
||||||
|
|
||||||
|
/**** Function Prototypes ****************************************************/
|
||||||
|
|
||||||
|
/* Returns the number of hash tables, map tables, lists,
|
||||||
|
* and sparse arrays allocated thus far. */
|
||||||
|
size_t
|
||||||
|
_objects_number_allocated(void);
|
||||||
|
|
||||||
|
/* Returns the number of hash tables, map tables, lists,
|
||||||
|
* and sparse arrays deallocated thus far. */
|
||||||
|
size_t
|
||||||
|
_objects_number_deallocated(void);
|
||||||
|
|
||||||
|
/* Returns (but does not increment) the number of hash tables,
|
||||||
|
* map tables, lists, and sparse arrays given serial numbers thus far. */
|
||||||
|
size_t
|
||||||
|
_objects_number_serialized(void);
|
||||||
|
|
||||||
|
/* Returns the least power of two strictly greater than BOUND. */
|
||||||
|
size_t
|
||||||
|
_objects_next_power_of_two(size_t bound);
|
||||||
|
|
||||||
|
#endif /* __numbers_h_OBJECTS_INCLUDE */
|
||||||
|
|
126
Headers/gnustep/base/o_x_bas.h.in
Normal file
126
Headers/gnustep/base/o_x_bas.h.in
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
#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 <objects/numbers.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
#define __@XX@__ 1
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
/** Magic numbers... **/
|
||||||
|
|
||||||
|
/* Returns XX's magic number. */
|
||||||
|
int
|
||||||
|
objects_@XX@_magic_number(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/** Zones... **/
|
||||||
|
|
||||||
|
/* Returns the allocs used to create and maintain XX. */
|
||||||
|
NSZone *
|
||||||
|
objects_@XX@_zone(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/** Names... **/
|
||||||
|
|
||||||
|
/* Returns the name that was given to XX. */
|
||||||
|
NSString *
|
||||||
|
objects_@XX@_name(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/* Gives XX a name. */
|
||||||
|
void
|
||||||
|
objects_@XX@_set_name(objects_@XX@_t *xx, NSString *name);
|
||||||
|
|
||||||
|
/* Takes away XX's name. */
|
||||||
|
void
|
||||||
|
objects_@XX@_unset_name(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/** Serial numbers... **/
|
||||||
|
|
||||||
|
/* Returns the (process-wide) unique number given to the Libfn
|
||||||
|
* structure XX. See <objects/numbers.h> for more info. */
|
||||||
|
size_t
|
||||||
|
objects_@XX@_serial_number(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/* Gives XX a new (process-wide) unique number. Numbers are not
|
||||||
|
* reused. See <objects/numbers.h> for more info. */
|
||||||
|
size_t
|
||||||
|
_objects_@XX@_set_serial_number(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/** Extras... **/
|
||||||
|
|
||||||
|
/* Sets the callbacks associated with XX's ``extra''. NOTE: This must
|
||||||
|
* be done before calling `objects_@XX@_set_extra()', as these callbacks
|
||||||
|
* are used in that routine. */
|
||||||
|
objects_callbacks_t
|
||||||
|
objects_@XX@_set_extra_callbacks(objects_@XX@_t *xx,
|
||||||
|
objects_callbacks_t callbacks);
|
||||||
|
|
||||||
|
/* Returns the callbacks associated with XX's ``extra''. */
|
||||||
|
objects_callbacks_t
|
||||||
|
objects_@XX@_extra_callbacks(objects_@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 *
|
||||||
|
objects_@XX@_extra(objects_@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 *
|
||||||
|
objects_@XX@_set_extra(objects_@XX@_t *xx, const void *extra);
|
||||||
|
|
||||||
|
/* Resets XX's ``extra''. */
|
||||||
|
void
|
||||||
|
objects_@XX@_unset_extra(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/** Low-level Creation and Destruction **/
|
||||||
|
|
||||||
|
/* Handles the universal, low-level allocation of structures. */
|
||||||
|
objects_@XX@_t *
|
||||||
|
_objects_@XX@_alloc_with_zone(NSZone *zone);
|
||||||
|
|
||||||
|
/* Handles the universal, low-level deallocation of structures. */
|
||||||
|
void
|
||||||
|
_objects_@XX@_dealloc(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/* Handles the low-level copying of structures. */
|
||||||
|
objects_@XX@_t *
|
||||||
|
_objects_@XX@_copy_with_zone(objects_@XX@_t *xx, NSZone *zone);
|
||||||
|
|
||||||
|
/* Returns a low-level description of XX. */
|
||||||
|
NSString *
|
||||||
|
_objects_@XX@_description(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
#endif /* __@XX@_bas_h_OBJECTS_INCLUDE */
|
||||||
|
|
69
Headers/gnustep/base/o_x_cbs.h.in
Normal file
69
Headers/gnustep/base/o_x_cbs.h.in
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
#ifndef __@YY@_cbs_h_OBJECTS_INCLUDE
|
||||||
|
#define __@YY@_cbs_h_OBJECTS_INCLUDE 1
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
#include <objects/@YY@.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
#define __@YY@__ 1
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
#ifdef __map__
|
||||||
|
|
||||||
|
/** Callbacks **/
|
||||||
|
|
||||||
|
/* Returns the callbacks associated with YY's keys. */
|
||||||
|
objects_callbacks_t objects_@YY@_key_callbacks (objects_@YY@_t *yy);
|
||||||
|
|
||||||
|
/* Returns the ``bogus'' marker associated with YY's keys. */
|
||||||
|
const void *objects_@YY@_not_a_key_marker (objects_@YY@_t *yy);
|
||||||
|
|
||||||
|
/* Returns the callbacks associated with YY's values. */
|
||||||
|
objects_callbacks_t
|
||||||
|
objects_@YY@_value_callbacks (objects_@YY@_t *yy);
|
||||||
|
|
||||||
|
/* Returns the ``bogus'' marker associated with YY's values. */
|
||||||
|
const void *objects_@YY@_not_a_value_marker (objects_@YY@_t *yy);
|
||||||
|
|
||||||
|
#else /* !__map__ */
|
||||||
|
|
||||||
|
/** Callbacks **/
|
||||||
|
|
||||||
|
/* Returns the callbacks associated with YY's elements. */
|
||||||
|
objects_callbacks_t objects_@YY@_element_callbacks (objects_@YY@_t *yy);
|
||||||
|
|
||||||
|
/* Returns the ``bogus'' marker associated with YY's elements. */
|
||||||
|
const void *objects_@YY@_not_an_element_marker (objects_@YY@_t *yy);
|
||||||
|
|
||||||
|
#endif /* __map__ */
|
||||||
|
|
||||||
|
#endif /* __@YY@_cbs_h_OBJECTS_INCLUDE */
|
||||||
|
|
910
Source/array.m
Normal file
910
Source/array.m
Normal file
|
@ -0,0 +1,910 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <Foundation/NSZone.h>
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
#include <objects/array.h>
|
||||||
|
#include <objects/hash.h>
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
/** Background functions **/
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
_objects_array_fold_index(size_t index, size_t slot_count)
|
||||||
|
{
|
||||||
|
return (slot_count ? (index % slot_count) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
_objects_array_internal_index(objects_array_t *array, size_t index)
|
||||||
|
{
|
||||||
|
return _objects_array_fold_index (index, array->slot_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline objects_array_slot_t *
|
||||||
|
_objects_array_slot_for_index(objects_array_t *array, size_t index)
|
||||||
|
{
|
||||||
|
return (array->slots + _objects_array_internal_index (array, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline objects_array_bucket_t *
|
||||||
|
_objects_array_bucket_for_index (objects_array_t *array, size_t index)
|
||||||
|
{
|
||||||
|
objects_array_slot_t *slot;
|
||||||
|
objects_array_bucket_t *bucket;
|
||||||
|
|
||||||
|
/* First, we translate the index into a bucket index to find our
|
||||||
|
* candidate for the bucket. */
|
||||||
|
slot = _objects_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 objects_array_bucket_t *
|
||||||
|
_objects_array_new_bucket (objects_array_t *array, size_t index, const void *element)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket;
|
||||||
|
|
||||||
|
bucket = (objects_array_bucket_t *) NSZoneMalloc(objects_array_zone(array),
|
||||||
|
sizeof(objects_array_bucket_t));
|
||||||
|
if (bucket != 0)
|
||||||
|
{
|
||||||
|
objects_retain(objects_array_element_callbacks(array), element, array);
|
||||||
|
bucket->index = index;
|
||||||
|
bucket->element = element;
|
||||||
|
}
|
||||||
|
return bucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_objects_array_free_bucket(objects_array_t *array,
|
||||||
|
objects_array_bucket_t *bucket)
|
||||||
|
{
|
||||||
|
if (bucket != 0)
|
||||||
|
{
|
||||||
|
objects_release(objects_array_element_callbacks (array),
|
||||||
|
(void *)(bucket->element),
|
||||||
|
array);
|
||||||
|
NSZoneFree(objects_array_zone(array), bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline objects_array_slot_t *
|
||||||
|
_objects_array_new_slots(objects_array_t *array, size_t slot_count)
|
||||||
|
{
|
||||||
|
return (objects_array_slot_t *) NSZoneCalloc(objects_array_zone(array),
|
||||||
|
slot_count,
|
||||||
|
sizeof(objects_array_slot_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_objects_array_free_slots(objects_array_t *array,
|
||||||
|
objects_array_slot_t *slots)
|
||||||
|
{
|
||||||
|
if (slots != 0)
|
||||||
|
NSZoneFree(objects_array_zone(array), slots);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_objects_array_empty_slot (objects_array_t *array, objects_array_slot_t * slot)
|
||||||
|
{
|
||||||
|
if (*slot != 0)
|
||||||
|
{
|
||||||
|
/* Get rid of the bucket. */
|
||||||
|
_objects_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
|
||||||
|
_objects_array_insert_bucket(objects_array_t *array,
|
||||||
|
objects_array_bucket_t * bucket)
|
||||||
|
{
|
||||||
|
objects_array_slot_t *slot;
|
||||||
|
|
||||||
|
slot = _objects_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)
|
||||||
|
{
|
||||||
|
_objects_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. */
|
||||||
|
_objects_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;
|
||||||
|
objects_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 = _objects_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[_objects_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 = _objects_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. */
|
||||||
|
_objects_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)
|
||||||
|
_objects_array_free_slots (array, array->slots);
|
||||||
|
|
||||||
|
array->slots = new_slots;
|
||||||
|
array->slot_count = new_slot_count;
|
||||||
|
++(array->element_count);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
_objects_array_compare_slots (const objects_array_slot_t *slot1,
|
||||||
|
const objects_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
|
||||||
|
_objects_array_make_sorted_slots (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_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 = _objects_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 (objects_array_slot_t)));
|
||||||
|
|
||||||
|
/* Sort the new slots. */
|
||||||
|
qsort (new_slots, array->slot_count, sizeof (objects_array_slot_t),
|
||||||
|
(qsort_compare_func_t) _objects_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 objects_array_bucket_t *
|
||||||
|
_objects_array_enumerator_next_bucket (objects_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)
|
||||||
|
{
|
||||||
|
objects_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)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket;
|
||||||
|
|
||||||
|
--(enumerator->index);
|
||||||
|
bucket = enumerator->array->sorted_slots[enumerator->index];
|
||||||
|
return bucket;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
objects_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
|
||||||
|
objects_array_count(objects_array_t *array)
|
||||||
|
{
|
||||||
|
return array->element_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
objects_array_capacity (objects_array_t *array)
|
||||||
|
{
|
||||||
|
return array->slot_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_check(objects_array_t *array)
|
||||||
|
{
|
||||||
|
/* FIXME: Code this. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_is_empty(objects_array_t *array)
|
||||||
|
{
|
||||||
|
return objects_array_count (array) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Emptying **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_array_empty(objects_array_t *array)
|
||||||
|
{
|
||||||
|
size_t c;
|
||||||
|
|
||||||
|
/* Just empty each slot out, one by one. */
|
||||||
|
for (c = 0; c < array->slot_count; ++c)
|
||||||
|
_objects_array_empty_slot (array, array->slots + c);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creating **/
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_alloc_with_zone(NSZone *zone)
|
||||||
|
{
|
||||||
|
objects_array_t *array;
|
||||||
|
|
||||||
|
/* Get a new array. */
|
||||||
|
array = _objects_array_alloc_with_zone(zone);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_alloc(void)
|
||||||
|
{
|
||||||
|
return objects_array_alloc_with_zone(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_with_zone(NSZone *zone)
|
||||||
|
{
|
||||||
|
return objects_array_init(objects_array_alloc_with_zone(zone));
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_with_zone_with_callbacks(NSZone *zone,
|
||||||
|
objects_callbacks_t callbacks)
|
||||||
|
{
|
||||||
|
return objects_array_init_with_callbacks(objects_array_alloc_with_zone(zone),
|
||||||
|
callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_with_callbacks(objects_callbacks_t callbacks)
|
||||||
|
{
|
||||||
|
return objects_array_init_with_callbacks(objects_array_alloc(), callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_of_char_p(void)
|
||||||
|
{
|
||||||
|
return objects_array_with_callbacks(objects_callbacks_for_char_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_of_non_owned_void_p(void)
|
||||||
|
{
|
||||||
|
return objects_array_with_callbacks(objects_callbacks_for_non_owned_void_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_of_owned_void_p(void)
|
||||||
|
{
|
||||||
|
return objects_array_with_callbacks(objects_callbacks_for_owned_void_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_of_int(void)
|
||||||
|
{
|
||||||
|
return objects_array_with_callbacks(objects_callbacks_for_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_of_id(void)
|
||||||
|
{
|
||||||
|
return objects_array_with_callbacks(objects_callbacks_for_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initializing **/
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_init_with_callbacks(objects_array_t *array,
|
||||||
|
objects_callbacks_t callbacks)
|
||||||
|
{
|
||||||
|
if (array != 0)
|
||||||
|
{
|
||||||
|
/* The default capacity is 15. */
|
||||||
|
size_t capacity = 15;
|
||||||
|
|
||||||
|
/* Record the element callbacks. */
|
||||||
|
array->callbacks = objects_callbacks_standardize(callbacks);
|
||||||
|
|
||||||
|
/* Initialize ARRAY's information. */
|
||||||
|
array->element_count = 0;
|
||||||
|
array->slot_count = capacity + 1;
|
||||||
|
|
||||||
|
/* Make some new slots. */
|
||||||
|
array->slots = _objects_array_new_slots(array, capacity + 1);
|
||||||
|
|
||||||
|
/* Get the sorted slots ready for later use. */
|
||||||
|
array->sorted_slots = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_init (objects_array_t *array)
|
||||||
|
{
|
||||||
|
return objects_array_init_with_callbacks (array,
|
||||||
|
objects_callbacks_standard());
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_init_from_array (objects_array_t *array, objects_array_t *old_array)
|
||||||
|
{
|
||||||
|
objects_array_enumerator_t enumerator;
|
||||||
|
size_t index;
|
||||||
|
const void *element;
|
||||||
|
|
||||||
|
/* Initialize ARRAY in the usual way. */
|
||||||
|
objects_array_init_with_callbacks (array,
|
||||||
|
objects_array_element_callbacks (old_array));
|
||||||
|
|
||||||
|
/* Get an enumerator for OLD_ARRAY. */
|
||||||
|
enumerator = objects_array_enumerator (old_array);
|
||||||
|
|
||||||
|
/* Step through OLD_ARRAY's elements, putting them at the proper
|
||||||
|
* index in ARRAY. */
|
||||||
|
while (objects_array_enumerator_next_index_and_element (&enumerator,
|
||||||
|
&index, &element))
|
||||||
|
{
|
||||||
|
objects_array_at_index_put_element (array, index, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Destroying **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_array_dealloc(objects_array_t *array)
|
||||||
|
{
|
||||||
|
if (array != 0)
|
||||||
|
{
|
||||||
|
/* Empty out ARRAY. */
|
||||||
|
objects_array_empty (array);
|
||||||
|
|
||||||
|
/* Free up its slots. */
|
||||||
|
_objects_array_free_slots (array, array->slots);
|
||||||
|
|
||||||
|
/* FIXME: What about ARRAY's sorted slots? */
|
||||||
|
|
||||||
|
/* Free up ARRAY itself. */
|
||||||
|
_objects_array_dealloc (array);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Searching **/
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_array_element_at_index (objects_array_t *array, size_t index)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket = _objects_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 objects_array_not_an_element_marker (array);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
objects_array_index_of_element (objects_array_t *array, const void *element)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < array->slot_count; ++i)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket = array->slots[i];
|
||||||
|
|
||||||
|
if (bucket != 0)
|
||||||
|
if (objects_is_equal (objects_array_element_callbacks (array),
|
||||||
|
bucket->element,
|
||||||
|
element,
|
||||||
|
array))
|
||||||
|
return bucket->index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_contains_element (objects_array_t *array, const void *element)
|
||||||
|
{
|
||||||
|
/* Note that this search is quite inefficient. */
|
||||||
|
return objects_array_index_of_element (array, element) < (array->slot_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void **
|
||||||
|
objects_array_all_elements (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_array_enumerator_t enumerator;
|
||||||
|
const void **elements;
|
||||||
|
size_t count, i;
|
||||||
|
|
||||||
|
count = objects_array_count (array);
|
||||||
|
|
||||||
|
/* Set aside space to hold the elements. */
|
||||||
|
elements = (const void **)NSZoneCalloc(objects_array_zone(array),
|
||||||
|
count + 1,
|
||||||
|
sizeof(const void *));
|
||||||
|
|
||||||
|
enumerator = objects_array_enumerator(array);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
objects_array_enumerator_next_element (&enumerator, elements + i);
|
||||||
|
|
||||||
|
elements[i] = objects_array_not_an_element_marker(array);
|
||||||
|
|
||||||
|
/* We're done, so heave it back. */
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void **
|
||||||
|
objects_array_all_elements_ascending (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_array_enumerator_t enumerator;
|
||||||
|
const void **elements;
|
||||||
|
size_t count, i;
|
||||||
|
|
||||||
|
count = objects_array_count (array);
|
||||||
|
|
||||||
|
/* Set aside space to hold the elements. */
|
||||||
|
elements = (const void **)NSZoneCalloc(objects_array_zone(array),
|
||||||
|
count + 1,
|
||||||
|
sizeof(const void *));
|
||||||
|
|
||||||
|
enumerator = objects_array_ascending_enumerator (array);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
objects_array_enumerator_next_element (&enumerator, elements + i);
|
||||||
|
|
||||||
|
elements[i] = objects_array_not_an_element_marker (array);
|
||||||
|
|
||||||
|
/* We're done, so heave it back. */
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void **
|
||||||
|
objects_array_all_elements_descending (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_array_enumerator_t enumerator;
|
||||||
|
const void **elements;
|
||||||
|
size_t count, i;
|
||||||
|
|
||||||
|
count = objects_array_count (array);
|
||||||
|
|
||||||
|
/* Set aside space to hold the elements. */
|
||||||
|
elements = (const void **)NSZoneCalloc(objects_array_zone(array),
|
||||||
|
count + 1,
|
||||||
|
sizeof(const void *));
|
||||||
|
|
||||||
|
enumerator = objects_array_descending_enumerator (array);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
objects_array_enumerator_next_element (&enumerator, elements + i);
|
||||||
|
|
||||||
|
elements[i] = objects_array_not_an_element_marker (array);
|
||||||
|
|
||||||
|
/* We're done, so heave it back. */
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Removing **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_array_remove_element_at_index (objects_array_t *array, size_t index)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket;
|
||||||
|
|
||||||
|
/* Get the bucket that might be there. */
|
||||||
|
bucket = _objects_array_bucket_for_index (array, index);
|
||||||
|
|
||||||
|
/* If there's a bucket at the index, then we empty its slot out. */
|
||||||
|
if (bucket != 0)
|
||||||
|
_objects_array_empty_slot (array, _objects_array_slot_for_index (array, index));
|
||||||
|
|
||||||
|
/* Finally, we return. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_array_remove_element_known_present (objects_array_t *array,
|
||||||
|
const void *element)
|
||||||
|
{
|
||||||
|
objects_array_remove_element_at_index (array,
|
||||||
|
objects_array_index_of_element (array,
|
||||||
|
element));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_array_remove_element (objects_array_t *array, const void *element)
|
||||||
|
{
|
||||||
|
if (objects_array_contains_element (array, element))
|
||||||
|
objects_array_remove_element_known_present (array, element);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adding **/
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_array_at_index_put_element (objects_array_t *array,
|
||||||
|
size_t index,
|
||||||
|
const void *element)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket;
|
||||||
|
|
||||||
|
/* Clean out anything that's already there. */
|
||||||
|
objects_array_remove_element_at_index (array, index);
|
||||||
|
|
||||||
|
/* Make a bucket for our information. */
|
||||||
|
bucket = _objects_array_new_bucket (array, index, element);
|
||||||
|
|
||||||
|
/* Put our bucket in the array. */
|
||||||
|
_objects_array_insert_bucket (array, bucket);
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enumerating **/
|
||||||
|
|
||||||
|
objects_array_enumerator_t
|
||||||
|
objects_array_ascending_enumerator (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_array_enumerator_t enumerator;
|
||||||
|
|
||||||
|
enumerator.array = array;
|
||||||
|
enumerator.is_sorted = 1;
|
||||||
|
enumerator.is_ascending = 1;
|
||||||
|
enumerator.index = 0;
|
||||||
|
|
||||||
|
_objects_array_make_sorted_slots (array);
|
||||||
|
|
||||||
|
return enumerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_enumerator_t
|
||||||
|
objects_array_descending_enumerator (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_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 `_objects_array_enumerator_next_bucket()'. */
|
||||||
|
enumerator.index = array->element_count + 1;
|
||||||
|
|
||||||
|
_objects_array_make_sorted_slots (array);
|
||||||
|
|
||||||
|
return enumerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_enumerator_t
|
||||||
|
objects_array_enumerator (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_array_enumerator_t enumerator;
|
||||||
|
|
||||||
|
enumerator.array = array;
|
||||||
|
enumerator.is_sorted = 0;
|
||||||
|
enumerator.is_ascending = 0;
|
||||||
|
enumerator.index = 0;
|
||||||
|
|
||||||
|
return enumerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_enumerator_next_index_and_element (objects_array_enumerator_t * enumerator,
|
||||||
|
size_t * index,
|
||||||
|
const void **element)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket;
|
||||||
|
|
||||||
|
bucket = _objects_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 = objects_array_not_an_element_marker (enumerator->array);
|
||||||
|
if (index != 0)
|
||||||
|
*index = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_enumerator_next_element (objects_array_enumerator_t * enumerator,
|
||||||
|
const void **element)
|
||||||
|
{
|
||||||
|
return objects_array_enumerator_next_index_and_element (enumerator,
|
||||||
|
0,
|
||||||
|
element);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_enumerator_next_index (objects_array_enumerator_t * enumerator,
|
||||||
|
size_t * index)
|
||||||
|
{
|
||||||
|
return objects_array_enumerator_next_index_and_element (enumerator,
|
||||||
|
index,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Comparing **/
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_is_equal_to_array (objects_array_t *array1, objects_array_t *array2)
|
||||||
|
{
|
||||||
|
size_t a, b;
|
||||||
|
const void *m, *n;
|
||||||
|
objects_array_enumerator_t e, f;
|
||||||
|
|
||||||
|
a = objects_array_count (array1);
|
||||||
|
b = objects_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 = objects_array_ascending_enumerator (array1);
|
||||||
|
e = objects_array_ascending_enumerator (array1);
|
||||||
|
|
||||||
|
while (objects_array_enumerator_next_index_and_element (&e, &a, &m)
|
||||||
|
&& objects_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 = objects_compare (objects_array_element_callbacks (array1), m, n, array1);
|
||||||
|
if (c != 0)
|
||||||
|
return c;
|
||||||
|
|
||||||
|
d = objects_compare (objects_array_element_callbacks (array2), n, m, array2);
|
||||||
|
if (d != 0)
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Mapping **/
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_map_elements(objects_array_t *array,
|
||||||
|
const void *(*fcn) (const void *, const void *),
|
||||||
|
const void *user_data)
|
||||||
|
{
|
||||||
|
/* FIXME: Code this. */
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Miscellaneous **/
|
||||||
|
|
||||||
|
objects_hash_t *
|
||||||
|
objects_hash_init_from_array (objects_hash_t * hash, objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_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 = objects_array_enumerator (array);
|
||||||
|
|
||||||
|
/* Just walk through ARRAY's elements and add them to HASH. */
|
||||||
|
while (objects_array_enumerator_next_element (&enumerator, &element))
|
||||||
|
objects_hash_add_element (hash, element);
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// objects_chash_t *
|
||||||
|
// objects_chash_init_from_array (objects_chash_t * chash, objects_array_t *array)
|
||||||
|
// {
|
||||||
|
// objects_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 = objects_array_enumerator (array);
|
||||||
|
//
|
||||||
|
// /* Just walk through ARRAY's elements and add them to CHASH. */
|
||||||
|
// while (objects_array_enumerator_next_element (&enumerator, &element))
|
||||||
|
// objects_chash_add_element (chash, element);
|
||||||
|
//
|
||||||
|
// return chash;
|
||||||
|
// }
|
||||||
|
|
1026
Source/data.m
Normal file
1026
Source/data.m
Normal file
File diff suppressed because it is too large
Load diff
1130
Source/hash.m
Normal file
1130
Source/hash.m
Normal file
File diff suppressed because it is too large
Load diff
906
Source/list.m
Normal file
906
Source/list.m
Normal file
|
@ -0,0 +1,906 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <Foundation/NSZone.h>
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
#include <objects/list.h>
|
||||||
|
#include <objects/hash.h>
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
/** Background functions **/
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_objects_list_remove_node_from_its_list (objects_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 objects_list_node_t *
|
||||||
|
_objects_list_new_node (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = NSZoneMalloc(objects_list_zone(list), sizeof(objects_list_node_t));
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
{
|
||||||
|
node->list = list;
|
||||||
|
node->next_in_list = 0;
|
||||||
|
node->prev_in_list = 0;
|
||||||
|
objects_retain (objects_list_element_callbacks (list), element, list);
|
||||||
|
node->element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_objects_list_free_node (objects_list_t *list, objects_list_node_t * node)
|
||||||
|
{
|
||||||
|
objects_release (objects_list_element_callbacks (node->list),
|
||||||
|
(void*)node->element,
|
||||||
|
node->list);
|
||||||
|
NSZoneFree(objects_list_zone(list), node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline objects_list_node_t *
|
||||||
|
_objects_list_nth_node (objects_list_t *list, long int n)
|
||||||
|
{
|
||||||
|
objects_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 objects_list_node_t *
|
||||||
|
_objects_list_nth_node_for_element (objects_list_t *list,
|
||||||
|
long int n,
|
||||||
|
const void *element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
node = list->last_node;
|
||||||
|
|
||||||
|
++n;
|
||||||
|
|
||||||
|
while (node != 0 && n != 0)
|
||||||
|
{
|
||||||
|
if (objects_is_equal (objects_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 (objects_is_equal (objects_list_element_callbacks (list), element, node->element, list))
|
||||||
|
--n;
|
||||||
|
if (n != 0)
|
||||||
|
node = node->next_in_list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline objects_list_node_t *
|
||||||
|
_objects_list_enumerator_next_node (objects_list_enumerator_t *enumerator)
|
||||||
|
{
|
||||||
|
objects_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
|
||||||
|
objects_list_count (objects_list_t *list)
|
||||||
|
{
|
||||||
|
return list->element_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
objects_list_capacity (objects_list_t *list)
|
||||||
|
{
|
||||||
|
return list->element_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_list_check (objects_list_t *list)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_list_contains_element (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
const void *member;
|
||||||
|
|
||||||
|
objects_list_enumerator (list);
|
||||||
|
|
||||||
|
while (objects_list_enumerator_next_element (&enumerator, &member))
|
||||||
|
if (objects_compare (objects_list_element_callbacks (list), element, member, list))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_list_is_empty (objects_list_t *list)
|
||||||
|
{
|
||||||
|
return objects_list_count (list) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enumerating **/
|
||||||
|
|
||||||
|
objects_list_enumerator_t
|
||||||
|
objects_list_enumerator (objects_list_t *list)
|
||||||
|
{
|
||||||
|
return objects_list_forward_enumerator (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_enumerator_t
|
||||||
|
objects_list_forward_enumerator (objects_list_t *list)
|
||||||
|
{
|
||||||
|
objects_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_enumerator_t
|
||||||
|
objects_list_reverse_enumerator (objects_list_t *list)
|
||||||
|
{
|
||||||
|
objects_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
|
||||||
|
objects_list_enumerator_next_element (objects_list_enumerator_t *enumerator,
|
||||||
|
const void **element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
/* Try and get the next node in the enumeration represented by
|
||||||
|
* ENUMERATOR. */
|
||||||
|
node = _objects_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 = objects_list_not_an_element_marker (enumerator->list);
|
||||||
|
|
||||||
|
/* Indicate that the enumeration is over. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Searching **/
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_element (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node_for_element (list, 0, element);
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
return node->element;
|
||||||
|
else
|
||||||
|
return objects_list_not_an_element_marker (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_nth_element (objects_list_t *list, long int n)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node (list, n);
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
return node->element;
|
||||||
|
else
|
||||||
|
return objects_list_not_an_element_marker (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_first_element (objects_list_t *list)
|
||||||
|
{
|
||||||
|
if (list->first_node != 0)
|
||||||
|
return list->first_node->element;
|
||||||
|
else
|
||||||
|
return objects_list_not_an_element_marker (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_last_element (objects_list_t *list)
|
||||||
|
{
|
||||||
|
if (list->last_node != 0)
|
||||||
|
return list->last_node->element;
|
||||||
|
else
|
||||||
|
return objects_list_not_an_element_marker (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Obtaining elements **/
|
||||||
|
|
||||||
|
const void **
|
||||||
|
objects_list_all_elements (objects_list_t *list)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
const void **array;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
array = NSZoneCalloc(objects_list_zone(list),
|
||||||
|
objects_list_count(list) + 1,
|
||||||
|
sizeof(const void *));
|
||||||
|
|
||||||
|
for (i = 0; objects_list_enumerator_next_element (&enumerator, array + i); ++i);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adding elements **/
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_append_element (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
return objects_list_at_index_insert_element (list, -1, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_append_element_if_absent (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
return objects_list_at_index_insert_element_if_absent (list, -1, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_prepend_element (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
return objects_list_at_index_insert_element (list, 0, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_prepend_element_if_absent (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
return objects_list_at_index_insert_element_if_absent (list, 0, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_at_index_insert_element(objects_list_t *list,
|
||||||
|
long int n,
|
||||||
|
const void *element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *anode, *bnode, *new_node, *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node (list, n);
|
||||||
|
new_node = _objects_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 *
|
||||||
|
objects_list_at_index_insert_element_if_absent (objects_list_t *list,
|
||||||
|
long int n,
|
||||||
|
const void *element)
|
||||||
|
{
|
||||||
|
if (!objects_list_contains_element (list, element))
|
||||||
|
return objects_list_at_index_insert_element (list, n, element);
|
||||||
|
else
|
||||||
|
return objects_list_element (list, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Removing elements **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_remove_nth_occurrance_of_element (objects_list_t *list,
|
||||||
|
long int n,
|
||||||
|
const void *element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node_for_element (list, n, element);
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
{
|
||||||
|
_objects_list_remove_node_from_its_list (node);
|
||||||
|
_objects_list_free_node (list, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_remove_element (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
objects_list_remove_nth_occurrance_of_element (list, 0, element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_remove_nth_element (objects_list_t *list, long int n)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node (list, n);
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
{
|
||||||
|
_objects_list_remove_node_from_its_list (node);
|
||||||
|
_objects_list_free_node (list, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_remove_first_element (objects_list_t *list)
|
||||||
|
{
|
||||||
|
objects_list_remove_nth_element (list, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_remove_last_element (objects_list_t *list)
|
||||||
|
{
|
||||||
|
objects_list_remove_nth_element (list, -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Emptying **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_empty (objects_list_t *list)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
enumerator = objects_list_enumerator (list);
|
||||||
|
|
||||||
|
while ((node = _objects_list_enumerator_next_node (&enumerator)) != 0)
|
||||||
|
{
|
||||||
|
_objects_list_remove_node_from_its_list (node);
|
||||||
|
_objects_list_free_node (list, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Replacing **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_replace_nth_occurrance_of_element (objects_list_t *list,
|
||||||
|
long int n,
|
||||||
|
const void *old_element,
|
||||||
|
const void *new_element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node_for_element (list, n, old_element);
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
{
|
||||||
|
objects_retain (objects_list_element_callbacks (list), new_element, list);
|
||||||
|
objects_release (objects_list_element_callbacks (list),
|
||||||
|
(void*)node->element,
|
||||||
|
list);
|
||||||
|
node->element = new_element;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_replace_element (objects_list_t *list,
|
||||||
|
const void *old_element,
|
||||||
|
const void *new_element)
|
||||||
|
{
|
||||||
|
objects_list_replace_nth_occurrance_of_element (list, 0, old_element, new_element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_replace_nth_element (objects_list_t *list,
|
||||||
|
long int n,
|
||||||
|
const void *new_element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node (list, n);
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
{
|
||||||
|
objects_retain (objects_list_element_callbacks (list), new_element, list);
|
||||||
|
objects_release (objects_list_element_callbacks (list),
|
||||||
|
(void*)node->element,
|
||||||
|
list);
|
||||||
|
node->element = new_element;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_replace_first_element (objects_list_t *list,
|
||||||
|
const void *new_element)
|
||||||
|
{
|
||||||
|
objects_list_replace_nth_element (list, 0, new_element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_replace_last_element (objects_list_t *list,
|
||||||
|
const void *new_element)
|
||||||
|
{
|
||||||
|
objects_list_replace_nth_element (list, -1, new_element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creating **/
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_alloc_with_zone (NSZone *zone)
|
||||||
|
{
|
||||||
|
objects_list_t *list;
|
||||||
|
|
||||||
|
list = _objects_list_alloc_with_zone(zone);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_alloc (void)
|
||||||
|
{
|
||||||
|
return objects_list_alloc_with_zone (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list (void)
|
||||||
|
{
|
||||||
|
return objects_list_init (objects_list_alloc ());
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_with_zone (NSZone *zone)
|
||||||
|
{
|
||||||
|
return objects_list_init (objects_list_alloc_with_zone(zone));
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_with_zone_with_callbacks (NSZone *zone,
|
||||||
|
objects_callbacks_t callbacks)
|
||||||
|
{
|
||||||
|
return objects_list_init_with_callbacks(objects_list_alloc_with_zone(zone),
|
||||||
|
callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_with_callbacks (objects_callbacks_t callbacks)
|
||||||
|
{
|
||||||
|
return objects_list_init_with_callbacks (objects_list_alloc (), callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_of_char_p (void)
|
||||||
|
{
|
||||||
|
return objects_list_with_callbacks (objects_callbacks_for_char_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_of_int (void)
|
||||||
|
{
|
||||||
|
return objects_list_with_callbacks (objects_callbacks_for_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_of_non_owned_void_p (void)
|
||||||
|
{
|
||||||
|
return objects_list_with_callbacks (objects_callbacks_for_non_owned_void_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_of_owned_void_p (void)
|
||||||
|
{
|
||||||
|
return objects_list_with_callbacks (objects_callbacks_for_owned_void_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_of_id (void)
|
||||||
|
{
|
||||||
|
return objects_list_with_callbacks (objects_callbacks_for_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initializing **/
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_init (objects_list_t *list)
|
||||||
|
{
|
||||||
|
return objects_list_init_with_callbacks (list, objects_callbacks_standard());
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_init_with_callbacks (objects_list_t *list, objects_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_init_from_list (objects_list_t *list, objects_list_t *old_list)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
const void *element;
|
||||||
|
|
||||||
|
if (list != 0)
|
||||||
|
{
|
||||||
|
list->callbacks = objects_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 = objects_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 (objects_list_enumerator_next_element (&enumerator, &element))
|
||||||
|
objects_list_at_index_insert_element (list, -1, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Destroying **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_dealloc (objects_list_t *list)
|
||||||
|
{
|
||||||
|
/* Empty LIST out. */
|
||||||
|
objects_list_empty (list);
|
||||||
|
|
||||||
|
/* Get rid of LIST. */
|
||||||
|
_objects_list_dealloc (list);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Comparing **/
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_list_is_equal_to_list(objects_list_t *list, objects_list_t *other_list)
|
||||||
|
{
|
||||||
|
/* FIXME: Code this. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Concatenating **/
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_append_list (objects_list_t *base_list, objects_list_t *suffix_list)
|
||||||
|
{
|
||||||
|
return objects_list_at_index_insert_list (base_list, -1, suffix_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_prepend_list (objects_list_t *base_list, objects_list_t *prefix_list)
|
||||||
|
{
|
||||||
|
return objects_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. */
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_at_index_insert_list(objects_list_t *base_list,
|
||||||
|
long int n,
|
||||||
|
objects_list_t *infix_list)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
const void *element;
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
|
enumerator = objects_list_forward_enumerator(infix_list);
|
||||||
|
else /* (n >= 0) */
|
||||||
|
enumerator = objects_list_reverse_enumerator(infix_list);
|
||||||
|
|
||||||
|
while (objects_list_enumerator_next_element(&enumerator, &element))
|
||||||
|
objects_list_at_index_insert_element(base_list, n, element);
|
||||||
|
|
||||||
|
return base_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Copying **/
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_copy (objects_list_t *old_list)
|
||||||
|
{
|
||||||
|
return objects_list_copy_with_zone (old_list, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_copy_with_zone (objects_list_t *old_list, NSZone *zone)
|
||||||
|
{
|
||||||
|
objects_list_t *list;
|
||||||
|
|
||||||
|
/* Allocate a new (low-level) copy of OLD_LIST. */
|
||||||
|
list = _objects_list_copy_with_zone(old_list, zone);
|
||||||
|
|
||||||
|
/* Fill it in. */
|
||||||
|
return objects_list_init_from_list (list, old_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Mapping **/
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_map_elements(objects_list_t *list,
|
||||||
|
const void *(*fcn)(const void *, void *),
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
objects_list_node_t *node;
|
||||||
|
objects_callbacks_t callbacks;
|
||||||
|
|
||||||
|
callbacks = objects_list_element_callbacks(list);
|
||||||
|
enumerator = objects_list_enumerator (list);
|
||||||
|
|
||||||
|
while ((node = _objects_list_enumerator_next_node (&enumerator)) != 0)
|
||||||
|
{
|
||||||
|
const void *element;
|
||||||
|
|
||||||
|
element = (*fcn)(node->element, user_data);
|
||||||
|
|
||||||
|
objects_retain (callbacks, element, list);
|
||||||
|
objects_release (callbacks, (void *)(node->element), list);
|
||||||
|
|
||||||
|
node->element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creating other collections from lists **/
|
||||||
|
|
||||||
|
objects_hash_t *
|
||||||
|
objects_hash_init_from_list (objects_hash_t * hash, objects_list_t *list)
|
||||||
|
{
|
||||||
|
if (hash != 0)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
const void *element;
|
||||||
|
|
||||||
|
/* Make a note of the callbacks for HASH. */
|
||||||
|
hash->callbacks = objects_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. */
|
||||||
|
objects_hash_resize (hash, objects_list_capacity (list));
|
||||||
|
|
||||||
|
/* Get an element enumerator for LIST. */
|
||||||
|
enumerator = objects_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 (objects_list_enumerator_next_element (&enumerator, &element))
|
||||||
|
objects_hash_add_element (hash, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the newly initialized HASH. */
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// objects_chash_t *
|
||||||
|
// objects_chash_init_from_list (objects_chash_t * chash, objects_list_t *list)
|
||||||
|
// {
|
||||||
|
// if (chash != 0)
|
||||||
|
// {
|
||||||
|
// objects_list_enumerator_t enumerator;
|
||||||
|
// const void *element;
|
||||||
|
//
|
||||||
|
// /* Make a note of the callbacks for CHASH. */
|
||||||
|
// chash->callbacks = objects_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. */
|
||||||
|
// objects_chash_resize (chash, objects_list_capacity (list));
|
||||||
|
//
|
||||||
|
// /* Get an element enumerator for LIST. */
|
||||||
|
// enumerator = objects_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 (objects_list_enumerator_next_element (&enumerator, &element))
|
||||||
|
// objects_chash_add_element (chash, element);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* Return the newly initialized CHASH. */
|
||||||
|
// return chash;
|
||||||
|
// }
|
||||||
|
|
1379
Source/map.m
Normal file
1379
Source/map.m
Normal file
File diff suppressed because it is too large
Load diff
64
Source/numbers.c
Normal file
64
Source/numbers.c
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/* Structure counters and functions for getting at them.
|
||||||
|
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||||
|
* Created: Sun Dec 3 00:23:13 EST 1995
|
||||||
|
* Updated: Mon Mar 11 02:40:00 EST 1996
|
||||||
|
* Serial: 96.03.11.03
|
||||||
|
*
|
||||||
|
* This file is part of the GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <objects/numbers.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
size_t ___objects_number_allocated = 0;
|
||||||
|
size_t ___objects_number_deallocated = 0;
|
||||||
|
size_t ___objects_number_serialized = 0;
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
/* Returns the number of Libobjects structures allocated. */
|
||||||
|
size_t
|
||||||
|
_objects_number_allocated(void)
|
||||||
|
{
|
||||||
|
return ___objects_number_allocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the number of Libobjects structures deallocated. */
|
||||||
|
size_t
|
||||||
|
_objects_number_deallocated(void)
|
||||||
|
{
|
||||||
|
return ___objects_number_deallocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the next serial number to be handed out. */
|
||||||
|
size_t
|
||||||
|
_objects_number_serialized(void)
|
||||||
|
{
|
||||||
|
return ___objects_number_serialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
_objects_next_power_of_two(size_t bound)
|
||||||
|
{
|
||||||
|
size_t start = 1;
|
||||||
|
while ((start <= bound) && (start <<= 1));
|
||||||
|
return start;
|
||||||
|
}
|
910
Source/o_array.m
Normal file
910
Source/o_array.m
Normal file
|
@ -0,0 +1,910 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <Foundation/NSZone.h>
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
#include <objects/array.h>
|
||||||
|
#include <objects/hash.h>
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
/** Background functions **/
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
_objects_array_fold_index(size_t index, size_t slot_count)
|
||||||
|
{
|
||||||
|
return (slot_count ? (index % slot_count) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
_objects_array_internal_index(objects_array_t *array, size_t index)
|
||||||
|
{
|
||||||
|
return _objects_array_fold_index (index, array->slot_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline objects_array_slot_t *
|
||||||
|
_objects_array_slot_for_index(objects_array_t *array, size_t index)
|
||||||
|
{
|
||||||
|
return (array->slots + _objects_array_internal_index (array, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline objects_array_bucket_t *
|
||||||
|
_objects_array_bucket_for_index (objects_array_t *array, size_t index)
|
||||||
|
{
|
||||||
|
objects_array_slot_t *slot;
|
||||||
|
objects_array_bucket_t *bucket;
|
||||||
|
|
||||||
|
/* First, we translate the index into a bucket index to find our
|
||||||
|
* candidate for the bucket. */
|
||||||
|
slot = _objects_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 objects_array_bucket_t *
|
||||||
|
_objects_array_new_bucket (objects_array_t *array, size_t index, const void *element)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket;
|
||||||
|
|
||||||
|
bucket = (objects_array_bucket_t *) NSZoneMalloc(objects_array_zone(array),
|
||||||
|
sizeof(objects_array_bucket_t));
|
||||||
|
if (bucket != 0)
|
||||||
|
{
|
||||||
|
objects_retain(objects_array_element_callbacks(array), element, array);
|
||||||
|
bucket->index = index;
|
||||||
|
bucket->element = element;
|
||||||
|
}
|
||||||
|
return bucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_objects_array_free_bucket(objects_array_t *array,
|
||||||
|
objects_array_bucket_t *bucket)
|
||||||
|
{
|
||||||
|
if (bucket != 0)
|
||||||
|
{
|
||||||
|
objects_release(objects_array_element_callbacks (array),
|
||||||
|
(void *)(bucket->element),
|
||||||
|
array);
|
||||||
|
NSZoneFree(objects_array_zone(array), bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline objects_array_slot_t *
|
||||||
|
_objects_array_new_slots(objects_array_t *array, size_t slot_count)
|
||||||
|
{
|
||||||
|
return (objects_array_slot_t *) NSZoneCalloc(objects_array_zone(array),
|
||||||
|
slot_count,
|
||||||
|
sizeof(objects_array_slot_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_objects_array_free_slots(objects_array_t *array,
|
||||||
|
objects_array_slot_t *slots)
|
||||||
|
{
|
||||||
|
if (slots != 0)
|
||||||
|
NSZoneFree(objects_array_zone(array), slots);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_objects_array_empty_slot (objects_array_t *array, objects_array_slot_t * slot)
|
||||||
|
{
|
||||||
|
if (*slot != 0)
|
||||||
|
{
|
||||||
|
/* Get rid of the bucket. */
|
||||||
|
_objects_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
|
||||||
|
_objects_array_insert_bucket(objects_array_t *array,
|
||||||
|
objects_array_bucket_t * bucket)
|
||||||
|
{
|
||||||
|
objects_array_slot_t *slot;
|
||||||
|
|
||||||
|
slot = _objects_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)
|
||||||
|
{
|
||||||
|
_objects_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. */
|
||||||
|
_objects_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;
|
||||||
|
objects_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 = _objects_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[_objects_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 = _objects_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. */
|
||||||
|
_objects_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)
|
||||||
|
_objects_array_free_slots (array, array->slots);
|
||||||
|
|
||||||
|
array->slots = new_slots;
|
||||||
|
array->slot_count = new_slot_count;
|
||||||
|
++(array->element_count);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
_objects_array_compare_slots (const objects_array_slot_t *slot1,
|
||||||
|
const objects_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
|
||||||
|
_objects_array_make_sorted_slots (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_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 = _objects_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 (objects_array_slot_t)));
|
||||||
|
|
||||||
|
/* Sort the new slots. */
|
||||||
|
qsort (new_slots, array->slot_count, sizeof (objects_array_slot_t),
|
||||||
|
(qsort_compare_func_t) _objects_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 objects_array_bucket_t *
|
||||||
|
_objects_array_enumerator_next_bucket (objects_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)
|
||||||
|
{
|
||||||
|
objects_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)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket;
|
||||||
|
|
||||||
|
--(enumerator->index);
|
||||||
|
bucket = enumerator->array->sorted_slots[enumerator->index];
|
||||||
|
return bucket;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
objects_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
|
||||||
|
objects_array_count(objects_array_t *array)
|
||||||
|
{
|
||||||
|
return array->element_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
objects_array_capacity (objects_array_t *array)
|
||||||
|
{
|
||||||
|
return array->slot_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_check(objects_array_t *array)
|
||||||
|
{
|
||||||
|
/* FIXME: Code this. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_is_empty(objects_array_t *array)
|
||||||
|
{
|
||||||
|
return objects_array_count (array) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Emptying **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_array_empty(objects_array_t *array)
|
||||||
|
{
|
||||||
|
size_t c;
|
||||||
|
|
||||||
|
/* Just empty each slot out, one by one. */
|
||||||
|
for (c = 0; c < array->slot_count; ++c)
|
||||||
|
_objects_array_empty_slot (array, array->slots + c);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creating **/
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_alloc_with_zone(NSZone *zone)
|
||||||
|
{
|
||||||
|
objects_array_t *array;
|
||||||
|
|
||||||
|
/* Get a new array. */
|
||||||
|
array = _objects_array_alloc_with_zone(zone);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_alloc(void)
|
||||||
|
{
|
||||||
|
return objects_array_alloc_with_zone(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_with_zone(NSZone *zone)
|
||||||
|
{
|
||||||
|
return objects_array_init(objects_array_alloc_with_zone(zone));
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_with_zone_with_callbacks(NSZone *zone,
|
||||||
|
objects_callbacks_t callbacks)
|
||||||
|
{
|
||||||
|
return objects_array_init_with_callbacks(objects_array_alloc_with_zone(zone),
|
||||||
|
callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_with_callbacks(objects_callbacks_t callbacks)
|
||||||
|
{
|
||||||
|
return objects_array_init_with_callbacks(objects_array_alloc(), callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_of_char_p(void)
|
||||||
|
{
|
||||||
|
return objects_array_with_callbacks(objects_callbacks_for_char_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_of_non_owned_void_p(void)
|
||||||
|
{
|
||||||
|
return objects_array_with_callbacks(objects_callbacks_for_non_owned_void_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_of_owned_void_p(void)
|
||||||
|
{
|
||||||
|
return objects_array_with_callbacks(objects_callbacks_for_owned_void_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_of_int(void)
|
||||||
|
{
|
||||||
|
return objects_array_with_callbacks(objects_callbacks_for_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_of_id(void)
|
||||||
|
{
|
||||||
|
return objects_array_with_callbacks(objects_callbacks_for_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initializing **/
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_init_with_callbacks(objects_array_t *array,
|
||||||
|
objects_callbacks_t callbacks)
|
||||||
|
{
|
||||||
|
if (array != 0)
|
||||||
|
{
|
||||||
|
/* The default capacity is 15. */
|
||||||
|
size_t capacity = 15;
|
||||||
|
|
||||||
|
/* Record the element callbacks. */
|
||||||
|
array->callbacks = objects_callbacks_standardize(callbacks);
|
||||||
|
|
||||||
|
/* Initialize ARRAY's information. */
|
||||||
|
array->element_count = 0;
|
||||||
|
array->slot_count = capacity + 1;
|
||||||
|
|
||||||
|
/* Make some new slots. */
|
||||||
|
array->slots = _objects_array_new_slots(array, capacity + 1);
|
||||||
|
|
||||||
|
/* Get the sorted slots ready for later use. */
|
||||||
|
array->sorted_slots = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_init (objects_array_t *array)
|
||||||
|
{
|
||||||
|
return objects_array_init_with_callbacks (array,
|
||||||
|
objects_callbacks_standard());
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_init_from_array (objects_array_t *array, objects_array_t *old_array)
|
||||||
|
{
|
||||||
|
objects_array_enumerator_t enumerator;
|
||||||
|
size_t index;
|
||||||
|
const void *element;
|
||||||
|
|
||||||
|
/* Initialize ARRAY in the usual way. */
|
||||||
|
objects_array_init_with_callbacks (array,
|
||||||
|
objects_array_element_callbacks (old_array));
|
||||||
|
|
||||||
|
/* Get an enumerator for OLD_ARRAY. */
|
||||||
|
enumerator = objects_array_enumerator (old_array);
|
||||||
|
|
||||||
|
/* Step through OLD_ARRAY's elements, putting them at the proper
|
||||||
|
* index in ARRAY. */
|
||||||
|
while (objects_array_enumerator_next_index_and_element (&enumerator,
|
||||||
|
&index, &element))
|
||||||
|
{
|
||||||
|
objects_array_at_index_put_element (array, index, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Destroying **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_array_dealloc(objects_array_t *array)
|
||||||
|
{
|
||||||
|
if (array != 0)
|
||||||
|
{
|
||||||
|
/* Empty out ARRAY. */
|
||||||
|
objects_array_empty (array);
|
||||||
|
|
||||||
|
/* Free up its slots. */
|
||||||
|
_objects_array_free_slots (array, array->slots);
|
||||||
|
|
||||||
|
/* FIXME: What about ARRAY's sorted slots? */
|
||||||
|
|
||||||
|
/* Free up ARRAY itself. */
|
||||||
|
_objects_array_dealloc (array);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Searching **/
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_array_element_at_index (objects_array_t *array, size_t index)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket = _objects_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 objects_array_not_an_element_marker (array);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
objects_array_index_of_element (objects_array_t *array, const void *element)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < array->slot_count; ++i)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket = array->slots[i];
|
||||||
|
|
||||||
|
if (bucket != 0)
|
||||||
|
if (objects_is_equal (objects_array_element_callbacks (array),
|
||||||
|
bucket->element,
|
||||||
|
element,
|
||||||
|
array))
|
||||||
|
return bucket->index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_contains_element (objects_array_t *array, const void *element)
|
||||||
|
{
|
||||||
|
/* Note that this search is quite inefficient. */
|
||||||
|
return objects_array_index_of_element (array, element) < (array->slot_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void **
|
||||||
|
objects_array_all_elements (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_array_enumerator_t enumerator;
|
||||||
|
const void **elements;
|
||||||
|
size_t count, i;
|
||||||
|
|
||||||
|
count = objects_array_count (array);
|
||||||
|
|
||||||
|
/* Set aside space to hold the elements. */
|
||||||
|
elements = (const void **)NSZoneCalloc(objects_array_zone(array),
|
||||||
|
count + 1,
|
||||||
|
sizeof(const void *));
|
||||||
|
|
||||||
|
enumerator = objects_array_enumerator(array);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
objects_array_enumerator_next_element (&enumerator, elements + i);
|
||||||
|
|
||||||
|
elements[i] = objects_array_not_an_element_marker(array);
|
||||||
|
|
||||||
|
/* We're done, so heave it back. */
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void **
|
||||||
|
objects_array_all_elements_ascending (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_array_enumerator_t enumerator;
|
||||||
|
const void **elements;
|
||||||
|
size_t count, i;
|
||||||
|
|
||||||
|
count = objects_array_count (array);
|
||||||
|
|
||||||
|
/* Set aside space to hold the elements. */
|
||||||
|
elements = (const void **)NSZoneCalloc(objects_array_zone(array),
|
||||||
|
count + 1,
|
||||||
|
sizeof(const void *));
|
||||||
|
|
||||||
|
enumerator = objects_array_ascending_enumerator (array);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
objects_array_enumerator_next_element (&enumerator, elements + i);
|
||||||
|
|
||||||
|
elements[i] = objects_array_not_an_element_marker (array);
|
||||||
|
|
||||||
|
/* We're done, so heave it back. */
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void **
|
||||||
|
objects_array_all_elements_descending (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_array_enumerator_t enumerator;
|
||||||
|
const void **elements;
|
||||||
|
size_t count, i;
|
||||||
|
|
||||||
|
count = objects_array_count (array);
|
||||||
|
|
||||||
|
/* Set aside space to hold the elements. */
|
||||||
|
elements = (const void **)NSZoneCalloc(objects_array_zone(array),
|
||||||
|
count + 1,
|
||||||
|
sizeof(const void *));
|
||||||
|
|
||||||
|
enumerator = objects_array_descending_enumerator (array);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
objects_array_enumerator_next_element (&enumerator, elements + i);
|
||||||
|
|
||||||
|
elements[i] = objects_array_not_an_element_marker (array);
|
||||||
|
|
||||||
|
/* We're done, so heave it back. */
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Removing **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_array_remove_element_at_index (objects_array_t *array, size_t index)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket;
|
||||||
|
|
||||||
|
/* Get the bucket that might be there. */
|
||||||
|
bucket = _objects_array_bucket_for_index (array, index);
|
||||||
|
|
||||||
|
/* If there's a bucket at the index, then we empty its slot out. */
|
||||||
|
if (bucket != 0)
|
||||||
|
_objects_array_empty_slot (array, _objects_array_slot_for_index (array, index));
|
||||||
|
|
||||||
|
/* Finally, we return. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_array_remove_element_known_present (objects_array_t *array,
|
||||||
|
const void *element)
|
||||||
|
{
|
||||||
|
objects_array_remove_element_at_index (array,
|
||||||
|
objects_array_index_of_element (array,
|
||||||
|
element));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_array_remove_element (objects_array_t *array, const void *element)
|
||||||
|
{
|
||||||
|
if (objects_array_contains_element (array, element))
|
||||||
|
objects_array_remove_element_known_present (array, element);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adding **/
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_array_at_index_put_element (objects_array_t *array,
|
||||||
|
size_t index,
|
||||||
|
const void *element)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket;
|
||||||
|
|
||||||
|
/* Clean out anything that's already there. */
|
||||||
|
objects_array_remove_element_at_index (array, index);
|
||||||
|
|
||||||
|
/* Make a bucket for our information. */
|
||||||
|
bucket = _objects_array_new_bucket (array, index, element);
|
||||||
|
|
||||||
|
/* Put our bucket in the array. */
|
||||||
|
_objects_array_insert_bucket (array, bucket);
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enumerating **/
|
||||||
|
|
||||||
|
objects_array_enumerator_t
|
||||||
|
objects_array_ascending_enumerator (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_array_enumerator_t enumerator;
|
||||||
|
|
||||||
|
enumerator.array = array;
|
||||||
|
enumerator.is_sorted = 1;
|
||||||
|
enumerator.is_ascending = 1;
|
||||||
|
enumerator.index = 0;
|
||||||
|
|
||||||
|
_objects_array_make_sorted_slots (array);
|
||||||
|
|
||||||
|
return enumerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_enumerator_t
|
||||||
|
objects_array_descending_enumerator (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_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 `_objects_array_enumerator_next_bucket()'. */
|
||||||
|
enumerator.index = array->element_count + 1;
|
||||||
|
|
||||||
|
_objects_array_make_sorted_slots (array);
|
||||||
|
|
||||||
|
return enumerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_array_enumerator_t
|
||||||
|
objects_array_enumerator (objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_array_enumerator_t enumerator;
|
||||||
|
|
||||||
|
enumerator.array = array;
|
||||||
|
enumerator.is_sorted = 0;
|
||||||
|
enumerator.is_ascending = 0;
|
||||||
|
enumerator.index = 0;
|
||||||
|
|
||||||
|
return enumerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_enumerator_next_index_and_element (objects_array_enumerator_t * enumerator,
|
||||||
|
size_t * index,
|
||||||
|
const void **element)
|
||||||
|
{
|
||||||
|
objects_array_bucket_t *bucket;
|
||||||
|
|
||||||
|
bucket = _objects_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 = objects_array_not_an_element_marker (enumerator->array);
|
||||||
|
if (index != 0)
|
||||||
|
*index = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_enumerator_next_element (objects_array_enumerator_t * enumerator,
|
||||||
|
const void **element)
|
||||||
|
{
|
||||||
|
return objects_array_enumerator_next_index_and_element (enumerator,
|
||||||
|
0,
|
||||||
|
element);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_enumerator_next_index (objects_array_enumerator_t * enumerator,
|
||||||
|
size_t * index)
|
||||||
|
{
|
||||||
|
return objects_array_enumerator_next_index_and_element (enumerator,
|
||||||
|
index,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Comparing **/
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_array_is_equal_to_array (objects_array_t *array1, objects_array_t *array2)
|
||||||
|
{
|
||||||
|
size_t a, b;
|
||||||
|
const void *m, *n;
|
||||||
|
objects_array_enumerator_t e, f;
|
||||||
|
|
||||||
|
a = objects_array_count (array1);
|
||||||
|
b = objects_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 = objects_array_ascending_enumerator (array1);
|
||||||
|
e = objects_array_ascending_enumerator (array1);
|
||||||
|
|
||||||
|
while (objects_array_enumerator_next_index_and_element (&e, &a, &m)
|
||||||
|
&& objects_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 = objects_compare (objects_array_element_callbacks (array1), m, n, array1);
|
||||||
|
if (c != 0)
|
||||||
|
return c;
|
||||||
|
|
||||||
|
d = objects_compare (objects_array_element_callbacks (array2), n, m, array2);
|
||||||
|
if (d != 0)
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Mapping **/
|
||||||
|
|
||||||
|
objects_array_t *
|
||||||
|
objects_array_map_elements(objects_array_t *array,
|
||||||
|
const void *(*fcn) (const void *, const void *),
|
||||||
|
const void *user_data)
|
||||||
|
{
|
||||||
|
/* FIXME: Code this. */
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Miscellaneous **/
|
||||||
|
|
||||||
|
objects_hash_t *
|
||||||
|
objects_hash_init_from_array (objects_hash_t * hash, objects_array_t *array)
|
||||||
|
{
|
||||||
|
objects_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 = objects_array_enumerator (array);
|
||||||
|
|
||||||
|
/* Just walk through ARRAY's elements and add them to HASH. */
|
||||||
|
while (objects_array_enumerator_next_element (&enumerator, &element))
|
||||||
|
objects_hash_add_element (hash, element);
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// objects_chash_t *
|
||||||
|
// objects_chash_init_from_array (objects_chash_t * chash, objects_array_t *array)
|
||||||
|
// {
|
||||||
|
// objects_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 = objects_array_enumerator (array);
|
||||||
|
//
|
||||||
|
// /* Just walk through ARRAY's elements and add them to CHASH. */
|
||||||
|
// while (objects_array_enumerator_next_element (&enumerator, &element))
|
||||||
|
// objects_chash_add_element (chash, element);
|
||||||
|
//
|
||||||
|
// return chash;
|
||||||
|
// }
|
||||||
|
|
151
Source/o_cbs.m
Normal file
151
Source/o_cbs.m
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <Foundation/NSString.h>
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
/* WARNING: Don't change this unless you know what you're getting into! */
|
||||||
|
static objects_callbacks_t ___objects_callbacks_standard =
|
||||||
|
{
|
||||||
|
(objects_hash_func_t) objects_non_owned_void_p_hash,
|
||||||
|
(objects_compare_func_t) objects_non_owned_void_p_compare,
|
||||||
|
(objects_is_equal_func_t) objects_non_owned_void_p_is_equal,
|
||||||
|
(objects_retain_func_t) objects_non_owned_void_p_retain,
|
||||||
|
(objects_release_func_t) objects_non_owned_void_p_release,
|
||||||
|
(objects_describe_func_t) objects_non_owned_void_p_describe,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
/** Getting the standard callbacks... **/
|
||||||
|
|
||||||
|
objects_callbacks_t
|
||||||
|
objects_callbacks_standard(void)
|
||||||
|
{
|
||||||
|
return ___objects_callbacks_standard;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Standardizing callbacks... **/
|
||||||
|
|
||||||
|
objects_callbacks_t
|
||||||
|
objects_callbacks_standardize(objects_callbacks_t callbacks)
|
||||||
|
{
|
||||||
|
if (callbacks.hash == 0)
|
||||||
|
callbacks.hash = objects_callbacks_standard().hash;
|
||||||
|
|
||||||
|
if (callbacks.compare == 0 && callbacks.is_equal == 0)
|
||||||
|
{
|
||||||
|
callbacks.compare = objects_callbacks_standard().compare;
|
||||||
|
callbacks.is_equal = objects_callbacks_standard().is_equal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbacks.retain == 0)
|
||||||
|
callbacks.retain = objects_callbacks_standard().retain;
|
||||||
|
|
||||||
|
if (callbacks.release == 0)
|
||||||
|
callbacks.release = objects_callbacks_standard().release;
|
||||||
|
|
||||||
|
return callbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Using callbacks... **/
|
||||||
|
|
||||||
|
size_t
|
||||||
|
objects_hash(objects_callbacks_t callbacks,
|
||||||
|
const void *thing,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
if (callbacks.hash != 0)
|
||||||
|
return callbacks.hash(thing, user_data);
|
||||||
|
else
|
||||||
|
return objects_callbacks_standard().hash(thing, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_compare(objects_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 objects_callbacks_standard().compare(thing1, thing2, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_is_equal(objects_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 objects_callbacks_standard().is_equal(thing1, thing2, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_retain(objects_callbacks_t callbacks,
|
||||||
|
const void *thing,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
if (callbacks.retain != 0)
|
||||||
|
return callbacks.retain(thing, user_data);
|
||||||
|
else
|
||||||
|
return objects_callbacks_standard().retain(thing, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_release(objects_callbacks_t callbacks,
|
||||||
|
void *thing,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
if (callbacks.release != 0)
|
||||||
|
callbacks.release (thing, user_data);
|
||||||
|
else
|
||||||
|
objects_callbacks_standard().release(thing, user_data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *
|
||||||
|
objects_describe(objects_callbacks_t callbacks,
|
||||||
|
const void *thing,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
if (callbacks.release != 0)
|
||||||
|
return callbacks.describe(thing, user_data);
|
||||||
|
else
|
||||||
|
return objects_callbacks_standard().describe(thing, user_data);
|
||||||
|
}
|
||||||
|
|
133
Source/o_cbs_char_p.m
Normal file
133
Source/o_cbs_char_p.m
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <Foundation/NSString.h>
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
/* FIXME: Is this right?!? */
|
||||||
|
#define _OBJECTS_NOT_A_CHAR_P_MARKER (const void *)(-1)
|
||||||
|
|
||||||
|
const void *objects_not_a_char_p_marker = _OBJECTS_NOT_A_CHAR_P_MARKER;
|
||||||
|
|
||||||
|
objects_callbacks_t objects_callbacks_for_char_p =
|
||||||
|
{
|
||||||
|
(objects_hash_func_t) objects_char_p_hash,
|
||||||
|
(objects_compare_func_t) objects_char_p_compare,
|
||||||
|
(objects_is_equal_func_t) objects_char_p_is_equal,
|
||||||
|
(objects_retain_func_t) objects_char_p_retain,
|
||||||
|
(objects_release_func_t) objects_char_p_release,
|
||||||
|
(objects_describe_func_t) objects_char_p_describe,
|
||||||
|
_OBJECTS_NOT_A_CHAR_P_MARKER
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
size_t
|
||||||
|
objects_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
|
||||||
|
objects_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
|
||||||
|
objects_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 *
|
||||||
|
objects_char_p_retain(const char *cptr)
|
||||||
|
{
|
||||||
|
return (const void *)cptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_char_p_release(char *cptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *
|
||||||
|
objects_char_p_describe(const char *cptr)
|
||||||
|
{
|
||||||
|
/* FIXME: Code this. */
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
95
Source/o_cbs_id.m
Normal file
95
Source/o_cbs_id.m
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <Foundation/NSObject.h>
|
||||||
|
#include <Foundation/NSString.h>
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
/* FIXME: Is this right?!? */
|
||||||
|
#define _OBJECTS_NOT_AN_ID_MARKER (const void *)(-1)
|
||||||
|
|
||||||
|
const void *objects_not_an_id_marker = _OBJECTS_NOT_AN_ID_MARKER;
|
||||||
|
|
||||||
|
objects_callbacks_t objects_callbacks_for_id =
|
||||||
|
{
|
||||||
|
(objects_hash_func_t) objects_id_hash,
|
||||||
|
(objects_compare_func_t) objects_id_compare,
|
||||||
|
(objects_is_equal_func_t) objects_id_is_equal,
|
||||||
|
(objects_retain_func_t) objects_id_retain,
|
||||||
|
(objects_release_func_t) objects_id_release,
|
||||||
|
(objects_describe_func_t) objects_id_describe,
|
||||||
|
_OBJECTS_NOT_AN_ID_MARKER
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** 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
|
||||||
|
objects_id_hash(id obj)
|
||||||
|
{
|
||||||
|
return (size_t)[obj hash];
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_id_compare(id obj, id jbo)
|
||||||
|
{
|
||||||
|
return (int)[obj compare:jbo];
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_id_is_equal(id obj, id jbo)
|
||||||
|
{
|
||||||
|
return (int)[obj isEqual:jbo];
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_id_retain(id obj)
|
||||||
|
{
|
||||||
|
return (const void *)[obj retain];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_id_release(id obj)
|
||||||
|
{
|
||||||
|
[obj release];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *
|
||||||
|
objects_id_describe(id obj)
|
||||||
|
{
|
||||||
|
return [obj description];
|
||||||
|
}
|
||||||
|
|
92
Source/o_cbs_int.m
Normal file
92
Source/o_cbs_int.m
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <Foundation/NSString.h>
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
/* FIXME: This isn't right. Fix it. */
|
||||||
|
#define _OBJECTS_NOT_AN_INT_MARKER (const void *)(-1)
|
||||||
|
|
||||||
|
const void *objects_not_an_int_marker = _OBJECTS_NOT_AN_INT_MARKER;
|
||||||
|
|
||||||
|
objects_callbacks_t objects_callbacks_for_int =
|
||||||
|
{
|
||||||
|
(objects_hash_func_t) objects_int_hash,
|
||||||
|
(objects_compare_func_t) objects_int_compare,
|
||||||
|
(objects_is_equal_func_t) objects_int_is_equal,
|
||||||
|
(objects_retain_func_t) objects_int_retain,
|
||||||
|
(objects_release_func_t) objects_int_release,
|
||||||
|
(objects_describe_func_t) objects_int_describe,
|
||||||
|
_OBJECTS_NOT_AN_INT_MARKER
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** 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
|
||||||
|
objects_int_hash(int i)
|
||||||
|
{
|
||||||
|
return (size_t)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_int_compare(int i, int j)
|
||||||
|
{
|
||||||
|
return i - j;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_int_is_equal(int i, int j)
|
||||||
|
{
|
||||||
|
return i == j;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_int_retain(int i)
|
||||||
|
{
|
||||||
|
return (const void *)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_int_release(int i)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *
|
||||||
|
objects_int_describe(int i)
|
||||||
|
{
|
||||||
|
/* FIXME: Code this. */
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
94
Source/o_cbs_int_p.m
Normal file
94
Source/o_cbs_int_p.m
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <Foundation/NSString.h>
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
/* FIXME: Is this right?!? */
|
||||||
|
#define _OBJECTS_NOT_AN_INT_P_MARKER (const void *)(-1)
|
||||||
|
|
||||||
|
const void *objects_not_an_int_p_marker = _OBJECTS_NOT_AN_INT_P_MARKER;
|
||||||
|
|
||||||
|
objects_callbacks_t objects_callbacks_for_int_p =
|
||||||
|
{
|
||||||
|
(objects_hash_func_t) objects_int_p_hash,
|
||||||
|
(objects_compare_func_t) objects_int_p_compare,
|
||||||
|
(objects_is_equal_func_t) objects_int_p_is_equal,
|
||||||
|
(objects_retain_func_t) objects_int_p_retain,
|
||||||
|
(objects_release_func_t) objects_int_p_release,
|
||||||
|
(objects_describe_func_t) objects_int_p_describe,
|
||||||
|
_OBJECTS_NOT_AN_INT_P_MARKER
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
size_t
|
||||||
|
objects_int_p_hash(const int *iptr)
|
||||||
|
{
|
||||||
|
return (size_t)(iptr) / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_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
|
||||||
|
objects_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 *
|
||||||
|
objects_int_p_retain(const int *iptr)
|
||||||
|
{
|
||||||
|
return (const void *)iptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_int_p_release(int *iptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *
|
||||||
|
objects_int_p_describe(const int *iptr)
|
||||||
|
{
|
||||||
|
/* FIXME: Code this. */
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
151
Source/o_cbs_void_p.m
Normal file
151
Source/o_cbs_void_p.m
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <Foundation/NSString.h>
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
/* FIXME: Is this right?!? */
|
||||||
|
#define _OBJECTS_NOT_A_VOID_P_MARKER (const void *)(-1)
|
||||||
|
|
||||||
|
const void *objects_not_a_void_p_marker = _OBJECTS_NOT_A_VOID_P_MARKER;
|
||||||
|
|
||||||
|
objects_callbacks_t objects_callbacks_for_non_owned_void_p =
|
||||||
|
{
|
||||||
|
(objects_hash_func_t) objects_non_owned_void_p_hash,
|
||||||
|
(objects_compare_func_t) objects_non_owned_void_p_compare,
|
||||||
|
(objects_is_equal_func_t) objects_non_owned_void_p_is_equal,
|
||||||
|
(objects_retain_func_t) objects_non_owned_void_p_retain,
|
||||||
|
(objects_release_func_t) objects_non_owned_void_p_release,
|
||||||
|
_OBJECTS_NOT_A_VOID_P_MARKER
|
||||||
|
};
|
||||||
|
|
||||||
|
objects_callbacks_t objects_callbacks_for_owned_void_p =
|
||||||
|
{
|
||||||
|
(objects_hash_func_t) objects_owned_void_p_hash,
|
||||||
|
(objects_compare_func_t) objects_owned_void_p_compare,
|
||||||
|
(objects_is_equal_func_t) objects_owned_void_p_is_equal,
|
||||||
|
(objects_retain_func_t) objects_owned_void_p_retain,
|
||||||
|
(objects_release_func_t) objects_owned_void_p_release,
|
||||||
|
_OBJECTS_NOT_A_VOID_P_MARKER
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
size_t
|
||||||
|
objects_non_owned_void_p_hash(register const void *cptr)
|
||||||
|
{
|
||||||
|
return ((size_t) cptr)/4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_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
|
||||||
|
objects_non_owned_void_p_is_equal(register const void *cptr,
|
||||||
|
register const void *dptr)
|
||||||
|
{
|
||||||
|
return (cptr == dptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_non_owned_void_p_retain(const void *cptr)
|
||||||
|
{
|
||||||
|
return cptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_non_owned_void_p_release(void *cptr)
|
||||||
|
{
|
||||||
|
/* We don't own CPTR, so we don't release it. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *
|
||||||
|
objects_non_owned_void_p_describe(const void *cptr)
|
||||||
|
{
|
||||||
|
/* FIXME: Code this. */
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
objects_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
|
||||||
|
objects_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
|
||||||
|
objects_owned_void_p_is_equal(register const void *cptr,
|
||||||
|
register const void *dptr)
|
||||||
|
{
|
||||||
|
return (cptr == dptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_owned_void_p_retain(const void *cptr)
|
||||||
|
{
|
||||||
|
return cptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_owned_void_p_release(void *cptr)
|
||||||
|
{
|
||||||
|
free((void *)cptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *
|
||||||
|
objects_owned_void_p_describe(const void *obj)
|
||||||
|
{
|
||||||
|
/* FIXME: Code this. */
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
1130
Source/o_hash.m
Normal file
1130
Source/o_hash.m
Normal file
File diff suppressed because it is too large
Load diff
906
Source/o_list.m
Normal file
906
Source/o_list.m
Normal file
|
@ -0,0 +1,906 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <Foundation/NSZone.h>
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
#include <objects/list.h>
|
||||||
|
#include <objects/hash.h>
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
/** Background functions **/
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_objects_list_remove_node_from_its_list (objects_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 objects_list_node_t *
|
||||||
|
_objects_list_new_node (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = NSZoneMalloc(objects_list_zone(list), sizeof(objects_list_node_t));
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
{
|
||||||
|
node->list = list;
|
||||||
|
node->next_in_list = 0;
|
||||||
|
node->prev_in_list = 0;
|
||||||
|
objects_retain (objects_list_element_callbacks (list), element, list);
|
||||||
|
node->element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_objects_list_free_node (objects_list_t *list, objects_list_node_t * node)
|
||||||
|
{
|
||||||
|
objects_release (objects_list_element_callbacks (node->list),
|
||||||
|
(void*)node->element,
|
||||||
|
node->list);
|
||||||
|
NSZoneFree(objects_list_zone(list), node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline objects_list_node_t *
|
||||||
|
_objects_list_nth_node (objects_list_t *list, long int n)
|
||||||
|
{
|
||||||
|
objects_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 objects_list_node_t *
|
||||||
|
_objects_list_nth_node_for_element (objects_list_t *list,
|
||||||
|
long int n,
|
||||||
|
const void *element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
node = list->last_node;
|
||||||
|
|
||||||
|
++n;
|
||||||
|
|
||||||
|
while (node != 0 && n != 0)
|
||||||
|
{
|
||||||
|
if (objects_is_equal (objects_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 (objects_is_equal (objects_list_element_callbacks (list), element, node->element, list))
|
||||||
|
--n;
|
||||||
|
if (n != 0)
|
||||||
|
node = node->next_in_list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline objects_list_node_t *
|
||||||
|
_objects_list_enumerator_next_node (objects_list_enumerator_t *enumerator)
|
||||||
|
{
|
||||||
|
objects_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
|
||||||
|
objects_list_count (objects_list_t *list)
|
||||||
|
{
|
||||||
|
return list->element_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
objects_list_capacity (objects_list_t *list)
|
||||||
|
{
|
||||||
|
return list->element_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_list_check (objects_list_t *list)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_list_contains_element (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
const void *member;
|
||||||
|
|
||||||
|
objects_list_enumerator (list);
|
||||||
|
|
||||||
|
while (objects_list_enumerator_next_element (&enumerator, &member))
|
||||||
|
if (objects_compare (objects_list_element_callbacks (list), element, member, list))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_list_is_empty (objects_list_t *list)
|
||||||
|
{
|
||||||
|
return objects_list_count (list) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enumerating **/
|
||||||
|
|
||||||
|
objects_list_enumerator_t
|
||||||
|
objects_list_enumerator (objects_list_t *list)
|
||||||
|
{
|
||||||
|
return objects_list_forward_enumerator (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_enumerator_t
|
||||||
|
objects_list_forward_enumerator (objects_list_t *list)
|
||||||
|
{
|
||||||
|
objects_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_enumerator_t
|
||||||
|
objects_list_reverse_enumerator (objects_list_t *list)
|
||||||
|
{
|
||||||
|
objects_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
|
||||||
|
objects_list_enumerator_next_element (objects_list_enumerator_t *enumerator,
|
||||||
|
const void **element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
/* Try and get the next node in the enumeration represented by
|
||||||
|
* ENUMERATOR. */
|
||||||
|
node = _objects_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 = objects_list_not_an_element_marker (enumerator->list);
|
||||||
|
|
||||||
|
/* Indicate that the enumeration is over. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Searching **/
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_element (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node_for_element (list, 0, element);
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
return node->element;
|
||||||
|
else
|
||||||
|
return objects_list_not_an_element_marker (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_nth_element (objects_list_t *list, long int n)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node (list, n);
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
return node->element;
|
||||||
|
else
|
||||||
|
return objects_list_not_an_element_marker (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_first_element (objects_list_t *list)
|
||||||
|
{
|
||||||
|
if (list->first_node != 0)
|
||||||
|
return list->first_node->element;
|
||||||
|
else
|
||||||
|
return objects_list_not_an_element_marker (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_last_element (objects_list_t *list)
|
||||||
|
{
|
||||||
|
if (list->last_node != 0)
|
||||||
|
return list->last_node->element;
|
||||||
|
else
|
||||||
|
return objects_list_not_an_element_marker (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Obtaining elements **/
|
||||||
|
|
||||||
|
const void **
|
||||||
|
objects_list_all_elements (objects_list_t *list)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
const void **array;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
array = NSZoneCalloc(objects_list_zone(list),
|
||||||
|
objects_list_count(list) + 1,
|
||||||
|
sizeof(const void *));
|
||||||
|
|
||||||
|
for (i = 0; objects_list_enumerator_next_element (&enumerator, array + i); ++i);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adding elements **/
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_append_element (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
return objects_list_at_index_insert_element (list, -1, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_append_element_if_absent (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
return objects_list_at_index_insert_element_if_absent (list, -1, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_prepend_element (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
return objects_list_at_index_insert_element (list, 0, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_prepend_element_if_absent (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
return objects_list_at_index_insert_element_if_absent (list, 0, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *
|
||||||
|
objects_list_at_index_insert_element(objects_list_t *list,
|
||||||
|
long int n,
|
||||||
|
const void *element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *anode, *bnode, *new_node, *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node (list, n);
|
||||||
|
new_node = _objects_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 *
|
||||||
|
objects_list_at_index_insert_element_if_absent (objects_list_t *list,
|
||||||
|
long int n,
|
||||||
|
const void *element)
|
||||||
|
{
|
||||||
|
if (!objects_list_contains_element (list, element))
|
||||||
|
return objects_list_at_index_insert_element (list, n, element);
|
||||||
|
else
|
||||||
|
return objects_list_element (list, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Removing elements **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_remove_nth_occurrance_of_element (objects_list_t *list,
|
||||||
|
long int n,
|
||||||
|
const void *element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node_for_element (list, n, element);
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
{
|
||||||
|
_objects_list_remove_node_from_its_list (node);
|
||||||
|
_objects_list_free_node (list, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_remove_element (objects_list_t *list, const void *element)
|
||||||
|
{
|
||||||
|
objects_list_remove_nth_occurrance_of_element (list, 0, element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_remove_nth_element (objects_list_t *list, long int n)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node (list, n);
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
{
|
||||||
|
_objects_list_remove_node_from_its_list (node);
|
||||||
|
_objects_list_free_node (list, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_remove_first_element (objects_list_t *list)
|
||||||
|
{
|
||||||
|
objects_list_remove_nth_element (list, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_remove_last_element (objects_list_t *list)
|
||||||
|
{
|
||||||
|
objects_list_remove_nth_element (list, -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Emptying **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_empty (objects_list_t *list)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
enumerator = objects_list_enumerator (list);
|
||||||
|
|
||||||
|
while ((node = _objects_list_enumerator_next_node (&enumerator)) != 0)
|
||||||
|
{
|
||||||
|
_objects_list_remove_node_from_its_list (node);
|
||||||
|
_objects_list_free_node (list, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Replacing **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_replace_nth_occurrance_of_element (objects_list_t *list,
|
||||||
|
long int n,
|
||||||
|
const void *old_element,
|
||||||
|
const void *new_element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node_for_element (list, n, old_element);
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
{
|
||||||
|
objects_retain (objects_list_element_callbacks (list), new_element, list);
|
||||||
|
objects_release (objects_list_element_callbacks (list),
|
||||||
|
(void*)node->element,
|
||||||
|
list);
|
||||||
|
node->element = new_element;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_replace_element (objects_list_t *list,
|
||||||
|
const void *old_element,
|
||||||
|
const void *new_element)
|
||||||
|
{
|
||||||
|
objects_list_replace_nth_occurrance_of_element (list, 0, old_element, new_element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_replace_nth_element (objects_list_t *list,
|
||||||
|
long int n,
|
||||||
|
const void *new_element)
|
||||||
|
{
|
||||||
|
objects_list_node_t *node;
|
||||||
|
|
||||||
|
node = _objects_list_nth_node (list, n);
|
||||||
|
|
||||||
|
if (node != 0)
|
||||||
|
{
|
||||||
|
objects_retain (objects_list_element_callbacks (list), new_element, list);
|
||||||
|
objects_release (objects_list_element_callbacks (list),
|
||||||
|
(void*)node->element,
|
||||||
|
list);
|
||||||
|
node->element = new_element;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_replace_first_element (objects_list_t *list,
|
||||||
|
const void *new_element)
|
||||||
|
{
|
||||||
|
objects_list_replace_nth_element (list, 0, new_element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_replace_last_element (objects_list_t *list,
|
||||||
|
const void *new_element)
|
||||||
|
{
|
||||||
|
objects_list_replace_nth_element (list, -1, new_element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creating **/
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_alloc_with_zone (NSZone *zone)
|
||||||
|
{
|
||||||
|
objects_list_t *list;
|
||||||
|
|
||||||
|
list = _objects_list_alloc_with_zone(zone);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_alloc (void)
|
||||||
|
{
|
||||||
|
return objects_list_alloc_with_zone (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list (void)
|
||||||
|
{
|
||||||
|
return objects_list_init (objects_list_alloc ());
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_with_zone (NSZone *zone)
|
||||||
|
{
|
||||||
|
return objects_list_init (objects_list_alloc_with_zone(zone));
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_with_zone_with_callbacks (NSZone *zone,
|
||||||
|
objects_callbacks_t callbacks)
|
||||||
|
{
|
||||||
|
return objects_list_init_with_callbacks(objects_list_alloc_with_zone(zone),
|
||||||
|
callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_with_callbacks (objects_callbacks_t callbacks)
|
||||||
|
{
|
||||||
|
return objects_list_init_with_callbacks (objects_list_alloc (), callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_of_char_p (void)
|
||||||
|
{
|
||||||
|
return objects_list_with_callbacks (objects_callbacks_for_char_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_of_int (void)
|
||||||
|
{
|
||||||
|
return objects_list_with_callbacks (objects_callbacks_for_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_of_non_owned_void_p (void)
|
||||||
|
{
|
||||||
|
return objects_list_with_callbacks (objects_callbacks_for_non_owned_void_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_of_owned_void_p (void)
|
||||||
|
{
|
||||||
|
return objects_list_with_callbacks (objects_callbacks_for_owned_void_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_of_id (void)
|
||||||
|
{
|
||||||
|
return objects_list_with_callbacks (objects_callbacks_for_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initializing **/
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_init (objects_list_t *list)
|
||||||
|
{
|
||||||
|
return objects_list_init_with_callbacks (list, objects_callbacks_standard());
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_init_with_callbacks (objects_list_t *list, objects_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_init_from_list (objects_list_t *list, objects_list_t *old_list)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
const void *element;
|
||||||
|
|
||||||
|
if (list != 0)
|
||||||
|
{
|
||||||
|
list->callbacks = objects_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 = objects_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 (objects_list_enumerator_next_element (&enumerator, &element))
|
||||||
|
objects_list_at_index_insert_element (list, -1, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Destroying **/
|
||||||
|
|
||||||
|
void
|
||||||
|
objects_list_dealloc (objects_list_t *list)
|
||||||
|
{
|
||||||
|
/* Empty LIST out. */
|
||||||
|
objects_list_empty (list);
|
||||||
|
|
||||||
|
/* Get rid of LIST. */
|
||||||
|
_objects_list_dealloc (list);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Comparing **/
|
||||||
|
|
||||||
|
int
|
||||||
|
objects_list_is_equal_to_list(objects_list_t *list, objects_list_t *other_list)
|
||||||
|
{
|
||||||
|
/* FIXME: Code this. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Concatenating **/
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_append_list (objects_list_t *base_list, objects_list_t *suffix_list)
|
||||||
|
{
|
||||||
|
return objects_list_at_index_insert_list (base_list, -1, suffix_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_prepend_list (objects_list_t *base_list, objects_list_t *prefix_list)
|
||||||
|
{
|
||||||
|
return objects_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. */
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_at_index_insert_list(objects_list_t *base_list,
|
||||||
|
long int n,
|
||||||
|
objects_list_t *infix_list)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
const void *element;
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
|
enumerator = objects_list_forward_enumerator(infix_list);
|
||||||
|
else /* (n >= 0) */
|
||||||
|
enumerator = objects_list_reverse_enumerator(infix_list);
|
||||||
|
|
||||||
|
while (objects_list_enumerator_next_element(&enumerator, &element))
|
||||||
|
objects_list_at_index_insert_element(base_list, n, element);
|
||||||
|
|
||||||
|
return base_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Copying **/
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_copy (objects_list_t *old_list)
|
||||||
|
{
|
||||||
|
return objects_list_copy_with_zone (old_list, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_copy_with_zone (objects_list_t *old_list, NSZone *zone)
|
||||||
|
{
|
||||||
|
objects_list_t *list;
|
||||||
|
|
||||||
|
/* Allocate a new (low-level) copy of OLD_LIST. */
|
||||||
|
list = _objects_list_copy_with_zone(old_list, zone);
|
||||||
|
|
||||||
|
/* Fill it in. */
|
||||||
|
return objects_list_init_from_list (list, old_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Mapping **/
|
||||||
|
|
||||||
|
objects_list_t *
|
||||||
|
objects_list_map_elements(objects_list_t *list,
|
||||||
|
const void *(*fcn)(const void *, void *),
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
objects_list_node_t *node;
|
||||||
|
objects_callbacks_t callbacks;
|
||||||
|
|
||||||
|
callbacks = objects_list_element_callbacks(list);
|
||||||
|
enumerator = objects_list_enumerator (list);
|
||||||
|
|
||||||
|
while ((node = _objects_list_enumerator_next_node (&enumerator)) != 0)
|
||||||
|
{
|
||||||
|
const void *element;
|
||||||
|
|
||||||
|
element = (*fcn)(node->element, user_data);
|
||||||
|
|
||||||
|
objects_retain (callbacks, element, list);
|
||||||
|
objects_release (callbacks, (void *)(node->element), list);
|
||||||
|
|
||||||
|
node->element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creating other collections from lists **/
|
||||||
|
|
||||||
|
objects_hash_t *
|
||||||
|
objects_hash_init_from_list (objects_hash_t * hash, objects_list_t *list)
|
||||||
|
{
|
||||||
|
if (hash != 0)
|
||||||
|
{
|
||||||
|
objects_list_enumerator_t enumerator;
|
||||||
|
const void *element;
|
||||||
|
|
||||||
|
/* Make a note of the callbacks for HASH. */
|
||||||
|
hash->callbacks = objects_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. */
|
||||||
|
objects_hash_resize (hash, objects_list_capacity (list));
|
||||||
|
|
||||||
|
/* Get an element enumerator for LIST. */
|
||||||
|
enumerator = objects_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 (objects_list_enumerator_next_element (&enumerator, &element))
|
||||||
|
objects_hash_add_element (hash, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the newly initialized HASH. */
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// objects_chash_t *
|
||||||
|
// objects_chash_init_from_list (objects_chash_t * chash, objects_list_t *list)
|
||||||
|
// {
|
||||||
|
// if (chash != 0)
|
||||||
|
// {
|
||||||
|
// objects_list_enumerator_t enumerator;
|
||||||
|
// const void *element;
|
||||||
|
//
|
||||||
|
// /* Make a note of the callbacks for CHASH. */
|
||||||
|
// chash->callbacks = objects_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. */
|
||||||
|
// objects_chash_resize (chash, objects_list_capacity (list));
|
||||||
|
//
|
||||||
|
// /* Get an element enumerator for LIST. */
|
||||||
|
// enumerator = objects_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 (objects_list_enumerator_next_element (&enumerator, &element))
|
||||||
|
// objects_chash_add_element (chash, element);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* Return the newly initialized CHASH. */
|
||||||
|
// return chash;
|
||||||
|
// }
|
||||||
|
|
1379
Source/o_map.m
Normal file
1379
Source/o_map.m
Normal file
File diff suppressed because it is too large
Load diff
261
Source/o_x_bas.m.in
Normal file
261
Source/o_x_bas.m.in
Normal file
|
@ -0,0 +1,261 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <Foundation/NSZone.h>
|
||||||
|
#include <Foundation/NSString.h>
|
||||||
|
#include <objects/numbers.h>
|
||||||
|
#include <objects/@XX@.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
#define __@XX@__ 1
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
/** Magic numbers... **/
|
||||||
|
|
||||||
|
/* Returns XX's magic number. */
|
||||||
|
inline int
|
||||||
|
objects_@XX@_magic_number(objects_@XX@_t *xx)
|
||||||
|
{
|
||||||
|
return xx->magic_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Zones... **/
|
||||||
|
|
||||||
|
/* Returns the zone used to create and maintain XX. */
|
||||||
|
inline NSZone *
|
||||||
|
objects_@XX@_zone(objects_@XX@_t *xx)
|
||||||
|
{
|
||||||
|
return xx->zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Names... **/
|
||||||
|
|
||||||
|
/* Returns the name that was given to XX. */
|
||||||
|
inline NSString *
|
||||||
|
objects_@XX@_name(objects_@XX@_t *xx)
|
||||||
|
{
|
||||||
|
return xx->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gives XX a name. */
|
||||||
|
inline void
|
||||||
|
objects_@XX@_set_name(objects_@XX@_t *xx, NSString *name)
|
||||||
|
{
|
||||||
|
[name retain];
|
||||||
|
[xx->name release];
|
||||||
|
xx->name = name;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Takes away XX's name. */
|
||||||
|
inline void
|
||||||
|
objects_@XX@_unset_name(objects_@XX@_t *xx)
|
||||||
|
{
|
||||||
|
[xx->name release];
|
||||||
|
xx->name = nil;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Number **/
|
||||||
|
|
||||||
|
/* Returns the (process-wide) unique serial number given to the
|
||||||
|
* structure XX. See <objects/numbers.h> for more info. */
|
||||||
|
inline size_t
|
||||||
|
objects_@XX@_serial_number(objects_@XX@_t *xx)
|
||||||
|
{
|
||||||
|
return xx->serial_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gives XX a new (process-wide) unique number. Numbers are not
|
||||||
|
* reused. See <objects/numbers.h> for more info. */
|
||||||
|
inline size_t
|
||||||
|
_objects_@XX@_set_serial_number(objects_@XX@_t *xx)
|
||||||
|
{
|
||||||
|
size_t old_number;
|
||||||
|
|
||||||
|
old_number = xx->serial_number;
|
||||||
|
xx->serial_number = (___objects_number_serialized)++;
|
||||||
|
|
||||||
|
return old_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Extras **/
|
||||||
|
|
||||||
|
/* Sets the callbacks associated with XX's ``extra''. NOTE: This must
|
||||||
|
* be done before calling `objects_@XX@_set_extra()', as these callbacks
|
||||||
|
* are used in that routine. */
|
||||||
|
inline objects_callbacks_t
|
||||||
|
objects_@XX@_set_extra_callbacks(objects_@XX@_t *xx,
|
||||||
|
objects_callbacks_t callbacks)
|
||||||
|
{
|
||||||
|
objects_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. */
|
||||||
|
objects_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 objects_callbacks_t
|
||||||
|
objects_@XX@_extra_callbacks(objects_@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 *
|
||||||
|
objects_@XX@_extra(objects_@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 *
|
||||||
|
objects_@XX@_set_extra(objects_@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 = objects_retain(xx->extra_callbacks, extra, xx);
|
||||||
|
objects_release(xx->extra_callbacks, (void *)old_extra, xx);
|
||||||
|
|
||||||
|
return old_extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resets XX's ``extra''. */
|
||||||
|
inline void
|
||||||
|
objects_@XX@_unset_extra (objects_@XX@_t *xx)
|
||||||
|
{
|
||||||
|
/* Release XX's extra. */
|
||||||
|
objects_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 objects_@XX@_t *
|
||||||
|
_objects_@XX@_alloc_with_zone(NSZone *zone)
|
||||||
|
{
|
||||||
|
objects_@XX@_t *xx;
|
||||||
|
|
||||||
|
/* Try to allocate some space for XX. */
|
||||||
|
xx = (objects_@XX@_t *) NSZoneMalloc(zone, sizeof(objects_@XX@_t));
|
||||||
|
|
||||||
|
/* The `objects_malloc()' was successful. */
|
||||||
|
if (xx != 0)
|
||||||
|
{
|
||||||
|
_objects_@XX@_set_serial_number(xx);
|
||||||
|
xx->magic_number = _OBJECTS_MAGIC_@XX@;
|
||||||
|
xx->name = 0;
|
||||||
|
xx->zone = zone;
|
||||||
|
xx->extra_callbacks = objects_callbacks_for_non_owned_void_p;
|
||||||
|
xx->extra = 0;
|
||||||
|
|
||||||
|
/* Increment the counter of allocated structures. */
|
||||||
|
++(___objects_number_allocated);
|
||||||
|
}
|
||||||
|
|
||||||
|
return xx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handles the universal, low-level deallocation of @XX@ structures. */
|
||||||
|
inline void
|
||||||
|
_objects_@XX@_dealloc(objects_@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(objects_@XX@_zone(xx), (char *)(xx->name));
|
||||||
|
|
||||||
|
/* Release XX's extra. */
|
||||||
|
objects_@XX@_unset_extra(xx);
|
||||||
|
|
||||||
|
/* Free up XX itself. */
|
||||||
|
NSZoneFree(objects_@XX@_zone(xx), xx);
|
||||||
|
|
||||||
|
/* Increment the counter of deallocated structures. */
|
||||||
|
++(___objects_number_deallocated);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handles the low-level copying of structures. */
|
||||||
|
inline objects_@XX@_t *
|
||||||
|
_objects_@XX@_copy_with_zone(objects_@XX@_t *xx, NSZone *zone)
|
||||||
|
{
|
||||||
|
objects_@XX@_t *new;
|
||||||
|
|
||||||
|
/* Create a new structure. */
|
||||||
|
new = _objects_@XX@_alloc_with_zone(zone);
|
||||||
|
|
||||||
|
if (new != 0)
|
||||||
|
{
|
||||||
|
/* Copy over XX's name. */
|
||||||
|
objects_@XX@_set_name(new, objects_@XX@_name(xx));
|
||||||
|
|
||||||
|
/* Copy over XX's extras. */
|
||||||
|
objects_@XX@_set_extra_callbacks(new, objects_@XX@_extra_callbacks(xx));
|
||||||
|
objects_@XX@_set_extra(new, objects_@XX@_extra(xx));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline NSString *
|
||||||
|
_objects_@XX@_description(objects_@XX@_t *xx)
|
||||||
|
{
|
||||||
|
return [NSString stringWithFormat:@"magic_number = %#x;\nserial_number = %d;\nname = %@;\nextra = %@;\nzone = %@;\n",
|
||||||
|
objects_@XX@_magic_number(xx),
|
||||||
|
objects_@XX@_serial_number(xx),
|
||||||
|
objects_@XX@_name(xx),
|
||||||
|
objects_describe(objects_@XX@_extra_callbacks(xx),
|
||||||
|
objects_@XX@_extra(xx), xx),
|
||||||
|
NSZoneName(objects_@XX@_zone(xx))];
|
||||||
|
}
|
87
Source/o_x_cbs.m.in
Normal file
87
Source/o_x_cbs.m.in
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
#include <objects/@YY@.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
#define __@YY@__ 1
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
#ifdef __map__
|
||||||
|
|
||||||
|
/** Callbacks **/
|
||||||
|
|
||||||
|
/* Returns the callbacks associated with YY's keys. */
|
||||||
|
objects_callbacks_t
|
||||||
|
objects_@YY@_key_callbacks(objects_@YY@_t * yy)
|
||||||
|
{
|
||||||
|
return yy->key_callbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the ``bogus'' marker associated with YY's keys. */
|
||||||
|
const void *
|
||||||
|
objects_@YY@_not_a_key_marker(objects_@YY@_t *yy)
|
||||||
|
{
|
||||||
|
return (yy->key_callbacks).not_an_item_marker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the callbacks associated with YY's values. */
|
||||||
|
objects_callbacks_t
|
||||||
|
objects_@YY@_value_callbacks(objects_@YY@_t *yy)
|
||||||
|
{
|
||||||
|
return yy->value_callbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the ``bogus'' marker associated with YY's values. */
|
||||||
|
const void *
|
||||||
|
objects_@YY@_not_a_value_marker(objects_@YY@_t *yy)
|
||||||
|
{
|
||||||
|
return (yy->value_callbacks).not_an_item_marker;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !__map__ */
|
||||||
|
|
||||||
|
/** Callbacks **/
|
||||||
|
|
||||||
|
/* Returns the callbacks associated with YY's elements. */
|
||||||
|
objects_callbacks_t
|
||||||
|
objects_@YY@_element_callbacks(objects_@YY@_t *yy)
|
||||||
|
{
|
||||||
|
return yy->callbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the ``bogus'' marker associated with YY's elements. */
|
||||||
|
const void *
|
||||||
|
objects_@YY@_not_an_element_marker(objects_@YY@_t *yy)
|
||||||
|
{
|
||||||
|
return (yy->callbacks).not_an_item_marker;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __map__ */
|
||||||
|
|
85
Source/objects/numbers.h
Normal file
85
Source/objects/numbers.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/* Structure counters and functions for getting at them.
|
||||||
|
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||||
|
* Created: Sun Dec 3 00:28:01 EST 1995
|
||||||
|
* Updated: Mon Mar 18 14:36:49 EST 1996
|
||||||
|
* Serial: 96.03.18.03
|
||||||
|
*
|
||||||
|
* This file is part of the GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
#ifndef __numbers_h_OBJECTS_INCLUDE
|
||||||
|
#define __numbers_h_OBJECTS_INCLUDE 1
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
/** Magic numbers... **/
|
||||||
|
|
||||||
|
/* Magic numbers for the different types of structures... */
|
||||||
|
#define OBJECTS_MAGIC_ARRAY 0x1b658008 /* Thu Mar 2 02:28:50 EST 1994 */
|
||||||
|
#define OBJECTS_MAGIC_DATA 0x1b651971 /* Fri Nov 24 21:46:14 EST 1995 */
|
||||||
|
#define OBJECTS_MAGIC_HASH 0x1b653ee5 /* ??? ??? ?? ??:??:?? ??? 1993 */
|
||||||
|
#define OBJECTS_MAGIC_HEAP 0x1b65beef /* Tue Sep 5 17:21:34 EDT 1995 */
|
||||||
|
#define OBJECTS_MAGIC_LIST 0x1b65600d /* Tue Sep 5 17:23:50 EDT 1995 */
|
||||||
|
#define OBJECTS_MAGIC_MAP 0x1b65abba /* ??? ??? ?? ??:??:?? ??? 1993 */
|
||||||
|
|
||||||
|
/* WARNING: Don't use these. They are not guaranteed to remain in future
|
||||||
|
* editions of this file. They are here only as a cheap fix for an
|
||||||
|
* annoying little problem. */
|
||||||
|
/* FIXME: Get rid of these. See `x-basics.[ch].in'
|
||||||
|
* and `x-callbacks.[ch].in'. */
|
||||||
|
#define _OBJECTS_MAGIC_array OBJECTS_MAGIC_ARRAY
|
||||||
|
#define _OBJECTS_MAGIC_data OBJECTS_MAGIC_DATA
|
||||||
|
#define _OBJECTS_MAGIC_hash OBJECTS_MAGIC_HASH
|
||||||
|
#define _OBJECTS_MAGIC_heap OBJECTS_MAGIC_HEAP
|
||||||
|
#define _OBJECTS_MAGIC_list OBJECTS_MAGIC_LIST
|
||||||
|
#define _OBJECTS_MAGIC_map OBJECTS_MAGIC_MAP
|
||||||
|
|
||||||
|
/* Internal counters for the three functions below. They are placed here
|
||||||
|
* purely for your viewing pleasure. WARNING: Do not mess with these
|
||||||
|
* unless you know what you're doing. */
|
||||||
|
extern size_t ___objects_number_allocated;
|
||||||
|
extern size_t ___objects_number_deallocated;
|
||||||
|
extern size_t ___objects_number_serialized;
|
||||||
|
|
||||||
|
/**** Function Prototypes ****************************************************/
|
||||||
|
|
||||||
|
/* Returns the number of hash tables, map tables, lists,
|
||||||
|
* and sparse arrays allocated thus far. */
|
||||||
|
size_t
|
||||||
|
_objects_number_allocated(void);
|
||||||
|
|
||||||
|
/* Returns the number of hash tables, map tables, lists,
|
||||||
|
* and sparse arrays deallocated thus far. */
|
||||||
|
size_t
|
||||||
|
_objects_number_deallocated(void);
|
||||||
|
|
||||||
|
/* Returns (but does not increment) the number of hash tables,
|
||||||
|
* map tables, lists, and sparse arrays given serial numbers thus far. */
|
||||||
|
size_t
|
||||||
|
_objects_number_serialized(void);
|
||||||
|
|
||||||
|
/* Returns the least power of two strictly greater than BOUND. */
|
||||||
|
size_t
|
||||||
|
_objects_next_power_of_two(size_t bound);
|
||||||
|
|
||||||
|
#endif /* __numbers_h_OBJECTS_INCLUDE */
|
||||||
|
|
126
Source/objects/x-bas.h.in
Normal file
126
Source/objects/x-bas.h.in
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
#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 <objects/numbers.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
#define __@XX@__ 1
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
/** Magic numbers... **/
|
||||||
|
|
||||||
|
/* Returns XX's magic number. */
|
||||||
|
int
|
||||||
|
objects_@XX@_magic_number(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/** Zones... **/
|
||||||
|
|
||||||
|
/* Returns the allocs used to create and maintain XX. */
|
||||||
|
NSZone *
|
||||||
|
objects_@XX@_zone(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/** Names... **/
|
||||||
|
|
||||||
|
/* Returns the name that was given to XX. */
|
||||||
|
NSString *
|
||||||
|
objects_@XX@_name(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/* Gives XX a name. */
|
||||||
|
void
|
||||||
|
objects_@XX@_set_name(objects_@XX@_t *xx, NSString *name);
|
||||||
|
|
||||||
|
/* Takes away XX's name. */
|
||||||
|
void
|
||||||
|
objects_@XX@_unset_name(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/** Serial numbers... **/
|
||||||
|
|
||||||
|
/* Returns the (process-wide) unique number given to the Libfn
|
||||||
|
* structure XX. See <objects/numbers.h> for more info. */
|
||||||
|
size_t
|
||||||
|
objects_@XX@_serial_number(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/* Gives XX a new (process-wide) unique number. Numbers are not
|
||||||
|
* reused. See <objects/numbers.h> for more info. */
|
||||||
|
size_t
|
||||||
|
_objects_@XX@_set_serial_number(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/** Extras... **/
|
||||||
|
|
||||||
|
/* Sets the callbacks associated with XX's ``extra''. NOTE: This must
|
||||||
|
* be done before calling `objects_@XX@_set_extra()', as these callbacks
|
||||||
|
* are used in that routine. */
|
||||||
|
objects_callbacks_t
|
||||||
|
objects_@XX@_set_extra_callbacks(objects_@XX@_t *xx,
|
||||||
|
objects_callbacks_t callbacks);
|
||||||
|
|
||||||
|
/* Returns the callbacks associated with XX's ``extra''. */
|
||||||
|
objects_callbacks_t
|
||||||
|
objects_@XX@_extra_callbacks(objects_@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 *
|
||||||
|
objects_@XX@_extra(objects_@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 *
|
||||||
|
objects_@XX@_set_extra(objects_@XX@_t *xx, const void *extra);
|
||||||
|
|
||||||
|
/* Resets XX's ``extra''. */
|
||||||
|
void
|
||||||
|
objects_@XX@_unset_extra(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/** Low-level Creation and Destruction **/
|
||||||
|
|
||||||
|
/* Handles the universal, low-level allocation of structures. */
|
||||||
|
objects_@XX@_t *
|
||||||
|
_objects_@XX@_alloc_with_zone(NSZone *zone);
|
||||||
|
|
||||||
|
/* Handles the universal, low-level deallocation of structures. */
|
||||||
|
void
|
||||||
|
_objects_@XX@_dealloc(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
/* Handles the low-level copying of structures. */
|
||||||
|
objects_@XX@_t *
|
||||||
|
_objects_@XX@_copy_with_zone(objects_@XX@_t *xx, NSZone *zone);
|
||||||
|
|
||||||
|
/* Returns a low-level description of XX. */
|
||||||
|
NSString *
|
||||||
|
_objects_@XX@_description(objects_@XX@_t *xx);
|
||||||
|
|
||||||
|
#endif /* __@XX@_bas_h_OBJECTS_INCLUDE */
|
||||||
|
|
69
Source/objects/x-cbs.h.in
Normal file
69
Source/objects/x-cbs.h.in
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/* 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 GNU Objective C Class Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
#ifndef __@YY@_cbs_h_OBJECTS_INCLUDE
|
||||||
|
#define __@YY@_cbs_h_OBJECTS_INCLUDE 1
|
||||||
|
|
||||||
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
|
#include <objects/callbacks.h>
|
||||||
|
#include <objects/@YY@.h>
|
||||||
|
|
||||||
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
#define __@YY@__ 1
|
||||||
|
|
||||||
|
/**** Function Implementations ***********************************************/
|
||||||
|
|
||||||
|
#ifdef __map__
|
||||||
|
|
||||||
|
/** Callbacks **/
|
||||||
|
|
||||||
|
/* Returns the callbacks associated with YY's keys. */
|
||||||
|
objects_callbacks_t objects_@YY@_key_callbacks (objects_@YY@_t *yy);
|
||||||
|
|
||||||
|
/* Returns the ``bogus'' marker associated with YY's keys. */
|
||||||
|
const void *objects_@YY@_not_a_key_marker (objects_@YY@_t *yy);
|
||||||
|
|
||||||
|
/* Returns the callbacks associated with YY's values. */
|
||||||
|
objects_callbacks_t
|
||||||
|
objects_@YY@_value_callbacks (objects_@YY@_t *yy);
|
||||||
|
|
||||||
|
/* Returns the ``bogus'' marker associated with YY's values. */
|
||||||
|
const void *objects_@YY@_not_a_value_marker (objects_@YY@_t *yy);
|
||||||
|
|
||||||
|
#else /* !__map__ */
|
||||||
|
|
||||||
|
/** Callbacks **/
|
||||||
|
|
||||||
|
/* Returns the callbacks associated with YY's elements. */
|
||||||
|
objects_callbacks_t objects_@YY@_element_callbacks (objects_@YY@_t *yy);
|
||||||
|
|
||||||
|
/* Returns the ``bogus'' marker associated with YY's elements. */
|
||||||
|
const void *objects_@YY@_not_an_element_marker (objects_@YY@_t *yy);
|
||||||
|
|
||||||
|
#endif /* __map__ */
|
||||||
|
|
||||||
|
#endif /* __@YY@_cbs_h_OBJECTS_INCLUDE */
|
||||||
|
|
Loading…
Reference in a new issue