1996-03-22 00:37:53 +00:00
|
|
|
/* 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
|
|
|
|
*
|
1996-05-12 00:56:10 +00:00
|
|
|
* This file is part of the GNUstep Base Library.
|
1996-03-22 00:37:53 +00:00
|
|
|
*
|
|
|
|
* 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
|
1999-09-09 02:56:20 +00:00
|
|
|
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/**** Included Headers *******************************************************/
|
|
|
|
|
1997-11-06 00:51:23 +00:00
|
|
|
#include <config.h>
|
1998-12-20 21:27:47 +00:00
|
|
|
#include <base/preface.h>
|
1996-03-22 00:37:53 +00:00
|
|
|
#include <Foundation/NSZone.h>
|
1998-12-20 21:27:47 +00:00
|
|
|
#include <base/o_cbs.h>
|
|
|
|
#include <base/o_array.h>
|
|
|
|
#include <base/o_hash.h>
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/**** Function Implementations ***********************************************/
|
|
|
|
|
|
|
|
/** Background functions **/
|
|
|
|
|
|
|
|
static inline size_t
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_fold_index(size_t index, size_t slot_count)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
return (slot_count ? (index % slot_count) : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_internal_index(o_array_t *array, size_t index)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return _o_array_fold_index (index, array->slot_count);
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
static inline o_array_slot_t *
|
|
|
|
_o_array_slot_for_index(o_array_t *array, size_t index)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return (array->slots + _o_array_internal_index (array, index));
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
static inline o_array_bucket_t *
|
|
|
|
_o_array_bucket_for_index (o_array_t *array, size_t index)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_slot_t *slot;
|
|
|
|
o_array_bucket_t *bucket;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* First, we translate the index into a bucket index to find our
|
|
|
|
* candidate for the bucket. */
|
1996-04-17 19:26:04 +00:00
|
|
|
slot = _o_array_slot_for_index (array, index);
|
1996-03-22 00:37:53 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
static inline o_array_bucket_t *
|
|
|
|
_o_array_new_bucket (o_array_t *array, size_t index, const void *element)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_bucket_t *bucket;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
bucket = (o_array_bucket_t *) NSZoneMalloc(o_array_zone(array),
|
|
|
|
sizeof(o_array_bucket_t));
|
1996-03-22 00:37:53 +00:00
|
|
|
if (bucket != 0)
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_retain(o_array_element_callbacks(array), element, array);
|
1996-03-22 00:37:53 +00:00
|
|
|
bucket->index = index;
|
|
|
|
bucket->element = element;
|
|
|
|
}
|
|
|
|
return bucket;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_free_bucket(o_array_t *array,
|
|
|
|
o_array_bucket_t *bucket)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
if (bucket != 0)
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_release(o_array_element_callbacks (array),
|
1996-03-22 00:37:53 +00:00
|
|
|
(void *)(bucket->element),
|
|
|
|
array);
|
1996-04-17 19:26:04 +00:00
|
|
|
NSZoneFree(o_array_zone(array), bucket);
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
static inline o_array_slot_t *
|
|
|
|
_o_array_new_slots(o_array_t *array, size_t slot_count)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return (o_array_slot_t *) NSZoneCalloc(o_array_zone(array),
|
1996-03-22 00:37:53 +00:00
|
|
|
slot_count,
|
1996-04-17 19:26:04 +00:00
|
|
|
sizeof(o_array_slot_t));
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_free_slots(o_array_t *array,
|
|
|
|
o_array_slot_t *slots)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
if (slots != 0)
|
1996-04-17 19:26:04 +00:00
|
|
|
NSZoneFree(o_array_zone(array), slots);
|
1996-03-22 00:37:53 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_empty_slot (o_array_t *array, o_array_slot_t * slot)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
if (*slot != 0)
|
|
|
|
{
|
|
|
|
/* Get rid of the bucket. */
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_free_bucket (array, *slot);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Mark the slot as empty. */
|
|
|
|
*slot = 0;
|
|
|
|
|
|
|
|
/* Keep the element count accurate */
|
|
|
|
--(array->element_count);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* And return. */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_insert_bucket(o_array_t *array,
|
|
|
|
o_array_bucket_t * bucket)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_slot_t *slot;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
slot = _o_array_slot_for_index (array, bucket->index);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* We're adding a bucket, so the current set of sorted slots is now
|
|
|
|
* invalidated. */
|
|
|
|
if (array->sorted_slots != 0)
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_free_slots (array, array->sorted_slots);
|
1996-03-22 00:37:53 +00:00
|
|
|
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. */
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_free_bucket (array, *slot);
|
1996-03-22 00:37:53 +00:00
|
|
|
*slot = bucket;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Now we get to fiddle around with things to make the world a
|
|
|
|
* better place... */
|
|
|
|
|
|
|
|
size_t new_slot_count;
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_slot_t *new_slots; /* This guy holds the buckets while we
|
1996-03-22 00:37:53 +00:00
|
|
|
* 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. */
|
1996-04-17 19:26:04 +00:00
|
|
|
new_slots = _o_array_new_slots (array, new_slot_count);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
if (new_slots == 0)
|
|
|
|
/* FIXME: Make this a *little* more friendly. */
|
|
|
|
abort();
|
|
|
|
|
|
|
|
/* Then we put the new bucket in the pile. */
|
1996-04-17 19:26:04 +00:00
|
|
|
new_slots[_o_array_fold_index (bucket->index,
|
1996-03-22 00:37:53 +00:00
|
|
|
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;
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
i = _o_array_fold_index (array->slots[d]->index,
|
1996-03-22 00:37:53 +00:00
|
|
|
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. */
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_free_slots (array, new_slots);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* 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)
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_free_slots (array, array->slots);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
array->slots = new_slots;
|
|
|
|
array->slot_count = new_slot_count;
|
|
|
|
++(array->element_count);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_compare_slots (const o_array_slot_t *slot1,
|
|
|
|
const o_array_slot_t *slot2)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
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
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_make_sorted_slots (o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_slot_t *new_slots;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* 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. */
|
1996-04-17 19:26:04 +00:00
|
|
|
new_slots = _o_array_new_slots (array, array->slot_count);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Copy the pointers to buckets into the new slots. */
|
|
|
|
memcpy (new_slots, array->slots, (array->slot_count
|
1996-04-17 19:26:04 +00:00
|
|
|
* sizeof (o_array_slot_t)));
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Sort the new slots. */
|
1996-04-17 19:26:04 +00:00
|
|
|
qsort (new_slots, array->slot_count, sizeof (o_array_slot_t),
|
|
|
|
(qsort_compare_func_t) _o_array_compare_slots);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Put the newly sorted slots in the `sorted_slots' element of the
|
|
|
|
* array structure. */
|
|
|
|
array->sorted_slots = new_slots;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
static inline o_array_bucket_t *
|
|
|
|
_o_array_enumerator_next_bucket (o_array_enumerator_t *enumerator)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
if (enumerator->is_sorted)
|
|
|
|
{
|
|
|
|
if (enumerator->is_ascending)
|
|
|
|
{
|
|
|
|
if (enumerator->array->sorted_slots == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (enumerator->index < enumerator->array->element_count)
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_bucket_t *bucket;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_bucket_t *bucket;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
--(enumerator->index);
|
|
|
|
bucket = enumerator->array->sorted_slots[enumerator->index];
|
|
|
|
return bucket;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_bucket_t *bucket;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
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
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_count(o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
return array->element_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_capacity (o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
return array->slot_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_check(o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
/* FIXME: Code this. */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_is_empty(o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_count (array) != 0;
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Emptying **/
|
|
|
|
|
|
|
|
void
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_empty(o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
size_t c;
|
|
|
|
|
|
|
|
/* Just empty each slot out, one by one. */
|
|
|
|
for (c = 0; c < array->slot_count; ++c)
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_empty_slot (array, array->slots + c);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Creating **/
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_alloc_with_zone(NSZone *zone)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *array;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Get a new array. */
|
1996-04-17 19:26:04 +00:00
|
|
|
array = _o_array_alloc_with_zone(zone);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_alloc(void)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1997-03-03 19:43:25 +00:00
|
|
|
return o_array_alloc_with_zone(NSDefaultMallocZone());
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_with_zone(NSZone *zone)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_init(o_array_alloc_with_zone(zone));
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_with_zone_with_callbacks(NSZone *zone,
|
|
|
|
o_callbacks_t callbacks)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_init_with_callbacks(o_array_alloc_with_zone(zone),
|
1996-03-22 00:37:53 +00:00
|
|
|
callbacks);
|
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_with_callbacks(o_callbacks_t callbacks)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_init_with_callbacks(o_array_alloc(), callbacks);
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_of_char_p(void)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_with_callbacks(o_callbacks_for_char_p);
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_of_non_owned_void_p(void)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_with_callbacks(o_callbacks_for_non_owned_void_p);
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_of_owned_void_p(void)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_with_callbacks(o_callbacks_for_owned_void_p);
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_of_int(void)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_with_callbacks(o_callbacks_for_int);
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_of_id(void)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_with_callbacks(o_callbacks_for_id);
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Initializing **/
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_init_with_callbacks(o_array_t *array,
|
|
|
|
o_callbacks_t callbacks)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
if (array != 0)
|
|
|
|
{
|
|
|
|
/* The default capacity is 15. */
|
|
|
|
size_t capacity = 15;
|
|
|
|
|
|
|
|
/* Record the element callbacks. */
|
1996-04-17 19:26:04 +00:00
|
|
|
array->callbacks = o_callbacks_standardize(callbacks);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Initialize ARRAY's information. */
|
|
|
|
array->element_count = 0;
|
|
|
|
array->slot_count = capacity + 1;
|
|
|
|
|
|
|
|
/* Make some new slots. */
|
1996-04-17 19:26:04 +00:00
|
|
|
array->slots = _o_array_new_slots(array, capacity + 1);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Get the sorted slots ready for later use. */
|
|
|
|
array->sorted_slots = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_init (o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_init_with_callbacks (array,
|
|
|
|
o_callbacks_standard());
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_init_from_array (o_array_t *array, o_array_t *old_array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_t enumerator;
|
1996-03-22 00:37:53 +00:00
|
|
|
size_t index;
|
|
|
|
const void *element;
|
|
|
|
|
|
|
|
/* Initialize ARRAY in the usual way. */
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_init_with_callbacks (array,
|
|
|
|
o_array_element_callbacks (old_array));
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Get an enumerator for OLD_ARRAY. */
|
1996-04-17 19:26:04 +00:00
|
|
|
enumerator = o_array_enumerator (old_array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Step through OLD_ARRAY's elements, putting them at the proper
|
|
|
|
* index in ARRAY. */
|
1996-04-17 19:26:04 +00:00
|
|
|
while (o_array_enumerator_next_index_and_element (&enumerator,
|
1996-03-22 00:37:53 +00:00
|
|
|
&index, &element))
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_at_index_put_element (array, index, element);
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Destroying **/
|
|
|
|
|
|
|
|
void
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_dealloc(o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
if (array != 0)
|
|
|
|
{
|
|
|
|
/* Empty out ARRAY. */
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_empty (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Free up its slots. */
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_free_slots (array, array->slots);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* FIXME: What about ARRAY's sorted slots? */
|
|
|
|
|
|
|
|
/* Free up ARRAY itself. */
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_dealloc (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Searching **/
|
|
|
|
|
|
|
|
const void *
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_element_at_index (o_array_t *array, size_t index)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_bucket_t *bucket = _o_array_bucket_for_index (array, index);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
if (bucket != 0)
|
|
|
|
return bucket->element;
|
|
|
|
else
|
|
|
|
/* If `bucket' is 0, then the requested index is unused. */
|
|
|
|
/* There's no bucket, so... */
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_not_an_element_marker (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_index_of_element (o_array_t *array, const void *element)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < array->slot_count; ++i)
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_bucket_t *bucket = array->slots[i];
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
if (bucket != 0)
|
1996-04-17 19:26:04 +00:00
|
|
|
if (o_is_equal (o_array_element_callbacks (array),
|
1996-03-22 00:37:53 +00:00
|
|
|
bucket->element,
|
|
|
|
element,
|
|
|
|
array))
|
|
|
|
return bucket->index;
|
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_contains_element (o_array_t *array, const void *element)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
/* Note that this search is quite inefficient. */
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_index_of_element (array, element) < (array->slot_count);
|
1996-03-22 00:37:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const void **
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_all_elements (o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_t enumerator;
|
1996-03-22 00:37:53 +00:00
|
|
|
const void **elements;
|
|
|
|
size_t count, i;
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
count = o_array_count (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Set aside space to hold the elements. */
|
1996-04-17 19:26:04 +00:00
|
|
|
elements = (const void **)NSZoneCalloc(o_array_zone(array),
|
1996-03-22 00:37:53 +00:00
|
|
|
count + 1,
|
|
|
|
sizeof(const void *));
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
enumerator = o_array_enumerator(array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
for (i = 0; i < count; ++i)
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_next_element (&enumerator, elements + i);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
elements[i] = o_array_not_an_element_marker(array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* We're done, so heave it back. */
|
|
|
|
return elements;
|
|
|
|
}
|
|
|
|
|
|
|
|
const void **
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_all_elements_ascending (o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_t enumerator;
|
1996-03-22 00:37:53 +00:00
|
|
|
const void **elements;
|
|
|
|
size_t count, i;
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
count = o_array_count (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Set aside space to hold the elements. */
|
1996-04-17 19:26:04 +00:00
|
|
|
elements = (const void **)NSZoneCalloc(o_array_zone(array),
|
1996-03-22 00:37:53 +00:00
|
|
|
count + 1,
|
|
|
|
sizeof(const void *));
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
enumerator = o_array_ascending_enumerator (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
for (i = 0; i < count; ++i)
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_next_element (&enumerator, elements + i);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
elements[i] = o_array_not_an_element_marker (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* We're done, so heave it back. */
|
|
|
|
return elements;
|
|
|
|
}
|
|
|
|
|
|
|
|
const void **
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_all_elements_descending (o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_t enumerator;
|
1996-03-22 00:37:53 +00:00
|
|
|
const void **elements;
|
|
|
|
size_t count, i;
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
count = o_array_count (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Set aside space to hold the elements. */
|
1996-04-17 19:26:04 +00:00
|
|
|
elements = (const void **)NSZoneCalloc(o_array_zone(array),
|
1996-03-22 00:37:53 +00:00
|
|
|
count + 1,
|
|
|
|
sizeof(const void *));
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
enumerator = o_array_descending_enumerator (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
for (i = 0; i < count; ++i)
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_next_element (&enumerator, elements + i);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
elements[i] = o_array_not_an_element_marker (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* We're done, so heave it back. */
|
|
|
|
return elements;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Removing **/
|
|
|
|
|
|
|
|
void
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_remove_element_at_index (o_array_t *array, size_t index)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_bucket_t *bucket;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Get the bucket that might be there. */
|
1996-04-17 19:26:04 +00:00
|
|
|
bucket = _o_array_bucket_for_index (array, index);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* If there's a bucket at the index, then we empty its slot out. */
|
|
|
|
if (bucket != 0)
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_empty_slot (array, _o_array_slot_for_index (array, index));
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Finally, we return. */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_remove_element_known_present (o_array_t *array,
|
1996-03-22 00:37:53 +00:00
|
|
|
const void *element)
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_remove_element_at_index (array,
|
|
|
|
o_array_index_of_element (array,
|
1996-03-22 00:37:53 +00:00
|
|
|
element));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_remove_element (o_array_t *array, const void *element)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
if (o_array_contains_element (array, element))
|
|
|
|
o_array_remove_element_known_present (array, element);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Adding **/
|
|
|
|
|
|
|
|
const void *
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_at_index_put_element (o_array_t *array,
|
1996-03-22 00:37:53 +00:00
|
|
|
size_t index,
|
|
|
|
const void *element)
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_bucket_t *bucket;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Clean out anything that's already there. */
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_remove_element_at_index (array, index);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Make a bucket for our information. */
|
1996-04-17 19:26:04 +00:00
|
|
|
bucket = _o_array_new_bucket (array, index, element);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Put our bucket in the array. */
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_insert_bucket (array, bucket);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
return element;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Enumerating **/
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_t
|
|
|
|
o_array_ascending_enumerator (o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_t enumerator;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
enumerator.array = array;
|
|
|
|
enumerator.is_sorted = 1;
|
|
|
|
enumerator.is_ascending = 1;
|
|
|
|
enumerator.index = 0;
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_make_sorted_slots (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
return enumerator;
|
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_t
|
|
|
|
o_array_descending_enumerator (o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_t enumerator;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
enumerator.array = array;
|
|
|
|
enumerator.is_sorted = 1;
|
|
|
|
enumerator.is_ascending = 0;
|
|
|
|
/* The `+ 1' is so that we have `0' as a known ending condition.
|
1996-04-17 19:26:04 +00:00
|
|
|
* See `_o_array_enumerator_next_bucket()'. */
|
1996-03-22 00:37:53 +00:00
|
|
|
enumerator.index = array->element_count + 1;
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
_o_array_make_sorted_slots (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
return enumerator;
|
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_t
|
|
|
|
o_array_enumerator (o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_t enumerator;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
enumerator.array = array;
|
|
|
|
enumerator.is_sorted = 0;
|
|
|
|
enumerator.is_ascending = 0;
|
|
|
|
enumerator.index = 0;
|
|
|
|
|
|
|
|
return enumerator;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_next_index_and_element (o_array_enumerator_t * enumerator,
|
1996-03-22 00:37:53 +00:00
|
|
|
size_t * index,
|
|
|
|
const void **element)
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_bucket_t *bucket;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
bucket = _o_array_enumerator_next_bucket (enumerator);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
if (bucket != 0)
|
|
|
|
{
|
|
|
|
if (element != 0)
|
|
|
|
*element = bucket->element;
|
|
|
|
if (index != 0)
|
|
|
|
*index = bucket->index;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (element != 0)
|
1996-04-17 19:26:04 +00:00
|
|
|
*element = o_array_not_an_element_marker (enumerator->array);
|
1996-03-22 00:37:53 +00:00
|
|
|
if (index != 0)
|
|
|
|
*index = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_next_element (o_array_enumerator_t * enumerator,
|
1996-03-22 00:37:53 +00:00
|
|
|
const void **element)
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_enumerator_next_index_and_element (enumerator,
|
1996-03-22 00:37:53 +00:00
|
|
|
0,
|
|
|
|
element);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_next_index (o_array_enumerator_t * enumerator,
|
1996-03-22 00:37:53 +00:00
|
|
|
size_t * index)
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_array_enumerator_next_index_and_element (enumerator,
|
1996-03-22 00:37:53 +00:00
|
|
|
index,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Comparing **/
|
|
|
|
|
|
|
|
int
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_is_equal_to_array (o_array_t *array1, o_array_t *array2)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
size_t a, b;
|
|
|
|
const void *m, *n;
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_t e, f;
|
1996-03-22 00:37:53 +00:00
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
a = o_array_count (array1);
|
|
|
|
b = o_array_count (array2);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
if (a < b)
|
|
|
|
return (b - a);
|
|
|
|
if (a > b)
|
|
|
|
return (a - b);
|
|
|
|
|
|
|
|
/* Get ascending enumerators for each of the two arrays. */
|
1996-04-17 19:26:04 +00:00
|
|
|
e = o_array_ascending_enumerator (array1);
|
|
|
|
e = o_array_ascending_enumerator (array1);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
while (o_array_enumerator_next_index_and_element (&e, &a, &m)
|
|
|
|
&& o_array_enumerator_next_index_and_element (&f, &b, &n))
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
|
|
|
int c, d;
|
|
|
|
|
|
|
|
if (a < b)
|
|
|
|
return (b - a);
|
|
|
|
if (a > b)
|
|
|
|
return (a - b);
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
c = o_compare (o_array_element_callbacks (array1), m, n, array1);
|
1996-03-22 00:37:53 +00:00
|
|
|
if (c != 0)
|
|
|
|
return c;
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
d = o_compare (o_array_element_callbacks (array2), n, m, array2);
|
1996-03-22 00:37:53 +00:00
|
|
|
if (d != 0)
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Mapping **/
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_t *
|
|
|
|
o_array_map_elements(o_array_t *array,
|
1996-03-22 00:37:53 +00:00
|
|
|
const void *(*fcn) (const void *, const void *),
|
|
|
|
const void *user_data)
|
|
|
|
{
|
|
|
|
/* FIXME: Code this. */
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Miscellaneous **/
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
o_hash_t *
|
|
|
|
o_hash_init_from_array (o_hash_t * hash, o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_array_enumerator_t enumerator;
|
1996-03-22 00:37:53 +00:00
|
|
|
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. */
|
1996-04-17 19:26:04 +00:00
|
|
|
enumerator = o_array_enumerator (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
/* Just walk through ARRAY's elements and add them to HASH. */
|
1996-04-17 19:26:04 +00:00
|
|
|
while (o_array_enumerator_next_element (&enumerator, &element))
|
|
|
|
o_hash_add_element (hash, element);
|
1996-03-22 00:37:53 +00:00
|
|
|
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
|
1996-04-17 19:26:04 +00:00
|
|
|
// o_chash_t *
|
|
|
|
// o_chash_init_from_array (o_chash_t * chash, o_array_t *array)
|
1996-03-22 00:37:53 +00:00
|
|
|
// {
|
1996-04-17 19:26:04 +00:00
|
|
|
// o_array_enumerator_t enumerator;
|
1996-03-22 00:37:53 +00:00
|
|
|
// 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. */
|
1996-04-17 19:26:04 +00:00
|
|
|
// enumerator = o_array_enumerator (array);
|
1996-03-22 00:37:53 +00:00
|
|
|
//
|
|
|
|
// /* Just walk through ARRAY's elements and add them to CHASH. */
|
1996-04-17 19:26:04 +00:00
|
|
|
// while (o_array_enumerator_next_element (&enumerator, &element))
|
|
|
|
// o_chash_add_element (chash, element);
|
1996-03-22 00:37:53 +00:00
|
|
|
//
|
|
|
|
// return chash;
|
|
|
|
// }
|
|
|
|
|