File deleted.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1493 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Andrew McCallum 1996-05-06 19:10:52 +00:00
parent b00a575e5e
commit d39b518212
8 changed files with 0 additions and 5741 deletions

View file

@ -1,248 +0,0 @@
/* A sparse array structure.
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Thu Mar 2 02:30:02 EST 1994
* Updated: Tue Mar 12 02:42:54 EST 1996
* Serial: 96.03.12.13
*
* This file is part of the Gnustep Base Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef __array_h_GNUSTEP_BASE_INCLUDE
#define __array_h_GNUSTEP_BASE_INCLUDE 1
/**** Included Headers *******************************************************/
#include <stdlib.h>
#include <Foundation/NSZone.h>
#include <gnustep/base/callbacks.h>
#include <gnustep/base/hash.h>
/**** Type, Constant, and Macro Definitions **********************************/
typedef struct _o_array o_array_t;
typedef struct _o_array_bucket o_array_bucket_t;
typedef o_array_bucket_t *o_array_slot_t;
typedef struct _o_array_enumerator o_array_enumerator_t;
struct _o_array_bucket
{
/* The bucket's real (or external) index */
size_t index;
/* The bucket's cargo */
const void *element;
};
struct _o_array
{
/* Identifying information. */
int magic_number;
size_t serial_number;
NSZone *zone;
NSString *name;
const void *extra;
o_callbacks_t extra_callbacks;
/* Callbacks for the items in the array. */
o_callbacks_t callbacks;
/* Internal counters */
size_t slot_count;
size_t element_count;
/* Databanks */
o_array_slot_t *slots;
o_array_slot_t *sorted_slots;
};
struct _o_array_enumerator
{
o_array_t *array;
size_t index;
int is_sorted;
int is_ascending;
};
/**** Function Prototypes ****************************************************/
/** Basics **/
#include <gnustep/base/array-bas.h>
#include <gnustep/base/array-cbs.h>
/** Creating **/
o_array_t *
o_array_alloc(void);
o_array_t *
o_array_alloc_with_zone(NSZone *zone);
o_array_t *
o_array(void);
o_array_t *
o_array_with_zone(NSZone *zone);
o_array_t *
o_array_with_zone_with_callbacks(NSZone *zone,
o_callbacks_t callbacks);
o_array_t *
o_array_with_callbacks(o_callbacks_t callbacks);
o_array_t *
o_array_of_char_p(void);
o_array_t *
o_array_of_non_owned_void_p(void);
o_array_t *
o_array_of_owned_void_p(void);
o_array_t *
o_array_of_int(void);
o_array_t *
o_array_of_id(void);
/** Initializing **/
o_array_t *
o_array_init(o_array_t *array);
o_array_t *
o_array_init_with_callbacks(o_array_t *array,
o_callbacks_t callbacks);
o_array_t *
o_array_init_with_array(o_array_t *array,
o_array_t *other_array);
/** Copying **/
o_array_t *
o_array_copy(o_array_t *array);
o_array_t *
o_array_copy_with_zone(o_array_t *array, NSZone *zone);
/** Destroying **/
void
o_array_dealloc(o_array_t *array);
/** Comparing **/
int
o_array_is_equal_to_array(o_array_t *array,
o_array_t *other_array);
/** Adding **/
const void *
o_array_at_index_put_element(o_array_t *array,
size_t index,
const void *element);
/** Replacing **/
/** Removing **/
void
o_array_remove_element_at_index(o_array_t *array, size_t index);
void
o_array_remove_element(o_array_t *array, const void *element);
void
o_array_remove_element_known_present(o_array_t *array,
const void *element);
/** Emptying **/
void
o_array_empty(o_array_t *array);
/** Searching **/
int
o_array_contains_element(o_array_t *array, const void *element);
const void *
o_array_element(o_array_t *array, const void *element);
size_t
o_array_index_of_element(o_array_t *array, const void *element);
const void *
o_array_element_at_index(o_array_t *array, size_t index);
const void **
o_array_all_elements(o_array_t *array);
const void **
o_array_all_elements_ascending(o_array_t *array);
const void **
o_array_all_element_descending(o_array_t *array);
/** Enumerating **/
o_array_enumerator_t
o_array_enumerator(o_array_t *array);
o_array_enumerator_t
o_array_ascending_enumerator(o_array_t *array);
o_array_enumerator_t
o_array_descending_enumerator(o_array_t *array);
int
o_array_enumerator_next_index_and_element(o_array_enumerator_t *enumerator,
size_t *index,
const void **element);
int
o_array_enumerator_next_element(o_array_enumerator_t *enumerator,
const void **element);
int
o_array_enumerator_next_index(o_array_enumerator_t *enumerator,
size_t *element);
/** Statistics **/
int
o_array_is_empty(o_array_t *array);
size_t
o_array_count(o_array_t *array);
size_t
o_array_capacity(o_array_t *array);
int
o_array_check(o_array_t *array);
/** Miscellaneous **/
o_hash_t *
o_hash_init_from_array(o_hash_t *hash, o_array_t *array);
#endif /* __array_h_GNUSTEP_BASE_INCLUDE */

View file

@ -1,393 +0,0 @@
/* A hash table.
* Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: ??? ??? ?? ??:??:?? ??? 1993
* Updated: Tue Mar 19 00:25:34 EST 1996
* Serial: 96.03.19.05
*
* This file is part of the Gnustep Base Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef __hash_h_GNUSTEP_BASE_INCLUDE
#define __hash_h_GNUSTEP_BASE_INCLUDE 1
/**** Included Headers *******************************************************/
#include <Foundation/NSZone.h>
#include <Foundation/NSString.h>
#include <gnustep/base/callbacks.h>
/**** Type, Constant, and Macro Definitions **********************************/
/* Need these up here because of their interdependence. */
typedef struct _o_hash o_hash_t;
typedef struct _o_hash_enumerator o_hash_enumerator_t;
typedef struct _o_hash_node o_hash_node_t;
typedef struct _o_hash_bucket o_hash_bucket_t;
/* Private type for elemental holding. */
struct _o_hash_node
{
/* The hash table with which the node is associated. */
o_hash_t *hash;
/* The bucket in HASH in which the node sits. */
o_hash_bucket_t *bucket;
/* These hold the BUCKET linked list together. */
o_hash_node_t *next_in_bucket;
o_hash_node_t *prev_in_bucket;
/* For enumerating over the whole hash table. These make
* enumerating much quicker. They also make it safer. */
o_hash_node_t *next_in_hash;
o_hash_node_t *prev_in_hash;
/* What the node is holding for us. Its raison d'etre. */
const void *element;
};
/* Private type for holding chains of nodes. */
struct _o_hash_bucket
{
/* The number of nodes in this bucket. For internal consistency checks. */
size_t node_count;
/* The number of elements in this bucket. (This had *better* be
* the same as NODE_COUNT, or something's wrong.) */
size_t element_count;
/* The head of this bucket's linked list of nodes. */
o_hash_node_t *first_node;
};
/* The hash table type. */
struct _o_hash
{
/* All structures have these...
* And all structures have them in the same order. */
int magic_number;
size_t serial_number;
NSZone *zone;
NSString *name;
const void *extra;
o_callbacks_t extra_callbacks;
/* Callbacks for the elements of the hash. */
o_callbacks_t callbacks;
/* Internal counters. Mainly for consistency's sake. */
size_t bucket_count; /* How many types of items? */
size_t node_count; /* How many items? */
size_t element_count; /* How many elements? */
/* Places to start looking for elements. */
o_hash_bucket_t *buckets; /* Organized as a hash. */
o_hash_node_t *first_node; /* Organized as a linked list.
* (For enumerating...) */
};
/* Type for enumerating the elements of a hash table. */
struct _o_hash_enumerator
{
o_hash_t *hash; /* To which hash do I belong? */
o_hash_node_t *node; /* Which node is next? */
};
/**** Function Prototypes ****************************************************/
/** Basics... **/
/* All the structures (hashes, maps, lists, and arrays) have
* the same basic ideas behind them. */
#include <gnustep/base/hash-bas.h>
#include <gnustep/base/hash-cbs.h>
/** Callbacks... **/
/* Returns a collection of callbacks for use with hash tables. */
o_callbacks_t
o_callbacks_for_hash(void);
/** Creating... **/
/* Allocate a hash table in the default zone. */
o_hash_t *
o_hash_alloc(void);
/* Allocate a hash table in the memory block ZONE. */
o_hash_t *
o_hash_alloc_with_zone(NSZone *zone);
/* Create an empty hash table in the memory block ZONE. The returned
* hash table has a "reasonable" default capacity, but will need to
* be resized to suit your specific needs if more than a couple of
* dozen elements will be placed within it. */
o_hash_t *
o_hash_with_zone_with_callbacks(NSZone *zone,
o_callbacks_t callbacks);
/* Like calling 'o_hash_with_zone_with_callbacks(zone,
* o_callbacks_standard())'. */
o_hash_t *
o_hash_with_zone(NSZone *zone);
/* Like calling 'o_hash_with_zone_with_callbacks(0, callbacks)'. */
o_hash_t *
o_hash_with_callbacks(o_callbacks_t callbacks);
/* These are just shortcuts for ease of use. */
o_hash_t *o_hash_of_char_p(void);
o_hash_t *o_hash_of_non_owned_void_p(void);
o_hash_t *o_hash_of_owned_void_p(void);
o_hash_t *o_hash_of_int(void);
o_hash_t *o_hash_of_int_p(void);
o_hash_t *o_hash_of_id(void);
/** Initializing... **/
/* Initializes HASH with a "reasonable" capacity, with the
* callbacks obtained from 'o_callbacks_standard()'. */
o_hash_t *
o_hash_init(o_hash_t *hash);
/* Initializes HASH with a "reasonable" capacity and
* with element callbacks CALLBACKS. */
o_hash_t *
o_hash_init_with_callbacks(o_hash_t *hash,
o_callbacks_t callbacks);
/* Initializes HASH with the capacity, callbacks, and contents
* of OTHER_HASH. NOTE: This is (as it must be) a "shallow" copying.
* See 'o_hash_copy_with_zone()', below. */
o_hash_t *
o_hash_init_with_hash(o_hash_t *hash,
o_hash_t *other_hash);
/** Copying... **/
/* Creates a (shallow) copy of HASH in the memory block ZONE. WARNING:
* If the elements of HASH are pointers to mutable items, it is the
* programmer's responsibility to deepen the copy returned by this
* function call (using, for example, `o_hash_map_elements()'). */
o_hash_t *
o_hash_copy_with_zone(o_hash_t *hash, NSZone *zone);
/* Create a (shallow) copy of HASH in the default zone. WARNING: See the
* above function for an important caveat about copying. */
o_hash_t *
o_hash_copy(o_hash_t *old_hash);
/** Mapping... **/
/* WARNING: The mapping function FCN must be one-to-one on elements of
* HASH. I.e., for reasons of efficiency, `o_hash_map_elements()'
* makes no provision for the possibility that FCN maps two unequal
* elements of HASH to the same (or "equal") elements. The better way
* to handle functions that aren't one-to-one is to create a new hash
* and transform the elements of the first to create the elements of
* the second (by manual enumeration). */
o_hash_t *
o_hash_map_elements(o_hash_t *hash,
const void *(*fcn)(const void *, const void *),
const void *user_data);
/** Destroying... **/
/* Releases all the elements of HASH, and then frees up the space
* HASH used. HASH is no longer a (pointer to a) valid hash
* table structure after this call. */
void
o_hash_dealloc(o_hash_t *hash);
/** Comparing... **/
/* Returns 'true' if every element of OTHER_HASH is also
* a member of HASH. Otherwise, returns 'false'. */
int
o_hash_contains_hash(o_hash_t *hash,
o_hash_t *other_hash);
/* Returns 'true' if some element of HASH is also
* a member of OTHER_HASH. Otherwise, returns 'false'. */
int
o_hash_intersects_hash(o_hash_t *hash,
o_hash_t *other_hash);
/* Returns 'true' if HASH and OTHER_HASH have the same number of elements,
* HASH contains OTHER_HASH, and OTHER_HASH contains HASH. Otheraise, returns 'false'. */
int
o_hash_is_equal_to_hash(o_hash_t *hash,
o_hash_t *other_hash);
/** Adding... **/
/* Adds ELEMENT to HASH. If ELEMENT is "equal" to an item already in HASH,
* then we abort. If ELEMENT is the "not an element marker" for HASH,
* then we abort. [NOTE: This abortive behaviour will be changed in a
* future revision.] */
const void *
o_hash_add_element_known_absent(o_hash_t *hash,
const void *element);
/* Adds ELEMENT to HASH. If ELEMENT is "equal" to an item already in HASH,
* then that older item is released using the 'release()' callback function
* that was specified when HASH was created. (If ELEMENT is the "not an
* element marker" for HASH, then all bets are off, and we abort.
* [NOTE: This abortive behaviour will be changed in a future revision.]) */
const void *
o_hash_add_element(o_hash_t *hash, const void *element);
/* If (any item "equal" to) ELEMENT is in HASH, then that member of HASH is
* returned. Otherwise, the "not an element marker" for HASH is returned
* and ELEMENT is added to HASH. If ELEMENT is the "not an element marker"
* for HASH, then we abort. [NOTE: This abortive behaviour will be changed
* in a future revision.] */
const void *
o_hash_add_element_if_absent(o_hash_t *hash, const void *element);
/** Replacing... **/
/* If (some item "equal" to) ELEMENT is an element of HASH, then ELEMENT is
* substituted for it. The old element is released. (This is rather
* like the non-existant but perfectly reasonable function
* 'o_hash_add_element_if_present()'.) */
void
o_hash_replace_element(o_hash_t *hash,
const void *element);
/** Removing... **/
/* Removes the element (if any) of HASH which is "equal" to ELEMENT,
* according to HASH's element callbacks. It is not an error to
* remove ELEMENT from HASH, if no element of HASH is "equal" to ELEMENT. */
void
o_hash_remove_element(o_hash_t *hash, const void *element);
/** Emptying... **/
/* Empties HASH, releasing all of its elements while retaining
* its current "capacity". */
void
o_hash_empty(o_hash_t *hash);
/** Searching... **/
/* Returns a "random" element of HASH, for your viewing enjoyment. */
void *
o_hash_any_element(o_hash_t *hash);
/* Returns `true' if some element of HASH is "equal" to ELEMENT,
* according to HASH's element callbacks. */
int
o_hash_contains_element(o_hash_t *hash, const void *element);
/* Returns the element of HASH (or the appropriate `not an element
* marker' if there is none) which is "equal" to ELEMENT. */
const void *
o_hash_element(o_hash_t *hash, const void *element);
/* Returns an array with all the elements of HASH, terminated
* by HASH's "not an element marker". It is your responsibility
* to free the returned array. [NOTE: this responsibility may
* shift from your shoulders in a later revision.] */
const void **
o_hash_all_elements(o_hash_t *hash);
/** Enumerating... **/
/* Returns an enumerator for HASH's elements. WARNING: DO NOT ALTER
* A HASH DURING AN ENUMERATION. DOING SO WILL PROBABLY LEAVE YOUR ENUMERATION
* IN AN INDETERMINATE STATE. If you are hell-bent on ignoring the above
* warning, please check out the source code for some more specific
* information about when and how one can get away with it. */
o_hash_enumerator_t
o_hash_enumerator_for_hash(o_hash_t *hash);
/* Returns `false' if the enumeration is complete, `true' otherwise.
* If ELEMENT is non-zero, the next element of ENUMERATOR's hash table
* is returned by reference. */
int
o_hash_enumerator_next_element(o_hash_enumerator_t *enumerator,
const void **element);
/** Statistics... **/
/* Returns `true' if HASH contains no elements. */
int
o_hash_is_empty(o_hash_t *hash);
/* Returns the number of elements HASH is currently holding. So long as no
* additions or removals occur, you may take this number to be accurate. */
size_t
o_hash_count(o_hash_t *hash);
/* Returns a number which represents (to some degree) HASH's current ability
* to hold stuff. Do not, however, rely on this for precision. Treat as
* a (reasonable) estimate. */
size_t
o_hash_capacity(o_hash_t *hash);
/* Performs an internal consistency check on HASH. Useful only
* for debugging. */
int
o_hash_check(o_hash_t *hash);
/** Resizing... **/
/* Resizes HASH to be ready to contain (at least) NEW_CAPACITY many elements.
* However, as far as you are concerned, it is indeterminate what exactly
* this means. After receiving and successfully processing this call,
* you are *not* guaranteed that HASH has actually set aside space for
* NEW_CAPACITY elements, for example. All that you are guaranteed is that,
* to the best of its ability, HASH will incur no loss in efficiency so long
* as it contains no more than NEW_CAPACITY elements. */
size_t
o_hash_resize(o_hash_t *hash, size_t new_capacity);
/* Shrinks (or grows) HASH to be comfortable with the number of elements
* it contains. In all likelyhood, after this call, HASH is more efficient
* in terms of its speed of search vs. use of space balance. */
size_t
o_hash_rightsize(o_hash_t *hash);
/** Describing... **/
/* Returns a string describing (the contents of) HASH. */
NSString *
o_hash_description(o_hash_t *hash);
/** Set theoretic operations... **/
/* Removes from HASH all of its elements which are not also
* elements of OTHER_HASH. Returns HASH as a courtesy. */
o_hash_t *
o_hash_intersect_hash(o_hash_t *hash, o_hash_t *other_hash);
/* Removes from HASH all of its elements which are also
* elements of OTHER_HASH. Returns HASH as a courtesy. */
o_hash_t *
o_hash_minus_hash(o_hash_t *hash, o_hash_t *other_hash);
/* Adds to HASH all elements of OTHER_HASH which are not
* already members of HASH. Returns HASH as a courtesy. */
o_hash_t *
o_hash_union_hash(o_hash_t *hash, o_hash_t *other_hash);
#endif /* __hash_h_GNUSTEP_BASE_INCLUDE */

View file

@ -1,346 +0,0 @@
/* A list structure.
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Tue Sep 5 17:25:59 EDT 1995
* Updated: Sun Mar 10 23:24:49 EST 1996
* Serial: 96.03.10.02
*
* This file is part of the Gnustep Base Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef __list_h_GNUSTEP_BASE_INCLUDE
#define __list_h_GNUSTEP_BASE_INCLUDE 1
/**** Included Headers *******************************************************/
#include <Foundation/NSZone.h>
#include <gnustep/base/callbacks.h>
#include <gnustep/base/hash.h>
#include <gnustep/base/array.h>
/**** Type, Constant, and Macro Definitions **********************************/
typedef struct _o_list o_list_t;
typedef struct _o_list_node o_list_node_t;
typedef struct _o_list_enumerator o_list_enumerator_t;
struct _o_list_node
{
o_list_t *list;
o_list_node_t *next_in_list;
o_list_node_t *prev_in_list;
const void *element;
};
struct _o_list
{
/* Container identifiers */
int magic_number;
size_t serial_number;
NSZone *zone;
NSString *name;
const void *extra;
o_callbacks_t extra_callbacks;
/* Element callbacks */
o_callbacks_t callbacks;
/* Internal counters */
size_t node_count;
size_t element_count;
/* Databanks */
o_list_node_t *first_node;
o_list_node_t *last_node;
};
struct _o_list_enumerator
{
o_list_t *list;
o_list_node_t *node;
size_t forward;
};
/**** Function Prototypes ****************************************************/
/** Basics **/
#include <gnustep/base/list-bas.h>
#include <gnustep/base/list-cbs.h>
/** Creating **/
o_list_t *
o_list_alloc(void);
o_list_t *
o_list_alloc_with_zone(NSZone *zone);
o_list_t *
o_list_with_zone(NSZone *zone);
o_list_t *
o_list_with_callbacks(o_callbacks_t callbacks);
o_list_t *
o_list_with_zone_with_callbacks(NSZone *zone,
o_callbacks_t callbacks);
o_list_t *
o_list_of_char_p(void);
o_list_t *
o_list_of_non_owned_void_p(void);
o_list_t *
o_list_of_owned_void_p(void);
o_list_t *
o_list_of_int(void);
o_list_t *
o_list_of_int_p(void);
o_list_t *
o_list_of_id(void);
/** Initializing **/
o_list_t *
o_list_init(o_list_t *list);
o_list_t *
o_list_init_with_callbacks(o_list_t *list,
o_callbacks_t callbacks);
/** Copying **/
o_list_t *
o_list_copy(o_list_t *old_list);
o_list_t *
o_list_copy_with_zone(o_list_t *old_list,
NSZone *zone);
/** Destroying **/
void
o_list_dealloc(o_list_t *list);
/** Comparing **/
int
o_list_is_equal_to_list(o_list_t *list,
o_list_t *other_list);
/** Concatenating **/
o_list_t *
o_list_append_list(o_list_t *base_list,
o_list_t *suffix_list);
o_list_t *
o_list_prepend_list(o_list_t *base_list,
o_list_t *prefix_list);
o_list_t *
o_list_at_index_insert_list(o_list_t *base_list,
long int n,
o_list_t *infix_list);
/** Permuting **/
o_list_t *
o_list_roll_to_nth_element(o_list_t *list, long int n);
o_list_t *
o_list_roll_to_element(o_list_t *list, const void *element);
o_list_t *
o_list_roll_to_nth_occurrance_of_element(o_list_t *list,
long int n,
const void *element);
o_list_t *
o_list_invert(o_list_t *list);
o_list_t *
o_list_swap_elements_at_indices(o_list_t *list,
long int m,
long int n);
/** Adding **/
const void *
o_list_append_element(o_list_t *list, const void *element);
const void *
o_list_append_element_if_absent(o_list_t *list,
const void *element);
const void *
o_list_prepend_element(o_list_t *list, const void *element);
const void *
o_list_prepend_element_if_absent(o_list_t *list,
const void *element);
const void *
o_list_at_index_insert_element(o_list_t *list,
long int n,
const void *element);
const void *
o_list_at_index_insert_element_if_absent(o_list_t *list,
long int n,
const void *element);
const void *
o_list_queue_push_element(o_list_t *list, const void *element);
const void *
o_list_stack_push_element(o_list_t *list, const void *element);
/** Replacing **/
void
o_list_replace_nth_occurrance_of_element(o_list_t *list,
long int n,
const void *old_element,
const void *new_element);
void
o_list_replace_element(o_list_t *list,
const void *old_element,
const void *new_element);
void
o_list_replace_nth_element(o_list_t *list,
long int n,
const void *new_element);
void
o_list_replace_first_element(o_list_t *list,
const void *new_element);
void
o_list_replace_last_element(o_list_t *list,
const void *new_element);
/** Removing **/
void
o_list_remove_nth_occurrence_of_element(o_list_t *list,
long int n,
const void *element);
void
o_list_remove_element(o_list_t *list, const void *element);
void
o_list_remove_nth_element(o_list_t *list, long int n);
void
o_list_remove_first_element(o_list_t *list);
void
o_list_remove_last_element(o_list_t *list);
void
o_list_queue_pop_element(o_list_t *list);
void
o_list_queue_pop_nth_element(o_list_t *list, long int n);
void
o_list_stack_pop_element(o_list_t *list);
void
o_list_stack_pop_nth_element(o_list_t *list, long int n);
/** Emptying **/
void
o_list_empty(o_list_t *list);
/** Searching **/
int
o_list_contains_element(o_list_t *list, const void *element);
const void *
o_list_element(o_list_t *list, const void *element);
const void *
o_list_nth_element(o_list_t *list, long int n);
const void *
o_list_first_element(o_list_t *list);
const void *
o_list_last_element(o_list_t *list);
const void **
o_list_all_elements(o_list_t *list);
/** Enumerating **/
o_list_enumerator_t
o_list_enumerator(o_list_t *list);
o_list_enumerator_t
o_list_forward_enumerator(o_list_t *list);
o_list_enumerator_t
o_list_reverse_enumerator(o_list_t *list);
int
o_list_enumerator_next_element(o_list_enumerator_t *enumerator,
const void **element);
/** Mapping **/
/* NO WARNING: The mapping function FCN need not be one-to-one on the
* elements of LIST. In fact, FCN may do whatever it likes. */
o_list_t *
o_list_map_elements(o_list_t *list,
const void *(*fcn)(const void *, void *),
void *user_data);
/** Statistics **/
int
o_list_is_empty(o_list_t *list);
size_t
o_list_count(o_list_t *list);
size_t
o_list_capacity(o_list_t *list);
int
o_list_check(o_list_t *list);
/** Miscellaneous **/
o_hash_t *
o_hash_init_from_list(o_hash_t *hash, o_list_t *list);
#endif /* __list_h_GNUSTEP_BASE_INCLUDE */

View file

@ -1,429 +0,0 @@
/* A map table.
* Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: ??? ??? ?? ??:??:?? ??? 1993
* Updated: Thu Mar 21 00:05:43 EST 1996
* Serial: 96.03.20.04
*
* This file is part of the Gnustep Base Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef __map_h_GNUSTEP_BASE_INCLUDE
#define __map_h_GNUSTEP_BASE_INCLUDE 1
/**** Included Headers *******************************************************/
#include <Foundation/NSZone.h>
#include <gnustep/base/callbacks.h>
#include <gnustep/base/hash.h>
/**** Type, Constant, and Macro Definitions **********************************/
/* Need these up here because of their interdependence. */
typedef struct _o_map o_map_t;
typedef struct _o_map_bucket o_map_bucket_t;
typedef struct _o_map_node o_map_node_t;
typedef struct _o_map_enumerator o_map_enumerator_t;
/* Important structures... */
/* Private type for elemental holding. */
struct _o_map_node
{
/* The map table with which the node is associated. */
o_map_t *map;
/* The bucket in MAP in which the node sits. */
o_map_bucket_t *bucket;
/* These hold the BUCKET linked list together. */
o_map_node_t *next_in_bucket;
o_map_node_t *prev_in_bucket;
/* For enumerating over the whole map table. These make
* enumerating much quicker. They also make it safer. */
o_map_node_t *next_in_map;
o_map_node_t *prev_in_map;
const void *key;
const void *value;
};
/* Private type for holding chains of nodes. */
struct _o_map_bucket
{
/* The number of nodes in this bucket. For internal consistency checks. */
size_t node_count;
/* The number of elements in this bucket. (This had *better* be
* the same as NODE_COUNT, or something's wrong.) */
size_t element_count;
/* The head of this bucket's linked list of nodes. */
o_map_node_t *first_node;
};
/* The map table type. */
struct _o_map
{
/* All structures have these...
* And all structures have them in the same order. */
int magic_number;
size_t serial_number;
NSZone *zone;
NSString *name;
const void *extra;
o_callbacks_t extra_callbacks;
/* For keys...And Values. */
o_callbacks_t key_callbacks;
o_callbacks_t value_callbacks;
/* Internal counters */
size_t bucket_count;
size_t node_count;
size_t element_count;
/* Places to start looking for elements. */
o_map_bucket_t *buckets; /* Organized as a hash. */
o_map_node_t *first_node; /* Organized as a linked list.
* (For enumerating...) */
};
/* Type for enumerating the elements of a map table. */
struct _o_map_enumerator
{
o_map_t *map; /* To which hash do I belong? */
o_map_node_t *node; /* Which node is next? */
};
/**** Function Prototypes ****************************************************/
/** Basics... **/
/* All the structures (hashes, maps, lists, and arrays) have
* the same basic ideas behind them. */
#include <gnustep/base/map-bas.h>
#include <gnustep/base/map-cbs.h>
/** Callbacks... **/
/* Returns a collection of callbacks for use with hash tables. */
o_callbacks_t
o_callbacks_for_map(void);
/** Creating... **/
/* Allocate a hash table in the default zone. */
o_map_t *
o_map_alloc(void);
/* Allocate a hash table in the memory block ZONE. */
o_map_t *
o_map_alloc_with_zone(NSZone *zone);
/* Create an empty map table in the memory block ZONE. The returned
* hash table has a "reasonable" default capacity, but will need to
* be resized to suit your specific needs if more than a couple of
* dozen key/value pairs will be placed within it. */
o_map_t *
o_map_with_zone_with_callbacks(NSZone *zone,
o_callbacks_t key_callbacks,
o_callbacks_t value_callbacks);
/* Like calling 'o_map_with_zone_with_callbacks(0, key_callbacks,
* value_callbacks)'. */
o_map_t *
o_map_with_callbacks(o_callbacks_t key_callbacks,
o_callbacks_t value_callbacks);
/* Like calling 'o_map_with_zone_with_callbacks(0,
* o_callbacks_standard(), o_callbacks_standard())'. */
o_map_t *
o_map_with_zone(NSZone *zone);
/* Shortcuts... */
o_map_t *o_map_of_int(void);
o_map_t *o_map_of_int_to_char_p(void);
o_map_t *o_map_of_int_to_non_owned_void_p(void);
o_map_t *o_map_of_int_to_id(void);
o_map_t *o_map_of_char_p(void);
o_map_t *o_map_of_char_p_to_int(void);
o_map_t *o_map_of_char_p_to_non_owned_void_p(void);
o_map_t *o_map_of_char_p_to_id(void);
o_map_t *o_map_of_non_owned_void_p(void);
o_map_t *o_map_of_non_owned_void_p_to_int(void);
o_map_t *o_map_of_non_owned_void_p_to_char_p(void);
o_map_t *o_map_of_non_owned_void_p_to_id(void);
o_map_t *o_map_of_id(void);
/** Initializing... **/
o_map_t *
o_map_init(o_map_t *map);
o_map_t *
o_map_init_with_callbacks(o_map_t *map,
o_callbacks_t key_callbacks,
o_callbacks_t value_callbacks);
o_map_t *
object_map_init_from_map(o_map_t *map, o_map_t *old_map);
/** Destroying... **/
/* Releases all the keys and values of MAP, and then
* deallocates MAP itself. */
void
o_map_dealloc(o_map_t *map);
/** Gathering statistics on a map... **/
/* Returns the number of key/value pairs in MAP. */
size_t
o_map_count(o_map_t *map);
/* Returns some (inexact) measure of how many key/value pairs
* MAP can comfortably hold without resizing. */
size_t
o_map_capacity(o_map_t *map);
/* Performs an internal consistency check, returns 'true' if
* everything is OK, 'false' otherwise. Really useful only
* for debugging. */
int
o_map_check(o_map_t *map);
/** Finding elements in a map... **/
/* Returns 'true' if and only if some key in MAP is equal
* (in the sense of the key callbacks of MAP) to KEY. */
int
o_map_contains_key(o_map_t *map, const void *key);
/* Returns 'true' if and only if some value in MAP is equal
* (in the sense of the value callbacks of MAP) to VALUE. */
/* WARNING: This is rather inefficient. Not to be used lightly. */
int
o_map_contains_value(o_map_t *map, const void *value);
/* If KEY is in MAP, then the following three things happen:
* (1) 'true' is returned;
* (2) if OLD_KEY is non-zero, then the key in MAP
* equal to KEY is placed there;
* (3) if VALUE is non-zero, then the value in MAP
* mapped to by KEY is placed there.
* If KEY is not in MAP, then the following three things happen:
* (1) 'false' is returned;
* (2) if OLD_KEY is non-zero, then the "not a key marker"
* for MAP is placed there;
* (3) if VALUE is non-zero, then the the "not a value marker"
* for MAP is placed there. */
int
o_map_key_and_value_at_key(o_map_t *map,
const void **old_key,
const void **value,
const void *key);
/* If KEY is in MAP, then the key of MAP which is equal to KEY
* is returned. Otherwise, the "not a key marker" for MAP is returned. */
const void *
o_map_key_at_key(o_map_t *map, const void *key);
/* If KEY is in MAP, then the value of MAP which to which KEY maps
* is returned. Otherwise, the "not a value marker" for MAP is returned. */
const void *
o_map_value_at_key(o_map_t *map, const void *key);
/** Enumerating the nodes and elements of a map... **/
o_map_enumerator_t
o_map_enumerator_for_map(o_map_t *map);
int
o_map_enumerator_next_key_and_value(o_map_enumerator_t *enumerator,
const void **key,
const void **value);
int
o_map_enumerator_next_key(o_map_enumerator_t *enumerator,
const void **key);
int
o_map_enumerator_next_value(o_map_enumerator_t *enumerator,
const void **value);
/** Obtaining an array of the elements of a map... **/
const void **
o_map_all_keys_and_values(o_map_t *map);
const void **
o_map_all_keys(o_map_t *map);
const void **
o_map_all_values(o_map_t *map);
/** Removing... **/
/* Removes the key/value pair (if any) from MAP whose key is KEY. */
void
o_map_remove_key(o_map_t *map, const void *key);
/* Releases all of the keys and values of MAP without
* altering MAP's capacity. */
void
o_map_empty(o_map_t *map);
/** Adding... **/
const void *
o_map_at_key_put_value_known_absent(o_map_t *map,
const void *key,
const void *value);
const void *
o_map_at_key_put_value(o_map_t *map,
const void *key,
const void *value);
const void *
o_map_at_key_put_value_if_absent(o_map_t *map,
const void *key,
const void *value);
/** Replacing... **/
void
o_map_replace_key(o_map_t *map, const void *key);
/** Comparing... **/
/* Returns 'true' if every key/value pair of MAP2 is also a key/value pair
* of MAP1. Otherwise, returns 'false'. */
int
o_map_contains_map(o_map_t *map1, o_map_t *map2);
/* Returns 'true' if MAP1 and MAP2 have the same number of key/value pairs,
* MAP1 contains MAP2, and MAP2 contains MAP1. Otherwise, returns 'false'. */
int
o_map_is_equal_to_map(o_map_t *map1, o_map_t *map2);
/* Returns 'true' iff every key of MAP2 is a key of MAP1. */
int
o_map_keys_contain_keys_of_map(o_map_t *map1, o_map_t *map2);
/* Returns 'true' if MAP1 and MAP2 have the same number of key/value pairs,
* MAP1 contains every key of MAP2, and MAP2 contains every key of MAP1.
* Otherwise, returns 'false'. */
int
o_map_keys_are_equal_to_keys_of_map(o_map_t *map1,
o_map_t *map2);
/* Returns 'true' iff some key/value pair of MAP1 if also
* a key/value pair of MAP2. */
int
o_map_intersects_map(o_map_t *map1, o_map_t *map2);
/* Returns 'true' iff some key of MAP1 if also a key of MAP2. */
int
o_map_keys_intersect_keys_of_map(o_map_t *map1,
o_map_t *map2);
/** Copying... **/
/* Returns a copy of OLD_MAP in ZONE. Remember that, as far as what
* (if anything) OLD_MAP's keys and values point to, this copy is
* shallow. If, for example, OLD_MAP is a map from int to int, then
* you've got nothing more to worry about. If, however, OLD_MAP is a
* map from id to id, and you want the copy of OLD_MAP to be "deep",
* you'll need to use the mapping functions below to make copies of
* all of the returned map's elements. */
o_map_t *
o_map_copy_with_zone(o_map_t *old_map, NSZone *zone);
/* Just like 'o_map_copy_with_zone()', but returns a copy of
* OLD_MAP in the default zone. */
o_map_t *
o_map_copy(o_map_t *old_map);
/** Mapping... **/
/* Iterates through MAP, replacing each key with the result of
* '(*kfcn)(key, user_data)'. Useful for deepening copied maps
* and other uniform (and one-to-one) transformations of map keys. */
/* WARNING: The mapping function KFCN *must* be one-to-one on the
* (equivalence classes of) keys of MAP. I.e., for efficiency's sake,
* `o_map_map_keys()' makes no provision for the possibility
* that KFCN maps two unequal keys of MAP to the same (or equal) keys. */
o_map_t *
o_map_map_keys(o_map_t *map,
const void *(*kfcn)(const void *, void *),
void *user_data);
/* Iterates through MAP, replacing each value with the result of
* '(*vfcn)(value, user_data)'. Useful for deepening copied maps
* and other uniform transformations of map keys. */
/* NO WARNING: The mapping function VFCN need not be one-to-one on
* (the equivalence classes of) values. */
o_map_t *
o_map_map_values(o_map_t *map,
const void *(*vfcn)(const void *, void *),
void *user_data);
/** Resizing... **/
/* Resizes MAP to be ready to contain (at least) NEW_CAPACITY many elements.
* However, as far as you are concerned, it is indeterminate what exactly
* this means. After receiving and successfully processing this call,
* you are *not* guaranteed that MAP has actually set aside space for
* NEW_CAPACITY elements, for example. All that you are guaranteed is that,
* to the best of its ability, MAP will incur no loss in efficiency so long
* as it contains no more than NEW_CAPACITY elements. */
size_t
o_map_resize(o_map_t *map, size_t new_capacity);
/* Shrinks (or grows) MAP to be comfortable with the number of elements
* it contains. In all likelyhood, after this call, MAP is more efficient
* in terms of its speed of search vs. use of space balance. */
size_t
o_map_rightsize(o_map_t *map);
/** Describing... **/
/* Returns a string describing (the contents of) MAP. */
NSString *
o_map_description(o_map_t *map);
/** Set theoretic operations... **/
o_map_t *
o_map_intersect_map(o_map_t *map, o_map_t *other_map);
o_map_t *
o_map_minus_map(o_map_t *map, o_map_t *other_map);
o_map_t *
o_map_union_map(o_map_t *map, o_map_t *other_map);
o_hash_t *
o_hash_init_from_map_keys(o_hash_t *hash, o_map_t *map);
o_hash_t *
o_hash_init_from_map_values(o_hash_t *hash, o_map_t *map);
#endif /* __map_h_GNUSTEP_BASE_INCLUDE */

View file

@ -1,910 +0,0 @@
/* A (pretty good) implementation of a sparse array.
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Thu Mar 2 02:28:50 EST 1994
* Updated: Tue Mar 12 02:42:33 EST 1996
* Serial: 96.03.12.13
*
* This file is part of the Gnustep Base Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/**** Included Headers *******************************************************/
#include <Foundation/NSZone.h>
#include <gnustep/base/callbacks.h>
#include <gnustep/base/array.h>
#include <gnustep/base/hash.h>
/**** Function Implementations ***********************************************/
/** Background functions **/
static inline size_t
_o_array_fold_index(size_t index, size_t slot_count)
{
return (slot_count ? (index % slot_count) : 0);
}
static inline size_t
_o_array_internal_index(o_array_t *array, size_t index)
{
return _o_array_fold_index (index, array->slot_count);
}
static inline o_array_slot_t *
_o_array_slot_for_index(o_array_t *array, size_t index)
{
return (array->slots + _o_array_internal_index (array, index));
}
static inline o_array_bucket_t *
_o_array_bucket_for_index (o_array_t *array, size_t index)
{
o_array_slot_t *slot;
o_array_bucket_t *bucket;
/* First, we translate the index into a bucket index to find our
* candidate for the bucket. */
slot = _o_array_slot_for_index (array, index);
bucket = *slot;
/* But we need to check to see whether this is really the bucket we
* wanted. */
if (bucket != 0 && bucket->index == index)
/* Bucket `index' exists, and we've got it, so... */
return bucket;
else
/* Either no bucket or some other bucket is where bucket `index'
* would be, if it existed. So... */
return 0;
}
static inline o_array_bucket_t *
_o_array_new_bucket (o_array_t *array, size_t index, const void *element)
{
o_array_bucket_t *bucket;
bucket = (o_array_bucket_t *) NSZoneMalloc(o_array_zone(array),
sizeof(o_array_bucket_t));
if (bucket != 0)
{
o_retain(o_array_element_callbacks(array), element, array);
bucket->index = index;
bucket->element = element;
}
return bucket;
}
static inline void
_o_array_free_bucket(o_array_t *array,
o_array_bucket_t *bucket)
{
if (bucket != 0)
{
o_release(o_array_element_callbacks (array),
(void *)(bucket->element),
array);
NSZoneFree(o_array_zone(array), bucket);
}
return;
}
static inline o_array_slot_t *
_o_array_new_slots(o_array_t *array, size_t slot_count)
{
return (o_array_slot_t *) NSZoneCalloc(o_array_zone(array),
slot_count,
sizeof(o_array_slot_t));
}
static inline void
_o_array_free_slots(o_array_t *array,
o_array_slot_t *slots)
{
if (slots != 0)
NSZoneFree(o_array_zone(array), slots);
return;
}
static inline void
_o_array_empty_slot (o_array_t *array, o_array_slot_t * slot)
{
if (*slot != 0)
{
/* Get rid of the bucket. */
_o_array_free_bucket (array, *slot);
/* Mark the slot as empty. */
*slot = 0;
/* Keep the element count accurate */
--(array->element_count);
}
/* And return. */
return;
}
static inline void
_o_array_insert_bucket(o_array_t *array,
o_array_bucket_t * bucket)
{
o_array_slot_t *slot;
slot = _o_array_slot_for_index (array, bucket->index);
/* We're adding a bucket, so the current set of sorted slots is now
* invalidated. */
if (array->sorted_slots != 0)
{
_o_array_free_slots (array, array->sorted_slots);
array->sorted_slots = 0;
}
if ((*slot) == 0)
{
/* There's nothing there, so we can put `bucket' there. */
*slot = bucket;
/* Increment the array's bucket counter. */
++(array->element_count);
return;
}
if ((*slot)->index == bucket->index)
{
/* There's a bucket there, and it has the same index as `bucket'.
* So we get rid of the old one, and put the new one in its
* place. */
_o_array_free_bucket (array, *slot);
*slot = bucket;
return;
}
else
{
/* Now we get to fiddle around with things to make the world a
* better place... */
size_t new_slot_count;
o_array_slot_t *new_slots; /* This guy holds the buckets while we
* muck about with them. */
size_t d; /* Just a counter */
/* FIXME: I *really* wish I had a way of generating
* statistically better initial values for this variable. So
* I'll run a few tests and see... And is there a better
* algorithm, e.g., a better collection of sizes in the sense
* that the likelyhood of fitting everything in earlier is
* high? Well, enough mumbling. */
/* At any rate, we're guaranteed to need at least this many. */
new_slot_count = array->element_count + 1;
do
{
/* First we make a new pile of slots for the buckets. */
new_slots = _o_array_new_slots (array, new_slot_count);
if (new_slots == 0)
/* FIXME: Make this a *little* more friendly. */
abort();
/* Then we put the new bucket in the pile. */
new_slots[_o_array_fold_index (bucket->index,
new_slot_count)] = bucket;
/* Now loop and try to place the others. Upon collision
* with a previously inserted bucket, try again with more
* `new_slots'. */
for (d = 0; d < array->slot_count; ++d)
{
if (array->slots[d] != 0)
{
size_t i;
i = _o_array_fold_index (array->slots[d]->index,
new_slot_count);
if (new_slots[i] == 0)
{
new_slots[i] = array->slots[d];
}
else
{
/* A collision. Clean up and try again. */
/* Free the current set of new buckets. */
_o_array_free_slots (array, new_slots);
/* Bump up the number of new buckets. */
++new_slot_count;
/* Break out of the `for' loop. */
break;
}
}
}
}
while (d < array->slot_count);
if (array->slots != 0)
_o_array_free_slots (array, array->slots);
array->slots = new_slots;
array->slot_count = new_slot_count;
++(array->element_count);
return;
}
}
static inline int
_o_array_compare_slots (const o_array_slot_t *slot1,
const o_array_slot_t *slot2)
{
if (slot1 == slot2)
return 0;
if (*slot1 == 0)
return 1;
if (*slot2 == 0)
return -1;
if ((*slot1)->index < (*slot2)->index)
return -1;
else if ((*slot1)->index > (*slot2)->index)
return 1;
else
return 0;
}
typedef int (*qsort_compare_func_t) (const void *, const void *);
static inline void
_o_array_make_sorted_slots (o_array_t *array)
{
o_array_slot_t *new_slots;
/* If there're already some sorted slots, then they're valid, and
* we're done. */
if (array->sorted_slots != 0)
return;
/* Make some new slots. */
new_slots = _o_array_new_slots (array, array->slot_count);
/* Copy the pointers to buckets into the new slots. */
memcpy (new_slots, array->slots, (array->slot_count
* sizeof (o_array_slot_t)));
/* Sort the new slots. */
qsort (new_slots, array->slot_count, sizeof (o_array_slot_t),
(qsort_compare_func_t) _o_array_compare_slots);
/* Put the newly sorted slots in the `sorted_slots' element of the
* array structure. */
array->sorted_slots = new_slots;
return;
}
static inline o_array_bucket_t *
_o_array_enumerator_next_bucket (o_array_enumerator_t *enumerator)
{
if (enumerator->is_sorted)
{
if (enumerator->is_ascending)
{
if (enumerator->array->sorted_slots == 0)
return 0;
if (enumerator->index < enumerator->array->element_count)
{
o_array_bucket_t *bucket;
bucket = enumerator->array->sorted_slots[enumerator->index];
++(enumerator->index);
return bucket;
}
else
return 0;
}
else
{
if (enumerator->array->sorted_slots == 0)
return 0;
if (enumerator->index > 0)
{
o_array_bucket_t *bucket;
--(enumerator->index);
bucket = enumerator->array->sorted_slots[enumerator->index];
return bucket;
}
else
return 0;
}
}
else
{
o_array_bucket_t *bucket;
if (enumerator->array->slots == 0)
return 0;
for (bucket = 0;
(enumerator->index < enumerator->array->slot_count
&& bucket == 0);
++(enumerator->index))
{
bucket = enumerator->array->slots[enumerator->index];
}
return bucket;
}
}
/** Statistics **/
size_t
o_array_count(o_array_t *array)
{
return array->element_count;
}
size_t
o_array_capacity (o_array_t *array)
{
return array->slot_count;
}
int
o_array_check(o_array_t *array)
{
/* FIXME: Code this. */
return 0;
}
int
o_array_is_empty(o_array_t *array)
{
return o_array_count (array) != 0;
}
/** Emptying **/
void
o_array_empty(o_array_t *array)
{
size_t c;
/* Just empty each slot out, one by one. */
for (c = 0; c < array->slot_count; ++c)
_o_array_empty_slot (array, array->slots + c);
return;
}
/** Creating **/
o_array_t *
o_array_alloc_with_zone(NSZone *zone)
{
o_array_t *array;
/* Get a new array. */
array = _o_array_alloc_with_zone(zone);
return array;
}
o_array_t *
o_array_alloc(void)
{
return o_array_alloc_with_zone(0);
}
o_array_t *
o_array_with_zone(NSZone *zone)
{
return o_array_init(o_array_alloc_with_zone(zone));
}
o_array_t *
o_array_with_zone_with_callbacks(NSZone *zone,
o_callbacks_t callbacks)
{
return o_array_init_with_callbacks(o_array_alloc_with_zone(zone),
callbacks);
}
o_array_t *
o_array_with_callbacks(o_callbacks_t callbacks)
{
return o_array_init_with_callbacks(o_array_alloc(), callbacks);
}
o_array_t *
o_array_of_char_p(void)
{
return o_array_with_callbacks(o_callbacks_for_char_p);
}
o_array_t *
o_array_of_non_owned_void_p(void)
{
return o_array_with_callbacks(o_callbacks_for_non_owned_void_p);
}
o_array_t *
o_array_of_owned_void_p(void)
{
return o_array_with_callbacks(o_callbacks_for_owned_void_p);
}
o_array_t *
o_array_of_int(void)
{
return o_array_with_callbacks(o_callbacks_for_int);
}
o_array_t *
o_array_of_id(void)
{
return o_array_with_callbacks(o_callbacks_for_id);
}
/** Initializing **/
o_array_t *
o_array_init_with_callbacks(o_array_t *array,
o_callbacks_t callbacks)
{
if (array != 0)
{
/* The default capacity is 15. */
size_t capacity = 15;
/* Record the element callbacks. */
array->callbacks = o_callbacks_standardize(callbacks);
/* Initialize ARRAY's information. */
array->element_count = 0;
array->slot_count = capacity + 1;
/* Make some new slots. */
array->slots = _o_array_new_slots(array, capacity + 1);
/* Get the sorted slots ready for later use. */
array->sorted_slots = 0;
}
return array;
}
o_array_t *
o_array_init (o_array_t *array)
{
return o_array_init_with_callbacks (array,
o_callbacks_standard());
}
o_array_t *
o_array_init_from_array (o_array_t *array, o_array_t *old_array)
{
o_array_enumerator_t enumerator;
size_t index;
const void *element;
/* Initialize ARRAY in the usual way. */
o_array_init_with_callbacks (array,
o_array_element_callbacks (old_array));
/* Get an enumerator for OLD_ARRAY. */
enumerator = o_array_enumerator (old_array);
/* Step through OLD_ARRAY's elements, putting them at the proper
* index in ARRAY. */
while (o_array_enumerator_next_index_and_element (&enumerator,
&index, &element))
{
o_array_at_index_put_element (array, index, element);
}
return array;
}
/** Destroying **/
void
o_array_dealloc(o_array_t *array)
{
if (array != 0)
{
/* Empty out ARRAY. */
o_array_empty (array);
/* Free up its slots. */
_o_array_free_slots (array, array->slots);
/* FIXME: What about ARRAY's sorted slots? */
/* Free up ARRAY itself. */
_o_array_dealloc (array);
}
return;
}
/** Searching **/
const void *
o_array_element_at_index (o_array_t *array, size_t index)
{
o_array_bucket_t *bucket = _o_array_bucket_for_index (array, index);
if (bucket != 0)
return bucket->element;
else
/* If `bucket' is 0, then the requested index is unused. */
/* There's no bucket, so... */
return o_array_not_an_element_marker (array);
}
size_t
o_array_index_of_element (o_array_t *array, const void *element)
{
size_t i;
for (i = 0; i < array->slot_count; ++i)
{
o_array_bucket_t *bucket = array->slots[i];
if (bucket != 0)
if (o_is_equal (o_array_element_callbacks (array),
bucket->element,
element,
array))
return bucket->index;
}
return i;
}
int
o_array_contains_element (o_array_t *array, const void *element)
{
/* Note that this search is quite inefficient. */
return o_array_index_of_element (array, element) < (array->slot_count);
}
const void **
o_array_all_elements (o_array_t *array)
{
o_array_enumerator_t enumerator;
const void **elements;
size_t count, i;
count = o_array_count (array);
/* Set aside space to hold the elements. */
elements = (const void **)NSZoneCalloc(o_array_zone(array),
count + 1,
sizeof(const void *));
enumerator = o_array_enumerator(array);
for (i = 0; i < count; ++i)
o_array_enumerator_next_element (&enumerator, elements + i);
elements[i] = o_array_not_an_element_marker(array);
/* We're done, so heave it back. */
return elements;
}
const void **
o_array_all_elements_ascending (o_array_t *array)
{
o_array_enumerator_t enumerator;
const void **elements;
size_t count, i;
count = o_array_count (array);
/* Set aside space to hold the elements. */
elements = (const void **)NSZoneCalloc(o_array_zone(array),
count + 1,
sizeof(const void *));
enumerator = o_array_ascending_enumerator (array);
for (i = 0; i < count; ++i)
o_array_enumerator_next_element (&enumerator, elements + i);
elements[i] = o_array_not_an_element_marker (array);
/* We're done, so heave it back. */
return elements;
}
const void **
o_array_all_elements_descending (o_array_t *array)
{
o_array_enumerator_t enumerator;
const void **elements;
size_t count, i;
count = o_array_count (array);
/* Set aside space to hold the elements. */
elements = (const void **)NSZoneCalloc(o_array_zone(array),
count + 1,
sizeof(const void *));
enumerator = o_array_descending_enumerator (array);
for (i = 0; i < count; ++i)
o_array_enumerator_next_element (&enumerator, elements + i);
elements[i] = o_array_not_an_element_marker (array);
/* We're done, so heave it back. */
return elements;
}
/** Removing **/
void
o_array_remove_element_at_index (o_array_t *array, size_t index)
{
o_array_bucket_t *bucket;
/* Get the bucket that might be there. */
bucket = _o_array_bucket_for_index (array, index);
/* If there's a bucket at the index, then we empty its slot out. */
if (bucket != 0)
_o_array_empty_slot (array, _o_array_slot_for_index (array, index));
/* Finally, we return. */
return;
}
void
o_array_remove_element_known_present (o_array_t *array,
const void *element)
{
o_array_remove_element_at_index (array,
o_array_index_of_element (array,
element));
return;
}
void
o_array_remove_element (o_array_t *array, const void *element)
{
if (o_array_contains_element (array, element))
o_array_remove_element_known_present (array, element);
return;
}
/** Adding **/
const void *
o_array_at_index_put_element (o_array_t *array,
size_t index,
const void *element)
{
o_array_bucket_t *bucket;
/* Clean out anything that's already there. */
o_array_remove_element_at_index (array, index);
/* Make a bucket for our information. */
bucket = _o_array_new_bucket (array, index, element);
/* Put our bucket in the array. */
_o_array_insert_bucket (array, bucket);
return element;
}
/** Enumerating **/
o_array_enumerator_t
o_array_ascending_enumerator (o_array_t *array)
{
o_array_enumerator_t enumerator;
enumerator.array = array;
enumerator.is_sorted = 1;
enumerator.is_ascending = 1;
enumerator.index = 0;
_o_array_make_sorted_slots (array);
return enumerator;
}
o_array_enumerator_t
o_array_descending_enumerator (o_array_t *array)
{
o_array_enumerator_t enumerator;
enumerator.array = array;
enumerator.is_sorted = 1;
enumerator.is_ascending = 0;
/* The `+ 1' is so that we have `0' as a known ending condition.
* See `_o_array_enumerator_next_bucket()'. */
enumerator.index = array->element_count + 1;
_o_array_make_sorted_slots (array);
return enumerator;
}
o_array_enumerator_t
o_array_enumerator (o_array_t *array)
{
o_array_enumerator_t enumerator;
enumerator.array = array;
enumerator.is_sorted = 0;
enumerator.is_ascending = 0;
enumerator.index = 0;
return enumerator;
}
int
o_array_enumerator_next_index_and_element (o_array_enumerator_t * enumerator,
size_t * index,
const void **element)
{
o_array_bucket_t *bucket;
bucket = _o_array_enumerator_next_bucket (enumerator);
if (bucket != 0)
{
if (element != 0)
*element = bucket->element;
if (index != 0)
*index = bucket->index;
return 1;
}
else
{
if (element != 0)
*element = o_array_not_an_element_marker (enumerator->array);
if (index != 0)
*index = 0;
return 0;
}
}
int
o_array_enumerator_next_element (o_array_enumerator_t * enumerator,
const void **element)
{
return o_array_enumerator_next_index_and_element (enumerator,
0,
element);
}
int
o_array_enumerator_next_index (o_array_enumerator_t * enumerator,
size_t * index)
{
return o_array_enumerator_next_index_and_element (enumerator,
index,
0);
}
/** Comparing **/
int
o_array_is_equal_to_array (o_array_t *array1, o_array_t *array2)
{
size_t a, b;
const void *m, *n;
o_array_enumerator_t e, f;
a = o_array_count (array1);
b = o_array_count (array2);
if (a < b)
return (b - a);
if (a > b)
return (a - b);
/* Get ascending enumerators for each of the two arrays. */
e = o_array_ascending_enumerator (array1);
e = o_array_ascending_enumerator (array1);
while (o_array_enumerator_next_index_and_element (&e, &a, &m)
&& o_array_enumerator_next_index_and_element (&f, &b, &n))
{
int c, d;
if (a < b)
return (b - a);
if (a > b)
return (a - b);
c = o_compare (o_array_element_callbacks (array1), m, n, array1);
if (c != 0)
return c;
d = o_compare (o_array_element_callbacks (array2), n, m, array2);
if (d != 0)
return d;
}
return 0;
}
/** Mapping **/
o_array_t *
o_array_map_elements(o_array_t *array,
const void *(*fcn) (const void *, const void *),
const void *user_data)
{
/* FIXME: Code this. */
return array;
}
/** Miscellaneous **/
o_hash_t *
o_hash_init_from_array (o_hash_t * hash, o_array_t *array)
{
o_array_enumerator_t enumerator;
const void *element;
/* NOTE: If ARRAY contains multiple elements of the same equivalence
* class, it is indeterminate which will end up in HASH. This
* shouldn't matter, though. */
enumerator = o_array_enumerator (array);
/* Just walk through ARRAY's elements and add them to HASH. */
while (o_array_enumerator_next_element (&enumerator, &element))
o_hash_add_element (hash, element);
return hash;
}
// o_chash_t *
// o_chash_init_from_array (o_chash_t * chash, o_array_t *array)
// {
// o_array_enumerator_t enumerator;
// const void *element;
//
// /* NOTE: If ARRAY contains multiple elements of the same equivalence
// * class, it is indeterminate which will end up in CHASH. This
// * shouldn't matter, though. */
// enumerator = o_array_enumerator (array);
//
// /* Just walk through ARRAY's elements and add them to CHASH. */
// while (o_array_enumerator_next_element (&enumerator, &element))
// o_chash_add_element (chash, element);
//
// return chash;
// }

File diff suppressed because it is too large Load diff

View file

@ -1,906 +0,0 @@
/* A (pretty good) list implementation.
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Tue Sep 5 17:23:50 EDT 1995
* Updated: Wed Mar 20 20:48:39 EST 1996
* Serial: 96.03.20.04
*
* This file is part of the Gnustep Base Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/**** Included Headers *******************************************************/
#include <Foundation/NSZone.h>
#include <gnustep/base/callbacks.h>
#include <gnustep/base/list.h>
#include <gnustep/base/hash.h>
/**** Function Implementations ***********************************************/
/** Background functions **/
static inline void
_o_list_remove_node_from_its_list (o_list_node_t * node)
{
if (node->list->first_node == node)
node->list->first_node = node->next_in_list;
if (node->list->last_node == node)
node->list->last_node = node->prev_in_list;
if (node->next_in_list != 0)
node->next_in_list->prev_in_list = node->prev_in_list;
if (node->prev_in_list != 0)
node->prev_in_list->next_in_list = node->next_in_list;
node->list->node_count -= 1;
node->list->element_count -= 1;
return;
}
static inline o_list_node_t *
_o_list_new_node (o_list_t *list, const void *element)
{
o_list_node_t *node;
node = NSZoneMalloc(o_list_zone(list), sizeof(o_list_node_t));
if (node != 0)
{
node->list = list;
node->next_in_list = 0;
node->prev_in_list = 0;
o_retain (o_list_element_callbacks (list), element, list);
node->element = element;
}
return node;
}
void
_o_list_free_node (o_list_t *list, o_list_node_t * node)
{
o_release (o_list_element_callbacks (node->list),
(void*)node->element,
node->list);
NSZoneFree(o_list_zone(list), node);
return;
}
static inline o_list_node_t *
_o_list_nth_node (o_list_t *list, long int n)
{
o_list_node_t *node;
if (n < 0)
{
node = list->last_node;
++n;
while (node != 0 && n != 0)
{
node = node->prev_in_list;
++n;
}
}
else
/* (n >= 0) */
{
node = list->first_node;
while (node != 0 && n != 0)
{
node = node->next_in_list;
--n;
}
}
return node;
}
static inline o_list_node_t *
_o_list_nth_node_for_element (o_list_t *list,
long int n,
const void *element)
{
o_list_node_t *node;
if (n < 0)
{
node = list->last_node;
++n;
while (node != 0 && n != 0)
{
if (o_is_equal (o_list_element_callbacks (list), element, node->element, list))
++n;
if (n != 0)
node = node->prev_in_list;
}
}
else
{
node = list->first_node;
while (node != 0 && n != 0)
{
if (o_is_equal (o_list_element_callbacks (list), element, node->element, list))
--n;
if (n != 0)
node = node->next_in_list;
}
}
return node;
}
static inline o_list_node_t *
_o_list_enumerator_next_node (o_list_enumerator_t *enumerator)
{
o_list_node_t *node;
/* Remember ENUMERATOR's current node. */
node = enumerator->node;
/* If NODE is a real node, then we need to increment ENUMERATOR's
* current node to the next node in ENUMERATOR's list. */
if (node != 0)
{
if (enumerator->forward)
enumerator->node = enumerator->node->next_in_list;
else /* (!enumerator->forward) */
enumerator->node = enumerator->node->prev_in_list;
}
/* Send back NODE. */
return node;
}
/** Gathering statistics **/
size_t
o_list_count (o_list_t *list)
{
return list->element_count;
}
size_t
o_list_capacity (o_list_t *list)
{
return list->element_count;
}
int
o_list_check (o_list_t *list)
{
return 0;
}
int
o_list_contains_element (o_list_t *list, const void *element)
{
o_list_enumerator_t enumerator;
const void *member;
o_list_enumerator (list);
while (o_list_enumerator_next_element (&enumerator, &member))
if (o_compare (o_list_element_callbacks (list), element, member, list))
return 1;
return 0;
}
int
o_list_is_empty (o_list_t *list)
{
return o_list_count (list) == 0;
}
/** Enumerating **/
o_list_enumerator_t
o_list_enumerator (o_list_t *list)
{
return o_list_forward_enumerator (list);
}
o_list_enumerator_t
o_list_forward_enumerator (o_list_t *list)
{
o_list_enumerator_t enumerator;
/* Make sure ENUMERATOR knows its list. */
enumerator.list = list;
/* Start ENUMERATOR at LIST's first node. */
enumerator.node = list->first_node;
/* ENUMERATOR walks forward. */
enumerator.forward = 1;
return enumerator;
}
o_list_enumerator_t
o_list_reverse_enumerator (o_list_t *list)
{
o_list_enumerator_t enumerator;
/* Make sure ENUMERATOR knows its list. */
enumerator.list = list;
/* Start ENUMERATOR at LIST's first node. */
enumerator.node = list->last_node;
/* ENUMERATOR walks backward. */
enumerator.forward = 0;
return enumerator;
}
int
o_list_enumerator_next_element (o_list_enumerator_t *enumerator,
const void **element)
{
o_list_node_t *node;
/* Try and get the next node in the enumeration represented by
* ENUMERATOR. */
node = _o_list_enumerator_next_node (enumerator);
if (node != 0)
{
/* If NODE is real, then return the element it contains. */
if (element != 0)
*element = node->element;
/* Indicate that the enumeration continues. */
return 1;
}
else
{
/* If NODE isn't real, then we return the ``bogus'' indicator. */
if (element != 0)
*element = o_list_not_an_element_marker (enumerator->list);
/* Indicate that the enumeration is over. */
return 0;
}
}
/** Searching **/
const void *
o_list_element (o_list_t *list, const void *element)
{
o_list_node_t *node;
node = _o_list_nth_node_for_element (list, 0, element);
if (node != 0)
return node->element;
else
return o_list_not_an_element_marker (list);
}
const void *
o_list_nth_element (o_list_t *list, long int n)
{
o_list_node_t *node;
node = _o_list_nth_node (list, n);
if (node != 0)
return node->element;
else
return o_list_not_an_element_marker (list);
}
const void *
o_list_first_element (o_list_t *list)
{
if (list->first_node != 0)
return list->first_node->element;
else
return o_list_not_an_element_marker (list);
}
const void *
o_list_last_element (o_list_t *list)
{
if (list->last_node != 0)
return list->last_node->element;
else
return o_list_not_an_element_marker (list);
}
/** Obtaining elements **/
const void **
o_list_all_elements (o_list_t *list)
{
o_list_enumerator_t enumerator;
const void **array;
size_t i;
array = NSZoneCalloc(o_list_zone(list),
o_list_count(list) + 1,
sizeof(const void *));
for (i = 0; o_list_enumerator_next_element (&enumerator, array + i); ++i);
return array;
}
/** Adding elements **/
const void *
o_list_append_element (o_list_t *list, const void *element)
{
return o_list_at_index_insert_element (list, -1, element);
}
const void *
o_list_append_element_if_absent (o_list_t *list, const void *element)
{
return o_list_at_index_insert_element_if_absent (list, -1, element);
}
const void *
o_list_prepend_element (o_list_t *list, const void *element)
{
return o_list_at_index_insert_element (list, 0, element);
}
const void *
o_list_prepend_element_if_absent (o_list_t *list, const void *element)
{
return o_list_at_index_insert_element_if_absent (list, 0, element);
}
const void *
o_list_at_index_insert_element(o_list_t *list,
long int n,
const void *element)
{
o_list_node_t *anode, *bnode, *new_node, *node;
node = _o_list_nth_node (list, n);
new_node = _o_list_new_node (list, element);
if (new_node == 0)
/* FIXME: Make this a *little* more graceful, for goodness' sake! */
abort();
if (n < 0)
{
if (node == 0)
{
anode = 0;
bnode = list->first_node;
}
else
/* (node != 0) */
{
anode = node;
bnode = node->next_in_list;
}
}
else
/* (n >= 0) */
{
if (node == 0)
{
anode = list->last_node;
bnode = 0;
}
else
/* (node != 0) */
{
anode = node->prev_in_list;
bnode = node;
}
}
new_node->prev_in_list = anode;
new_node->next_in_list = bnode;
if (anode != 0)
anode->next_in_list = new_node;
if (bnode != 0)
bnode->prev_in_list = new_node;
if (list->last_node == anode)
list->last_node = new_node;
if (list->first_node == bnode)
list->first_node = new_node;
list->node_count += 1;
list->element_count += 1;
return new_node->element;
}
const void *
o_list_at_index_insert_element_if_absent (o_list_t *list,
long int n,
const void *element)
{
if (!o_list_contains_element (list, element))
return o_list_at_index_insert_element (list, n, element);
else
return o_list_element (list, element);
}
/** Removing elements **/
void
o_list_remove_nth_occurrance_of_element (o_list_t *list,
long int n,
const void *element)
{
o_list_node_t *node;
node = _o_list_nth_node_for_element (list, n, element);
if (node != 0)
{
_o_list_remove_node_from_its_list (node);
_o_list_free_node (list, node);
}
return;
}
void
o_list_remove_element (o_list_t *list, const void *element)
{
o_list_remove_nth_occurrance_of_element (list, 0, element);
return;
}
void
o_list_remove_nth_element (o_list_t *list, long int n)
{
o_list_node_t *node;
node = _o_list_nth_node (list, n);
if (node != 0)
{
_o_list_remove_node_from_its_list (node);
_o_list_free_node (list, node);
}
return;
}
void
o_list_remove_first_element (o_list_t *list)
{
o_list_remove_nth_element (list, 0);
return;
}
void
o_list_remove_last_element (o_list_t *list)
{
o_list_remove_nth_element (list, -1);
return;
}
/** Emptying **/
void
o_list_empty (o_list_t *list)
{
o_list_enumerator_t enumerator;
o_list_node_t *node;
enumerator = o_list_enumerator (list);
while ((node = _o_list_enumerator_next_node (&enumerator)) != 0)
{
_o_list_remove_node_from_its_list (node);
_o_list_free_node (list, node);
}
return;
}
/** Replacing **/
void
o_list_replace_nth_occurrance_of_element (o_list_t *list,
long int n,
const void *old_element,
const void *new_element)
{
o_list_node_t *node;
node = _o_list_nth_node_for_element (list, n, old_element);
if (node != 0)
{
o_retain (o_list_element_callbacks (list), new_element, list);
o_release (o_list_element_callbacks (list),
(void*)node->element,
list);
node->element = new_element;
}
return;
}
void
o_list_replace_element (o_list_t *list,
const void *old_element,
const void *new_element)
{
o_list_replace_nth_occurrance_of_element (list, 0, old_element, new_element);
return;
}
void
o_list_replace_nth_element (o_list_t *list,
long int n,
const void *new_element)
{
o_list_node_t *node;
node = _o_list_nth_node (list, n);
if (node != 0)
{
o_retain (o_list_element_callbacks (list), new_element, list);
o_release (o_list_element_callbacks (list),
(void*)node->element,
list);
node->element = new_element;
}
return;
}
void
o_list_replace_first_element (o_list_t *list,
const void *new_element)
{
o_list_replace_nth_element (list, 0, new_element);
return;
}
void
o_list_replace_last_element (o_list_t *list,
const void *new_element)
{
o_list_replace_nth_element (list, -1, new_element);
return;
}
/** Creating **/
o_list_t *
o_list_alloc_with_zone (NSZone *zone)
{
o_list_t *list;
list = _o_list_alloc_with_zone(zone);
return list;
}
o_list_t *
o_list_alloc (void)
{
return o_list_alloc_with_zone (0);
}
o_list_t *
o_list (void)
{
return o_list_init (o_list_alloc ());
}
o_list_t *
o_list_with_zone (NSZone *zone)
{
return o_list_init (o_list_alloc_with_zone(zone));
}
o_list_t *
o_list_with_zone_with_callbacks (NSZone *zone,
o_callbacks_t callbacks)
{
return o_list_init_with_callbacks(o_list_alloc_with_zone(zone),
callbacks);
}
o_list_t *
o_list_with_callbacks (o_callbacks_t callbacks)
{
return o_list_init_with_callbacks (o_list_alloc (), callbacks);
}
o_list_t *
o_list_of_char_p (void)
{
return o_list_with_callbacks (o_callbacks_for_char_p);
}
o_list_t *
o_list_of_int (void)
{
return o_list_with_callbacks (o_callbacks_for_int);
}
o_list_t *
o_list_of_non_owned_void_p (void)
{
return o_list_with_callbacks (o_callbacks_for_non_owned_void_p);
}
o_list_t *
o_list_of_owned_void_p (void)
{
return o_list_with_callbacks (o_callbacks_for_owned_void_p);
}
o_list_t *
o_list_of_id (void)
{
return o_list_with_callbacks (o_callbacks_for_id);
}
/** Initializing **/
o_list_t *
o_list_init (o_list_t *list)
{
return o_list_init_with_callbacks (list, o_callbacks_standard());
}
o_list_t *
o_list_init_with_callbacks (o_list_t *list, o_callbacks_t callbacks)
{
if (list != 0)
{
list->callbacks = callbacks;
list->element_count = 0;
list->node_count = 0;
list->first_node = 0;
list->last_node = 0;
}
return list;
}
o_list_t *
o_list_init_from_list (o_list_t *list, o_list_t *old_list)
{
o_list_enumerator_t enumerator;
const void *element;
if (list != 0)
{
list->callbacks = o_list_element_callbacks (old_list);
list->element_count = 0;
list->node_count = 0;
list->first_node = 0;
list->last_node = 0;
if (old_list != 0)
{
/* Get a forward enumerator for OLD_LIST. */
enumerator = o_list_forward_enumerator (old_list);
/* Walk from the beginning to the end of OLD_LIST, and add each
* element to the end of LIST. */
while (o_list_enumerator_next_element (&enumerator, &element))
o_list_at_index_insert_element (list, -1, element);
}
}
return list;
}
/** Destroying **/
void
o_list_dealloc (o_list_t *list)
{
/* Empty LIST out. */
o_list_empty (list);
/* Get rid of LIST. */
_o_list_dealloc (list);
return;
}
/** Comparing **/
int
o_list_is_equal_to_list(o_list_t *list, o_list_t *other_list)
{
/* FIXME: Code this. */
return 0;
}
/** Concatenating **/
o_list_t *
o_list_append_list (o_list_t *base_list, o_list_t *suffix_list)
{
return o_list_at_index_insert_list (base_list, -1, suffix_list);
}
o_list_t *
o_list_prepend_list (o_list_t *base_list, o_list_t *prefix_list)
{
return o_list_at_index_insert_list (base_list, 0, prefix_list);
}
/* FIXME: I was lazy when I wrote this next one. It can easily be
* sped up. Do it. */
o_list_t *
o_list_at_index_insert_list(o_list_t *base_list,
long int n,
o_list_t *infix_list)
{
o_list_enumerator_t enumerator;
const void *element;
if (n < 0)
enumerator = o_list_forward_enumerator(infix_list);
else /* (n >= 0) */
enumerator = o_list_reverse_enumerator(infix_list);
while (o_list_enumerator_next_element(&enumerator, &element))
o_list_at_index_insert_element(base_list, n, element);
return base_list;
}
/** Copying **/
o_list_t *
o_list_copy (o_list_t *old_list)
{
return o_list_copy_with_zone (old_list, 0);
}
o_list_t *
o_list_copy_with_zone (o_list_t *old_list, NSZone *zone)
{
o_list_t *list;
/* Allocate a new (low-level) copy of OLD_LIST. */
list = _o_list_copy_with_zone(old_list, zone);
/* Fill it in. */
return o_list_init_from_list (list, old_list);
}
/** Mapping **/
o_list_t *
o_list_map_elements(o_list_t *list,
const void *(*fcn)(const void *, void *),
void *user_data)
{
o_list_enumerator_t enumerator;
o_list_node_t *node;
o_callbacks_t callbacks;
callbacks = o_list_element_callbacks(list);
enumerator = o_list_enumerator (list);
while ((node = _o_list_enumerator_next_node (&enumerator)) != 0)
{
const void *element;
element = (*fcn)(node->element, user_data);
o_retain (callbacks, element, list);
o_release (callbacks, (void *)(node->element), list);
node->element = element;
}
return list;
}
/** Creating other collections from lists **/
o_hash_t *
o_hash_init_from_list (o_hash_t * hash, o_list_t *list)
{
if (hash != 0)
{
o_list_enumerator_t enumerator;
const void *element;
/* Make a note of the callbacks for HASH. */
hash->callbacks = o_list_element_callbacks (list);
/* Zero out the various counts. */
hash->node_count = 0;
hash->bucket_count = 0;
hash->element_count = 0;
/* Zero out the pointers. */
hash->first_node = 0;
hash->buckets = 0;
/* Resize HASH to the given CAPACITY. */
o_hash_resize (hash, o_list_capacity (list));
/* Get an element enumerator for LIST. */
enumerator = o_list_enumerator (list);
/* Add LIST's elements to HASH, one at a time. Note that if LIST
* contains multiple elements from the same equivalence class, it
* is indeterminate which will end up in HASH. But this shouldn't
* be a problem. */
while (o_list_enumerator_next_element (&enumerator, &element))
o_hash_add_element (hash, element);
}
/* Return the newly initialized HASH. */
return hash;
}
// o_chash_t *
// o_chash_init_from_list (o_chash_t * chash, o_list_t *list)
// {
// if (chash != 0)
// {
// o_list_enumerator_t enumerator;
// const void *element;
//
// /* Make a note of the callbacks for CHASH. */
// chash->callbacks = o_list_element_callbacks (list);
//
// /* Zero out the various counts. */
// chash->node_count = 0;
// chash->bucket_count = 0;
// chash->element_count = 0;
//
// /* Zero out the pointers. */
// chash->first_node = 0;
// chash->buckets = 0;
//
// /* Resize CHASH to the given CAPACITY. */
// o_chash_resize (chash, o_list_capacity (list));
//
// /* Get an element enumerator for LIST. */
// enumerator = o_list_enumerator (list);
//
// /* Add LIST's elements to CHASH, one at a time. Note that if LIST
// * contains multiple elements from the same equivalence class, it
// * is indeterminate which will end up in CHASH. But this shouldn't
// * be a problem. */
// while (o_list_enumerator_next_element (&enumerator, &element))
// o_chash_add_element (chash, element);
// }
//
// /* Return the newly initialized CHASH. */
// return chash;
// }

File diff suppressed because it is too large Load diff