*** empty log message ***

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@909 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Andrew McCallum 1996-02-13 02:31:48 +00:00
parent 73f762fe23
commit a2a3de7eec
21 changed files with 7997 additions and 0 deletions

503
Source/NSHashTable.m Normal file
View file

@ -0,0 +1,503 @@
/* NSHashTable implementation for GNUStep.
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Mon Dec 12 23:54:09 EST 1994
* Updated: Sat Feb 10 15:59:11 EST 1996
* Serial: 96.02.10.01
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <Foundation/NSString.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSException.h>
#include <Foundation/NSHashTable.h>
#include <Foundation/atoz.h>
#include <objects/hash.h>
/**** Type, Constant, and Macro Definitions **********************************/
/* These are to increase readabilty locally. */
typedef unsigned int (*NSHT_hash_func_t)(NSHashTable *, const void *);
typedef BOOL (*NSHT_isEqual_func_t)(NSHashTable *,
const void *,
const void *);
typedef void (*NSHT_retain_func_t)(NSHashTable *, const void *);
typedef void (*NSHT_release_func_t)(NSHashTable *, void *);
typedef NSString *(*NSHT_describe_func_t)(NSHashTable *, const void *);
/** Standard NSHashTable callbacks **/
const NSHashTableCallBacks NSIntHashCallBacks =
{
(NSHT_hash_func_t) _NSLF_int_hash,
(NSHT_isEqual_func_t) _NSLF_int_is_equal,
(NSHT_retain_func_t) fn_null_function,
(NSHT_release_func_t) fn_null_function,
(NSHT_describe_Func_t) _NSLF_int_describe
};
const NSHashTableCallBacks NSNonOwnedPointerHashCallBacks =
{
(NSHT_hash_func_t) _NSLF_void_p_hash,
(NSHT_isEqual_func_t) _NSLF_void_p_is_equal,
(NSHT_retain_func_t) fn_null_function,
(NSHT_release_func_t) fn_null_function,
(NSHT_describe_func_t) _NSLF_void_p_describe
};
const NSHashTableCallBacks NSNonRetainedObjectsHashCallBacks =
{
(NSHT_hash_func_t) _NSLF_id_hash,
(NSHT_isEqual_func_t) _NSLF_id_is_equal,
(NSHT_retain_func_t) fn_null_function,
(NSHT_release_func_t) fn_null_function,
(NSHT_describe_func_t) _NSLF_id_describe
};
const NSHashTableCallBacks NSObjectsHashCallBacks =
{
(NSHT_hash_func_t) _NSLF_id_hash,
(NSHT_isEqual_func_t) _NSLF_id_is_equal,
(NSHT_retain_func_t) _NSLF_id_retain,
(NSHT_release_func_t) _NSLF_id_object,
(NSHT_describe_func_t) _NSLF_id_describe
};
const NSHashTableCallBacks NSOwnedPointerHashCallBacks =
{
(NSHT_hash_func_t) _NSLF_void_p_hash,
(NSHT_isEqual_func_t) _NSLF_void_p_is_equal,
(NSHT_retain_func_t) fn_null_function,
(NSHT_release_func_t) _NSLF_void_p_release,
(NSHT_describe_func_t) _NSLF_void_p_describe
};
const NSHashTableCallBacks NSPointerToStructHashCallBacks =
{
(NSHT_hash_func_t) _NSLF_int_p_hash,
(NSHT_isEqual_func_t) _NSLF_int_p_is_equal,
(NSHT_retain_func_t) fn_null_function,
(NSHT_release_func_t) fn_null_function,
(NSHT_describe_func_t) _NSLF_int_p_describe
};
/** Macros **/
#define NSHT_ZONE(T) \
((NSZone *)((fn_hash_allocs((fn_hash_t *)(T))).user_data))
#define NSHT_CALLBACKS(T) \
(*((NSHashTableCallBacks *)(__void_p__(fn_hash_extra((fn_hash_t *)(T))))))
#define NSHT_DESCRIBE(T, P) \
NSHT_CALLBACKS((T)).describe((T), (P))
/** Dummy callbacks **/
size_t
_NSHT_hash(fn_generic_t element, void *table)
{
return NSHT_CALLBACKS(table).hash((NSHashTable *)table,
__void_p__(element));
}
int
_NSHT_compare(fn_generic_t element1,
fn_generic_t element2,
void *table)
{
return !(NSHT_CALLBACKS(table).isEqual((NSHashTable *)table,
__void_p__(element1),
__void_p__(element2)));
}
int
_NSHT_is_equal(fn_generic_t element1,
fn_generic_t element2,
void *table)
{
return NSHT_CALLBACKS(table).isEqual((NSHashTable *) table,
__void_p__(element1),
__void_p__(element2));
}
fn_generic_t
_NSHT_retain(fn_generic_t element, void *table)
{
NSHT_CALLBACKS(table).retain((NSHashTable *)table,
__void_p__(element));
return element;
}
void
_NSHT_release(fn_generic_t element, void *table)
{
NSHT_CALLBACKS(table).release(table, __void_p__(element));
return;
}
/* These are wrappers for getting at the real callbacks. */
const fn_callbacks_t _NSHT_callbacks =
{
_NSHT_hash,
_NSHT_compare,
_NSHT_is_equal,
_NSHT_retain,
_NSHT_release,
(fn_describe_func_t)fn_null_function,
0
};
/** Extra, extra **/
/* Make a copy of a hash table's callbacks. */
fn_generic_t
_NSHT_extra_retain(fn_generic_t extra, void *table)
{
/* Pick out the callbacks in EXTRA. */
NSHashTableCallBacks *callBacks = (NSHashTableCallBacks *)__void_p__(extra);
/* Find our zone. */
NSZone *zone = NSHT_ZONE(table);
/* A pointer to some new callbacks. */
NSHashTableCallbacks *newCallBacks;
/* Set aside space for our new callbacks in the right zone. */
newCallBacks = (NSHashTableCallBacks *)NSZoneMalloc(zone,
sizeof(NSHashTableCallBacks));
/* Copy CALLBACKS into NEWCALLBACKS. */
*newCallBacks = *callBacks;
/* Stuff NEWCALLBACKS into EXTRA. */
__void_p__(extra) = newCallBacks;
/* Return our new EXTRA. */
return extra;
}
void
_NSHT_extra_release(fn_generic_t extra, void *table)
{
void *ptr = __void_p__(extra);
NSZone *zone = NSHT_ZONE(table);
if (ptr != NULL)
NSZoneFree(zone, ptr);
return;
}
/* The idea here is that these callbacks ensure that the
* NSHashTableCallbacks which are associated with a given NSHashTable
* remain so throughout the life of the table and its copies. */
fn_callbacks_t _NSHT_extra_callbacks =
{
(fn_hash_func_t) fn_generic_hash,
(fn_is_equal_func_t) fn_generic_is_equal,
(fn_compare_func_t) fn_generic_compare,
_NSHT_extra_retain,
_NSHT_extra_release,
(fn_describe_func_t) fn_null_function,
0
};
/**** Function Implementations ***********************************************/
/** Creating NSHashTables **/
NSHashTable *
NSCreateHashTableWithZone(NSHashTableCallBacks callBacks,
unsigned int capacity,
NSZone *zone)
{
NSHashTable *table;
fn_callbacks_t callbacks;
fn_allocs_t allocs;
/* These callbacks just look in the TABLE's extra and uses the
* callbacks there. See above for precise definitions. */
callbacks = _NSHT_callbacks;
allocs = fn_allocs_for_zone(zone);
/* Then we build the table. */
table = fn_hash_with_allocs_with_callbacks(allocs, callbacks);
if (table != NULL)
{
fn_generic_t extra;
/* Resize TABLE to CAPACITY. */
fn_hash_resize(table, capacity);
/* Set aside space for the NSHashTableExtra. */
__void_p__(extra) = &callBacks;
/* Add EXTRA to TABLE. This takes care of everything for us. */
fn_hash_set_extra_callbacks(table, _NSHT_extra_callbacks);
fn_hash_set_extra(table, extra);
}
/* Wah-hoo! */
return table;
}
NSHashTable *
NSCreateHashTable(NSHashTableCallBacks callBacks,
unsigned int capacity)
{
return NSCreateHashTableWithZone(callBacks, capacity, NULL);
}
/** Copying **/
NSHashTable *
NSCopyHashTableWithZone(NSHashTable *table, NSZone *zone)
{
fn_allocs_t allocs;
NSHashTable *new_table;
/* Due to the wonders of modern Libfn technology, everything we care
* about is automagically transferred. */
allocs = fn_allocs_for_zone(zone);
new_table = fn_hash_copy_with_allocs(table, allocs);
return new_table;
}
/** Destroying **/
void
NSFreeHashTable(NSHashTable *table)
{
/* Due to the wonders of modern Libfn technology, everything we care
* about is automagically and safely destroyed. */
fn_hash_dealloc(table);
return;
}
/** Resetting **/
void
NSResetHashTable(NSHashTable *table)
{
fn_hash_empty(table);
return;
}
/** Comparing **/
BOOL
NSCompareHashTables(NSHashTable *table1, NSHashTable *table2)
{
return (fn_hash_is_equal_to_hash(table1, table2) ? YES : NO);
}
/** Counting **/
unsigned int
NSCountHashTable(NSHashTable *table)
{
return (unsigned int) fn_hash_count(table);
}
/** Retrieving **/
void *
NSHashGet(NSHashTable *table, const void *pointer)
{
fn_generic_t element;
fn_generic_t member;
/* Stuff POINTER into (the `void *' facet of) ELEMENT. */
__void_p__(element) = pointer;
/* Look up ELEMENT in TABLE. */
member = fn_hash_element(table, element);
/* Return the `void *' facet of MEMBER. */
return __void_p__(member);
}
NSArray *
NSAllHashTableObjects(NSHashTable *table)
{
NSArray *array;
fn_generic_t *elements;
id *objects;
unsigned int count;
/* FIXME: We should really be locking TABLE somehow, to insure
* the thread-safeness of this method. */
/* Get an array of the (generically-typed) elements of TABLE. */
elements = fn_hash_all_elements(table);
/* How many thing are in TABLE? */
count = NSCountHashTable(table);
/* Make enough room for our array of `id's together with a
* terminating `nil' that we add below. */
objects = fn_calloc(fn_hash_allocs(table), count + 1, sizeof(id));
/* Step through the generic array and copy the `id' facet of each
* into the corresponding member of the objects array. Remember
* that this function is only suppossed to be called when TABLE
* contains objects. Otherwise, everything goes to hell remarkably
* quickly. */
for (i = 0; i < count; ++i)
objects[i] = __id__(elements[i]);
/* `nil' terminate OBJECTS. */
objects[i] = nil;
/* Build the NSArray to return. */
array = [[NSArray alloc] initWithObjects:objects count:count];
/* Free up all the space we allocated here. */
fn_free(fn_hash_allocs(table), elements);
fn_free(fn_hash_allocs(table), objects);
/* FIXME: Should ARRAY returned be `autorelease'd? */
return [array autorelease];
}
/** Enumerating **/
NSHashEnumerator
NSEnumerateHashTable(NSHashTable *table)
{
return fn_hash_enumerator(table);
}
void *
NSNextHashEnumeratorItem(NSHashEnumerator *enumerator)
{
fn_generic_t element;
/* Grab the next element. */
fn_hash_enumerator_next_element(enumerator, &element);
/* Return ELEMENT's `void *' facet. */
return __void_p__(element);
}
/** Adding **/
void
NSHashInsert(NSHashTable *table, const void *pointer)
{
fn_generic_t element;
/* Stuff POINTER into ELEMENT. */
__void_p__(element) = (void *)pointer;
/* Place ELEMENT in TABLE. */
fn_hash_add_element(table, element);
return;
}
void
NSHashInsertKnownAbsent(NSHashTable *table, const void *pointer)
{
fn_generic_t element;
__void_p__(element) = pointer;
if (fn_hash_contains_element(table, element))
{
/* FIXME: I should make this give the user/programmer more
* information. Not difficult to do, just something for a later
* date. */
[NSException raise:NSInvalidArgumentException
format:@"Attempted reinsertion of \"%@\" into a hash table.",
NSHT_DESCRIBE(table, pointer)];
}
else
{
fn_hash_add_element_known_absent(table, element);
}
return;
}
void *
NSHashInsertIfAbsent(NSHashTable *table, const void *pointer)
{
fn_generic_t element;
/* Stuff POINTER into ELEMENT. */
__void_p__(element) = (void *)pointer;
/* Place ELEMENT in TABLE. */
element = fn_hash_add_element_if_absent(table, element);
/* Return the `void *' facet of ELEMENT. */
return __void_p__(element);
}
/** Removing **/
void
NSHashRemove(NSHashTable *table, const void *pointer)
{
fn_generic_t element;
/* Stuff POINTER into ELEMENT. */
__void_p__(element) = pointer;
/* Remove ELEMENT from TABLE. */
fn_hash_remove_element(table, element);
return;
}
/** Describing **/
/* FIXME: Make this nicer. I don't know what is desired here, though.
* If somebody has a clear idea of what this string should look like,
* please tell me, and I'll make it happen. */
NSString *
NSStringFromHashTable(NSHashTable *table)
{
NSString *string;
NSHashEnumerator enumerator;
void *pointer;
/* This will be our string. */
string = [NSMutableString string];
/* Get an enumerator for TABLE. */
enumerator = NSEnumerateHashTable(table);
/* Iterate over the elements of TABLE, appending the description of
* each to the mutable string STRING. */
while ((pointer = NSNextHashEnumeratorItem(&enumerator)) != NULL)
[string appendFormat:@"%@;", NSHT_DESCRIBE(table, pointer)];
/* Note that this string'll need to be `retain'ed. */
/* FIXME: Should I `autorelease' STRING? I think so. */
return [string autorelease];
}

612
Source/NSMapTable.m Normal file
View file

@ -0,0 +1,612 @@
/* NSMapTable implementation for GNUStep.
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Mon Dec 12 23:59:57 EST 1994
* Updated: Sat Feb 10 16:00:25 EST 1996
* Serial: 96.02.10.01
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <Foundation/NSString.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSException.h>
#include <Foundation/_NSLibfn.h>
#include <Foundation/NSMapTable.h>
#include <fn/map.h>
/**** Type, Constant, and Macro Definitions **********************************/
/* This is for keeping track of information... */
typedef struct _NSMT_extra NSMT_extra_t;
struct _NSMT_extra
{
NSMapTableKeyCallBacks keyCallBacks;
NSMapTableValueCallBacks valueCallBacks;
};
/* These are to increase readabilty locally. */
typedef unsigned int (*NSMT_hash_func_t)(NSMapTable *, const void *);
typedef BOOL (*NSMT_is_equal_func_t)(NSMapTable *, const void *,
const void *);
typedef void (*NSMT_retain_func_t)(NSMapTable *, const void *);
typedef void (*NSMT_release_func_t)(NSMapTable *, void *);
typedef NSString *(*NSMT_describe_func_t)(NSMapTable *, const void *);
const NSMapTableKeyCallBacks NSIntMapKeyCallBacks =
{
(NSMT_hash_func_t) _NS_int_hash,
(NSMT_is_equal_func_t) _NS_int_is_equal,
(NSMT_retain_func_t) fn_null_function,
(NSMT_release_func_t) fn_null_function,
(NSMT_describe_func_t) _NS_int_describe,
(const void *) 0
};
const NSMapTableKeyCallBacks NSNonOwnedPointerMapKeyCallBacks =
{
(NSMT_hash_func_t) _NS_void_p_hash,
(NSMT_is_equal_func_t) _NS_void_p_is_equal,
(NSMT_retain_func_t) fn_null_function,
(NSMT_release_func_t) fn_null_function,
(NSMT_describe_func_t) _NS_void_p_describe,
(const void *) NULL
};
const NSMapTableKeyCallBacks NSNonOwnedPointerOrNullMapKeyCallBacks =
{
(NSMT_hash_func_t) _NS_void_p_hash,
(NSMT_is_equal_func_t) _NS_void_p_is_equal,
(NSMT_retain_func_t) fn_null_function,
(NSMT_release_func_t) fn_null_function,
(NSMT_describe_func_t) _NS_void_p_describe,
/* FIXME: Oh my. Is this really ok? I did it in a moment of
* weakness. A fit of madness, I say! And if this is wrong, what
* *should* it be?!? */
(const void *) -1
};
const NSMapTableKeyCallBacks NSNonRetainedObjectMapKeyCallBacks =
{
(NSMT_hash_func_t) _NS_id_hash,
(NSMT_is_equal_func_t) _NS_id_is_equal,
(NSMT_retain_func_t) fn_null_function,
(NSMT_release_func_t) fn_null_function,
(NSMT_describe_func_t) _NS_id_describe,
(const void *) NULL
};
const NSMapTableKeyCallBacks NSObjectMapKeyCallBacks =
{
(NSMT_hash_func_t) _NS_id_hash,
(NSMT_is_equal_func_t) _NS_id_is_equal,
(NSMT_retain_func_t) _NS_id_retain,
(NSMT_release_func_t) _NS_id_release,
(NSMT_describe_func_t) _NS_id_describe,
(const void *) NULL
};
const NSMapTableKeyCallBacks NSOwnedPointerMapKeyCallBacks =
{
(NSMT_hash_func_t) _NS_void_p_hash,
(NSMT_is_equal_func_t) _NS_void_p_is_equal,
(NSMT_retain_func_t) fn_null_function,
(NSMT_release_func_t) _NS_void_p_release,
(NSMT_describe_func_t) _NS_void_p_describe,
(const void *) NULL
};
const NSMapTableValueCallBacks NSIntMapValueCallBacks =
{
(NSMT_retain_func_t) fn_null_function,
(NSMT_release_func_t) fn_null_function,
(NSMT_describe_func_t) _NS_int_describe
};
const NSMapTableValueCallBacks NSNonOwnedPointerMapValueCallBacks =
{
(NSMT_retain_func_t) fn_null_function,
(NSMT_release_func_t) fn_null_function,
(NSMT_describe_func_t) _NS_void_p_describe
};
const NSMapTableValueCallBacks NSObjectMapValueCallBacks =
{
(NSMT_retain_func_t) _NS_id_retain,
(NSMT_release_func_t) _NS_id_release,
(NSMT_describe_func_t) _NS_id_describe
};
const NSMapTableValueCallBacks NSOwnedPointerMapValueCallBacks =
{
(NSMT_retain_func_t) fn_null_function,
(NSMT_release_func_t) _NS_void_p_release,
(NSMT_describe_func_t) _NS_void_p_describe
};
/** Macros **/
#define NSMT_ZONE(T) \
((NSZone *)((fn_map_allocs((fn_map_t *)(T))).user_data))
#define NSMT_EXTRA(T) \
((NSMT_extra_t *)(__void_p__(fn_map_extra((fn_map_t *)(T)))))
#define NSMT_KEY_CALLBACKS(T) \
((NSMT_EXTRA((T)))->keyCallBacks)
#define NSMT_VALUE_CALLBACKS(T) \
((NSMT_EXTRA((T)))->valueCallBacks)
#define NSMT_DESCRIBE_KEY(T, P) \
NSMT_KEY_CALLBACKS((T)).describe((T), (P))
#define NSMT_DESCRIBE_VALUE(T, P) \
NSMT_VALUE_CALLBACKS((T)).describe((T), (P))
/** Dummy callbacks **/
size_t
_NSMT_key_hash(fn_generic_t element, void *table)
{
return NSMT_KEY_CALLBACKS(table).hash((NSMapTable *)table,
__void_p__(element));
}
int
_NSMT_key_compare(fn_generic_t element1,
fn_generic_t element2,
void *table)
{
return !(NSMT_KEY_CALLBACKS(table).isEqual((NSMapTable *)table,
__void_p__(element1),
__void_p__(element2)));
}
int
_NSMT_key_is_equal(fn_generic_t element1,
fn_generic_t element2,
void *table)
{
return NSMT_KEY_CALLBACKS(table).isEqual((NSMapTable *) table,
__void_p__(element1),
__void_p__(element2));
}
fn_generic_t
_NSMT_key_retain(fn_generic_t element, void *table)
{
NSMT_KEY_CALLBACKS(table).retain((NSMapTable *)table,
__void_p__(element));
return element;
}
void
_NSMT_key_release(fn_generic_t element, void *table)
{
NSMT_KEY_CALLBACKS(table).release(table, __void_p__(element));
return;
}
fn_generic_t
_NSMT_value_retain(fn_generic_t element, void *table)
{
NSMT_VALUE_CALLBACKS(table).retain((NSMapTable *)table,
__void_p__(element));
return element;
}
void
_NSMT_value_release(fn_generic_t element, void *table)
{
NSMT_VALUE_CALLBACKS(table).release(table, __void_p__(element));
return;
}
/* These are wrappers for getting at the real callbacks. */
fn_callbacks_t _NSMT_key_callbacks =
{
_NSMT_key_hash,
_NSMT_key_compare,
_NSMT_key_is_equal,
_NSMT_key_retain,
_NSMT_key_release,
(fn_describe_func_t)fn_null_function,
0
};
fn_callbacks_t
_NSMT_callbacks_for_key_callbacks(NSMapTableKeyCallBacks keyCallBacks)
{
fn_callbacks_t cb = _NSMT_key_callbacks;
__void_p__(cb.not_an_item_marker) = (void *)(keyCallBacks.notAKeyMarker);
return callbacks;
}
fn_callbacks_t _NSMT_value_callbacks =
{
(fn_hash_func_t) fn_generic_hash,
(fn_compare_func_t) fn_generic_compare,
(fn_is_equal_func_t) fn_generic_is_equal,
_NSMT_value_retain,
_NSMT_value_release,
(fn_describe_func_t)fn_null_function,
0
};
/** Extra, extra **/
/* Make a copy of a hash table's callbacks. */
fn_generic_t
_NSMT_extra_retain(fn_generic_t g, void *table)
{
/* A pointer to some space for new callbacks. */
NSMT_extra_t *new_extra;
/* Set aside space for our new callbacks in the right zone. */
new_extra = (NSMT_extra_t *)NSZoneMalloc(NSMT_ZONE(table),
sizeof(NSMT_extra_t));
/* Copy the old callbacks into NEW_EXTRA. */
*new_extra = *((NSMT_extra_t *)(__void_p__(g)))
/* Stuff NEW_EXTRA into G. */
__void_p__(g) = new_extra;
/* Return our new EXTRA. */
return g;
}
void
_NSMT_extra_release(fn_generic_t extra, void *table)
{
void *ptr = __void_p__(extra);
NSZone *zone = NSMT_ZONE(table);
if (ptr != NULL)
NSZoneFree(zone, ptr);
return;
}
/* The idea here is that these callbacks ensure that the
* NSMapTableCallbacks which are associated with a given NSMapTable
* remain so throughout the life of the table and its copies. */
fn_callbacks_t _NSMT_extra_callbacks =
{
(fn_hash_func_t) fn_generic_hash,
(fn_is_equal_func_t) fn_generic_is_equal,
(fn_compare_func_t) fn_generic_compare,
_NSMT_extra_retain,
_NSMT_extra_release,
(fn_describe_func_t) fn_null_function,
0
};
/**** Function Implementations ****/
/** Creating an NSMapTable **/
NSMapTable *
NSCreateMapTableWithZone(NSMapTableKeyCallBacks keyCallBacks,
NSMapTableValueCallBacks valueCallBacks,
unsigned capacity,
NSZone *zone)
{
NSMapTable *table;
fn_callbacks_t key_callbacks, value_callbacks;
fn_allocs_t alloc;
/* Transform the callbacks we were given. */
key_callbacks = _NSMT_callbacks_for_key_callbacks(keyCallBacks);
value_callbacks = _NSMT_value_callbacks;
/* Get some useful allocs. */
alloc = fn_allocs_for_zone(zone);
/* Create a map table. */
table = fn_map_with_allocs_with_callbacks(allocs, key_callbacks,
value_callbacks);
/* Adjust the capacity of TABLE. */
fn_map_resize(table, capacity);
if (table != NULL)
{
NSMapTableExtras *extras;
/* Set aside space for the NSMapTableExtras. */
extras = _NSNewMapTableExtrasWithZone(zone);
extras->keyCallBacks = keyCallBacks;
extras->valueCallBacks = valueCallBacks;
table->extras = extras;
}
return table;
}
NSMapTable *
NSCreateMapTable(NSMapTableKeyCallBacks keyCallBacks,
NSMapTableValueCallBacks valueCallBacks,
unsigned int capacity)
{
return NSCreateMapTableWithZone(keyCallBacks,
valueCallBacks,
capacity,
NULL);
}
/* FIXME: CODE THIS! */
NSMapTable *
NSCopyMapTableWithZone(NSMapTable *table, NSZone *zone)
{
fn_allocs_t allocs;
NSMapTable *new_table;
allocs = fn_allocs_for_zone(zone);
new_table = fn_map_copy_with_allocs(table, alloc);
return new_table;
}
/** Freeing an NSMapTable **/
void
NSFreeMapTable(NSMapTable *table)
{
fn_map_dealloc(table);
return;
}
void
NSResetMapTable(NSMapTable *table)
{
fn_map_empty(table);
return;
}
/** Comparing two NSMapTables **/
BOOL
NSCompareMapTables(NSMapTable *table1, NSMapTable *table2)
{
return fn_map_is_equal_map(table1, table2) ? YES : NO;
}
/** Getting the number of items in an NSMapTable **/
unsigned int
NSCountMapTable(NSMapTable *table)
{
return (unsigned int) fn_map_count(table);
}
/** Retrieving items from an NSMapTable **/
BOOL
NSMapMember(NSMapTable *table, const void *key,
void **originalKey, void **value)
{
fn_generic_t k, ok, v;
int i;
/* Stuff KEY into K. */
__void_p__(k) = key;
/* Check for K in TABLE. */
i = fn_map_key_and_value(table, k, &ok, &v);
/* Put the `void *' facet of OK and V into ORIGINALKEY and VALUE. */
if (originalKey != NULL)
*originalKey = __void_p__(ok);
if (value != NULL)
*value = __void_p__(v);
/* Indicate our state of success. */
return i ? YES : NO;
}
void *
NSMapGet(NSMapTable *table, const void *key)
{
return fn_map_value(table, key);
}
NSMapEnumerator
NSEnumerateMapTable(NSMapTable *table)
{
return fn_map_enumerator(table);
}
BOOL
NSNextMapEnumeratorPair(NSMapEnumerator *enumerator,
void **key, void **value)
{
fn_generic_t k, v;
int i;
/* Get the next pair. */
i = fn_map_enumerator_next_key_and_value(enumerator, &k, &v);
/* Put the `void *' facet of K and V into KEY and VALUE. */
*key = __void_p__(k);
*value = __void_p__(v);
/* Indicate our success or failure. */
return i ? YES : NO;
}
NSArray *
NSAllMapTableKeys(NSMapTable *table)
{
NSArray *array;
fn_generic_t *keys;
id *objects;
unsigned int count;
count = fn_map_count(table);
keys = fn_map_all_keys(table);
objects = fn_calloc(fn_set_allocs(table), count + 1, sizeof(id));
for (i = 0; i < count; ++i)
objects[i] = __id__(keys[i]);
objects[i] = nil;
array = [[NSArray alloc] initWithObjects:objects count:count];
fn_free(fn_map_allocs(table), keys);
fn_free(fn_map_allocs(table), objects);
/* FIXME: Should ARRAY returned be `autorelease'd? */
return [array autorelease];
}
NSArray *
NSAllMapTableValues(NSMapTable *table)
{
NSArray *array;
fn_generic_t *values;
id *objects;
unsigned int count;
count = fn_map_count(table);
values = fn_map_all_values(table);
objects = fn_calloc(fn_set_allocs(table), count + 1, sizeof(id));
for (i = 0; i < count; ++i)
objects[i] = __id__(values[i]);
objects[i] = nil;
array = [[NSArray alloc] initWithObjects:objects count:count];
fn_free(fn_map_allocs(table), keys);
fn_free(fn_map_allocs(table), objects);
/* FIXME: Should ARRAY returned be `autorelease'd? */
return [array autorelease];
}
/** Adding items to an NSMapTable **/
void
NSMapInsert(NSMapTable *table, const void *key, const void *value)
{
fn_generic_t k, v;
/* Stuff KEY and VALUE into K and V. */
__void_p__(k) = key;
__void_p__(v) = value;
/* Put K -> V into TABLE. */
fn_map_at_key_put_value(table, k, v);
return;
}
void *
NSMapInsertIfAbsent(NSMapTable *table, const void *key, const void *value)
{
fn_generic_t k, v, m;
/* Stuff KEY and VALUE into K and V. */
__void_p__(k) = key;
__void_p__(v) = value;
/* Put K -> V into TABLE. */
m = fn_map_at_key_put_value_if_absent(table, k, v);
/* Return the `void *' facet of M. */
return __void_p__(m);
}
void
NSMapInsertKnownAbsent(NSMapTable *table, const void *key, const void *value)
{
fn_generic_t k, v;
/* Stuff KEY and VALUE into K and V. */
__void_p__(k) = key;
__void_p__(v) = value;
/* Is the key already in the table? */
if (fn_map_contains_key(table, k))
{
/* Ooh. Bad. The docs say to raise an exception! */
/* FIXME: I should make this much more informative. */
[NSException raise:NSInvalidArgumentException
format:@"That key's already in the table."];
}
else
{
/* Well, we know it's not there, so... */
fn_map_at_key_put_value_known_absent(table, k, v);
}
/* Yah-hoo! */
return;
}
/** Removing items from an NSMapTable **/
void
NSMapRemove(NSMapTable *table, const void *key)
{
fn_map_remove_key(table, key);
return;
}
/** Getting an NSString representation of an NSMapTable **/
NSString *
NSStringFromMapTable(NSMapTable *table)
{
NSString *string;
NSMapEnumerator enumerator;
NSMapTableKeyCallBacks keyCallBacks;
NSMapTableValueCallBacks valueCallBacks;
void *key, *value;
/* Get an empty mutable string. */
string = [NSMutableString string];
/* Pull the NSMapTable...CallBacks out of the mess. */
keyCallBacks = NSMT_KEY_CALLBACKS(table);
valueCallBacks = NSMT_VALUE_CALLBACKS(table);
/* Get an enumerator for our table. */
enumerator = NSEnumerateMapTable(table);
/* Now, just step through the elements of the table, and add their
* descriptions to the string. */
while (NSNextMapEnumeratorPair(&enumerator, &key, &value))
[string appendFormat:@"%@ = %@;", (keyCallBacks.describe)(table, key),
(valueCallBacks.describe)(table, value)];
/* Note that this string'll need to be `retain'ed. */
/* FIXME: Should I be `autorelease'ing it? */
return [string autorelease];
}

46
Source/abort.c Normal file
View file

@ -0,0 +1,46 @@
/* A hookable abort function.
* Copyright (C) 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Sat Feb 10 12:31:57 EST 1996
* Updated: Sat Feb 10 12:31:57 EST 1996
* Serial: 96.02.10.01
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <stdio.h>
#include <objects/abort.h>
/**** Type, Constant, and Macro Definitions **********************************/
static void (*__objects_abort) (void) = NULL;
/**** Function Implementations ***********************************************/
void
objects_abort (void)
{
if (__objects_abort != NULL)
(__objects_abort) ();
else
abort ();
return;
}

81
Source/allocs.c Normal file
View file

@ -0,0 +1,81 @@
/* Modular memory management through structures.
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Thu Oct 13 23:45:49 EDT 1994
* Updated: Sat Feb 10 15:19:32 EST 1996
* Serial: 96.02.10.03
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <objects/allocs.h>
/**** Type, Constant, and Macro Definitions **********************************/
static objects_allocs_t __objects_allocs_standard =
{
(objects_malloc_func_t) malloc,
(objects_calloc_func_t) calloc,
(objects_realloc_func_t) realloc,
(objects_free_func_t) free,
(void *) 0
};
/**** Function Implementations ***********************************************/
objects_allocs_t
objects_allocs_standard (void)
{
return __objects_allocs_standard;
}
void *
objects_malloc (objects_allocs_t allocs, size_t s)
{
return (*(allocs.malloc)) (s, allocs.user_data);
}
void *
objects_calloc (objects_allocs_t allocs, size_t n, size_t s)
{
return (*(allocs.calloc)) (n, s, allocs.user_data);
}
void *
objects_realloc (objects_allocs_t allocs, void *p, size_t s)
{
return (*(allocs.realloc)) (p, s, allocs.user_data);
}
void
objects_free (objects_allocs_t allocs, void *p)
{
(*(allocs.free)) (p, allocs.user_data);
return;
}
size_t
objects_next_power_of_two (size_t beat)
{
size_t start = 1;
while ((start <= beat) && (start <<= 1));
return start;
}

904
Source/array.c Normal file
View file

@ -0,0 +1,904 @@
/* 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: Sat Feb 10 16:16:12 EST 1996
* Serial: 96.02.10.02
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <objects/allocs.h>
#include <objects/callbacks.h>
#include <objects/abort.h>
#include <objects/array.h>
#include <objects/hash.h>
/**** Function Implementations ***********************************************/
/** Background functions **/
size_t
_objects_array_fold_index (size_t index, size_t slot_count)
{
return (slot_count ? (index % slot_count) : 0);
}
size_t
_objects_array_internal_index (objects_array_t * array, size_t index)
{
return _objects_array_fold_index (index, array->slot_count);
}
objects_array_slot_t *
_objects_array_slot_for_index (objects_array_t * array, size_t index)
{
return (array->slots + _objects_array_internal_index (array, index));
}
objects_array_bucket_t *
_objects_array_bucket_for_index (objects_array_t * array, size_t index)
{
objects_array_slot_t *slot;
objects_array_bucket_t *bucket;
/* First, we translate the index into a bucket index to find our
* candidate for the bucket. */
slot = _objects_array_slot_for_index (array, index);
bucket = *slot;
/* But we need to check to see whether this is really the bucket we
* wanted. */
if (bucket != NULL && 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 NULL;
}
objects_array_bucket_t *
_objects_array_new_bucket (objects_array_t * array, size_t index, void *element)
{
objects_array_bucket_t *bucket;
bucket = (objects_array_bucket_t *) objects_malloc (objects_array_allocs (array),
sizeof (objects_array_bucket_t));
if (bucket != NULL)
{
objects_retain (objects_array_element_callbacks (array), element, array);
bucket->index = index;
bucket->element = element;
}
return bucket;
}
void
_objects_array_free_bucket (objects_array_t * array, objects_array_bucket_t * bucket)
{
if (bucket != NULL)
{
objects_release (objects_array_element_callbacks (array), bucket->element, array);
objects_free (objects_array_allocs (array), bucket);
}
return;
}
objects_array_slot_t *
_objects_array_new_slots (objects_array_t * array, size_t slot_count)
{
return (objects_array_slot_t *) objects_calloc (objects_array_allocs (array),
slot_count,
sizeof (objects_array_slot_t));
}
void
_objects_array_free_slots (objects_array_t * array, objects_array_slot_t * slots)
{
if (slots != NULL)
objects_free (objects_array_allocs (array), slots);
return;
}
void
_objects_array_empty_slot (objects_array_t * array, objects_array_slot_t * slot)
{
if (*slot != NULL)
{
/* Get rid of the bucket. */
_objects_array_free_bucket (array, *slot);
/* Mark the slot as empty. */
*slot = NULL;
/* Keep the element count accurate */
--(array->element_count);
}
/* And return. */
return;
}
void
_objects_array_insert_bucket (objects_array_t * array, objects_array_bucket_t * bucket)
{
objects_array_slot_t *slot;
slot = _objects_array_slot_for_index (array, bucket->index);
/* We're adding a bucket, so the current set of sorted slots is now
* invalidated. */
if (array->sorted_slots != NULL)
{
_objects_array_free_slots (array, array->sorted_slots);
array->sorted_slots = NULL;
}
if ((*slot) == NULL)
{
/* There's nothing there, so we can put `bucket' there. */
*slot = bucket;
/* Increment the array's bucket counter. */
++(array->element_count);
return;
}
if ((*slot)->index == bucket->index)
{
/* There's a bucket there, and it has the same index as `bucket'.
* So we get rid of the old one, and put the new one in its
* place. */
_objects_array_free_bucket (array, *slot);
*slot = bucket;
return;
}
else
{
/* Now we get to fiddle around with things to make the world a
* better place... */
size_t new_slot_count;
objects_array_slot_t *new_slots; /* This guy holds the buckets while we
* muck about with them. */
size_t d; /* Just a counter */
/* FIXME: I *really* wish I had a way of generating
* statistically better initial values for this variable. So
* I'll run a few tests and see... And is there a better
* algorithm, e.g., a better collection of sizes in the sense
* that the likelyhood of fitting everything in earlier is
* high? Well, enough mumbling. */
/* At any rate, we're guaranteed to need at least this many. */
new_slot_count = array->element_count + 1;
do
{
/* First we make a new pile of slots for the buckets. */
new_slots = _objects_array_new_slots (array, new_slot_count);
if (new_slots == NULL)
objects_abort ();
/* Then we put the new bucket in the pile. */
new_slots[_objects_array_fold_index (bucket->index,
new_slot_count)] = bucket;
/* Now loop and try to place the others. Upon collision
* with a previously inserted bucket, try again with more
* `new_slots'. */
for (d = 0; d < array->slot_count; ++d)
{
if (array->slots[d] != NULL)
{
size_t i;
i = _objects_array_fold_index (array->slots[d]->index,
new_slot_count);
if (new_slots[i] == NULL)
{
new_slots[i] = array->slots[d];
}
else
{
/* A collision. Clean up and try again. */
/* Free the current set of new buckets. */
_objects_array_free_slots (array, new_slots);
/* Bump up the number of new buckets. */
++new_slot_count;
/* Break out of the `for' loop. */
break;
}
}
}
}
while (d < array->slot_count);
if (array->slots != NULL)
_objects_array_free_slots (array, array->slots);
array->slots = new_slots;
array->slot_count = new_slot_count;
++(array->element_count);
return;
}
}
int
_objects_array_compare_slots (const objects_array_slot_t * slot1,
const objects_array_slot_t * slot2)
{
if (slot1 == slot2)
return 0;
if (*slot1 == NULL)
return 1;
if (*slot2 == NULL)
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 *);
void
_objects_array_make_sorted_slots (objects_array_t * array)
{
objects_array_slot_t *new_slots;
/* If there're already some sorted slots, then they're valid, and
* we're done. */
if (array->sorted_slots != NULL)
return;
/* Make some new slots. */
new_slots = _objects_array_new_slots (array, array->slot_count);
/* Copy the pointers to buckets into the new slots. */
memcpy (new_slots, array->slots, (array->slot_count
* sizeof (objects_array_slot_t)));
/* Sort the new slots. */
qsort (new_slots, array->slot_count, sizeof (objects_array_slot_t),
(qsort_compare_func_t) _objects_array_compare_slots);
/* Put the newly sorted slots in the `sorted_slots' element of the
* array structure. */
array->sorted_slots = new_slots;
return;
}
objects_array_bucket_t *
_objects_array_enumerator_next_bucket (objects_array_enumerator_t * enumerator)
{
if (enumerator->is_sorted)
{
if (enumerator->is_ascending)
{
if (enumerator->array->sorted_slots == NULL)
return NULL;
if (enumerator->index < enumerator->array->element_count)
{
objects_array_bucket_t *bucket;
bucket = enumerator->array->sorted_slots[enumerator->index];
++(enumerator->index);
return bucket;
}
else
return NULL;
}
else
{
if (enumerator->array->sorted_slots == NULL)
return NULL;
if (enumerator->index > 0)
{
objects_array_bucket_t *bucket;
--(enumerator->index);
bucket = enumerator->array->sorted_slots[enumerator->index];
return bucket;
}
else
return NULL;
}
}
else
{
objects_array_bucket_t *bucket;
if (enumerator->array->slots == NULL)
return NULL;
for (bucket = NULL;
(enumerator->index < enumerator->array->slot_count
&& bucket == NULL);
++(enumerator->index))
{
bucket = enumerator->array->slots[enumerator->index];
}
return bucket;
}
}
/** Statistics **/
size_t
objects_array_count (objects_array_t * array)
{
return array->element_count;
}
size_t
objects_array_capacity (objects_array_t * array)
{
return array->slot_count;
}
int
objects_array_check (objects_array_t * array)
{
return 0;
}
int
objects_array_is_empty (objects_array_t * array)
{
return objects_array_count (array) != 0;
}
/** Emptying **/
void
objects_array_empty (objects_array_t * array)
{
size_t c;
/* Just empty each slot out, one by one. */
for (c = 0; c < array->slot_count; ++c)
_objects_array_empty_slot (array, array->slots + c);
return;
}
/** Creating **/
objects_array_t *
objects_array_alloc_with_allocs (objects_allocs_t allocs)
{
objects_array_t *array;
/* Get a new array. */
array = _objects_array_alloc_with_allocs (allocs);
return array;
}
objects_array_t *
objects_array_alloc (void)
{
return objects_array_alloc_with_allocs (objects_allocs_standard ());
}
objects_array_t *
objects_array_with_allocs (objects_allocs_t allocs)
{
return objects_array_init (objects_array_alloc_with_allocs (allocs));
}
objects_array_t *
objects_array_with_allocs_with_callbacks (objects_allocs_t allocs,
objects_callbacks_t callbacks)
{
return objects_array_init_with_callbacks (objects_array_alloc_with_allocs (allocs),
callbacks);
}
objects_array_t *
objects_array_with_callbacks (objects_callbacks_t callbacks)
{
return objects_array_init_with_callbacks (objects_array_alloc (), callbacks);
}
objects_array_t *
objects_array_of_char_p (void)
{
return objects_array_with_callbacks (objects_callbacks_for_char_p);
}
objects_array_t *
objects_array_of_void_p (void)
{
return objects_array_with_callbacks (objects_callbacks_for_void_p);
}
objects_array_t *
objects_array_of_owned_void_p (void)
{
return objects_array_with_callbacks (objects_callbacks_for_owned_void_p);
}
objects_array_t *
objects_array_of_int (void)
{
return objects_array_with_callbacks (objects_callbacks_for_int);
}
objects_array_t *
objects_array_of_id (void)
{
return objects_array_with_callbacks (objects_callbacks_for_id);
}
/** Initializing **/
objects_array_t *
objects_array_init_with_callbacks (objects_array_t * array, objects_callbacks_t callbacks)
{
if (array != NULL)
{
/* The default capacity is 15. */
size_t capacity = 15;
/* Record the element callbacks. */
array->callbacks = objects_callbacks_standardize (callbacks);
/* Initialize ARRAY's information. */
array->element_count = 0;
array->slot_count = capacity + 1;
/* Make some new slots. */
array->slots = _objects_array_new_slots (array, capacity + 1);
/* Get the sorted slots ready for later use. */
array->sorted_slots = NULL;
}
return array;
}
objects_array_t *
objects_array_init (objects_array_t * array)
{
return objects_array_init_with_callbacks (array,
objects_callbacks_standard());
}
objects_array_t *
objects_array_init_from_array (objects_array_t * array, objects_array_t * old_array)
{
objects_array_enumerator_t enumerator;
size_t index;
void *element;
/* Initialize ARRAY in the usual way. */
objects_array_init_with_callbacks (array,
objects_array_element_callbacks (old_array));
/* Get an enumerator for OLD_ARRAY. */
enumerator = objects_array_enumerator (old_array);
/* Step through OLD_ARRAY's elements, putting them at the proper
* index in ARRAY. */
while (objects_array_enumerator_next_index_and_element (&enumerator,
&index, &element))
{
objects_array_at_index_put_element (array, index, element);
}
return array;
}
/** Destroying **/
void
objects_array_dealloc (objects_array_t * array)
{
if (array != NULL)
{
/* Empty out ARRAY. */
objects_array_empty (array);
/* Free up its slots. */
_objects_array_free_slots (array, array->slots);
/* FIXME: What about ARRAY's sorted slots? */
/* Free up ARRAY itself. */
_objects_array_dealloc (array);
}
return;
}
/** Searching **/
void *
objects_array_element_at_index (objects_array_t * array, size_t index)
{
objects_array_bucket_t *bucket = _objects_array_bucket_for_index (array, index);
if (bucket != NULL)
return bucket->element;
else
/* If `bucket' is NULL, then the requested index is unused. */
/* There's no bucket, so... */
return objects_array_not_an_element_marker (array);
}
size_t
objects_array_index_of_element (objects_array_t * array, void *element)
{
size_t i;
for (i = 0; i < array->slot_count; ++i)
{
objects_array_bucket_t *bucket = array->slots[i];
if (bucket != NULL)
if (objects_is_equal (objects_array_element_callbacks (array),
bucket->element,
element,
array))
return bucket->index;
}
return i;
}
int
objects_array_contains_element (objects_array_t * array, void *element)
{
/* Note that this search is quite inefficient. */
return objects_array_index_of_element (array, element) < (array->slot_count);
}
void **
objects_array_all_elements (objects_array_t * array)
{
objects_array_enumerator_t enumerator;
void **elements;
size_t count, i;
count = objects_array_count (array);
/* Set aside space to hold the elements. */
elements = (void **) objects_calloc (objects_array_allocs (array),
count + 1,
sizeof (void *));
enumerator = objects_array_enumerator (array);
for (i = 0; i < count; ++i)
objects_array_enumerator_next_element (&enumerator, elements + i);
elements[i] = objects_array_not_an_element_marker (array);
/* We're done, so heave it back. */
return elements;
}
void **
objects_array_all_elements_ascending (objects_array_t * array)
{
objects_array_enumerator_t enumerator;
void **elements;
size_t count, i;
count = objects_array_count (array);
/* Set aside space to hold the elements. */
elements = (void **) objects_calloc (objects_array_allocs (array),
count + 1,
sizeof (void *));
enumerator = objects_array_ascending_enumerator (array);
for (i = 0; i < count; ++i)
objects_array_enumerator_next_element (&enumerator, elements + i);
elements[i] = objects_array_not_an_element_marker (array);
/* We're done, so heave it back. */
return elements;
}
void **
objects_array_all_elements_descending (objects_array_t * array)
{
objects_array_enumerator_t enumerator;
void **elements;
size_t count, i;
count = objects_array_count (array);
/* Set aside space to hold the elements. */
elements = (void **) objects_calloc (objects_array_allocs (array),
count + 1,
sizeof (void *));
enumerator = objects_array_descending_enumerator (array);
for (i = 0; i < count; ++i)
objects_array_enumerator_next_element (&enumerator, elements + i);
elements[i] = objects_array_not_an_element_marker (array);
/* We're done, so heave it back. */
return elements;
}
/** Removing **/
void
objects_array_remove_element_at_index (objects_array_t * array, size_t index)
{
objects_array_bucket_t *bucket;
/* Get the bucket that might be there. */
bucket = _objects_array_bucket_for_index (array, index);
/* If there's a bucket at the index, then we empty its slot out. */
if (bucket != NULL)
_objects_array_empty_slot (array, _objects_array_slot_for_index (array, index));
/* Finally, we return. */
return;
}
void
objects_array_remove_element_known_present (objects_array_t * array,
void *element)
{
objects_array_remove_element_at_index (array,
objects_array_index_of_element (array,
element));
return;
}
void
objects_array_remove_element (objects_array_t * array, void *element)
{
if (objects_array_contains_element (array, element))
objects_array_remove_element_known_present (array, element);
return;
}
/** Adding **/
void *
objects_array_at_index_put_element (objects_array_t * array,
size_t index,
void *element)
{
objects_array_bucket_t *bucket;
/* Clean out anything that's already there. */
objects_array_remove_element_at_index (array, index);
/* Make a bucket for our information. */
bucket = _objects_array_new_bucket (array, index, element);
/* Put our bucket in the array. */
_objects_array_insert_bucket (array, bucket);
return element;
}
/** Enumerating **/
objects_array_enumerator_t
objects_array_ascending_enumerator (objects_array_t * array)
{
objects_array_enumerator_t enumerator;
enumerator.array = array;
enumerator.is_sorted = 1;
enumerator.is_ascending = 1;
enumerator.index = 0;
_objects_array_make_sorted_slots (array);
return enumerator;
}
objects_array_enumerator_t
objects_array_descending_enumerator (objects_array_t * array)
{
objects_array_enumerator_t enumerator;
enumerator.array = array;
enumerator.is_sorted = 1;
enumerator.is_ascending = 0;
/* The `+ 1' is so that we have `0' as a known ending condition.
* See `_objects_array_enumerator_next_bucket()'. */
enumerator.index = array->element_count + 1;
_objects_array_make_sorted_slots (array);
return enumerator;
}
objects_array_enumerator_t
objects_array_enumerator (objects_array_t * array)
{
objects_array_enumerator_t enumerator;
enumerator.array = array;
enumerator.is_sorted = 0;
enumerator.is_ascending = 0;
enumerator.index = 0;
return enumerator;
}
int
objects_array_enumerator_next_index_and_element (objects_array_enumerator_t * enumerator,
size_t * index,
void **element)
{
objects_array_bucket_t *bucket;
bucket = _objects_array_enumerator_next_bucket (enumerator);
if (bucket != NULL)
{
if (element != NULL)
*element = bucket->element;
if (index != NULL)
*index = bucket->index;
return 1;
}
else
{
if (element != NULL)
*element = objects_array_not_an_element_marker (enumerator->array);
if (index != NULL)
*index = 0;
return 0;
}
}
int
objects_array_enumerator_next_element (objects_array_enumerator_t * enumerator,
void **element)
{
return objects_array_enumerator_next_index_and_element (enumerator,
NULL,
element);
}
int
objects_array_enumerator_next_index (objects_array_enumerator_t * enumerator,
size_t * index)
{
return objects_array_enumerator_next_index_and_element (enumerator,
index,
NULL);
}
/** Comparing **/
int
objects_array_is_equal_to_array (objects_array_t * array1, objects_array_t * array2)
{
size_t a, b;
void *m, *n;
objects_array_enumerator_t e, f;
a = objects_array_count (array1);
b = objects_array_count (array2);
if (a < b)
return (b - a);
if (a > b)
return (a - b);
/* Get ascending enumerators for each of the two arrays. */
e = objects_array_ascending_enumerator (array1);
e = objects_array_ascending_enumerator (array1);
while (objects_array_enumerator_next_index_and_element (&e, &a, &m)
&& objects_array_enumerator_next_index_and_element (&f, &b, &n))
{
int c, d;
if (a < b)
return (b - a);
if (a > b)
return (a - b);
c = objects_compare (objects_array_element_callbacks (array1), m, n, array1);
if (c != 0)
return c;
d = objects_compare (objects_array_element_callbacks (array2), n, m, array2);
if (d != 0)
return d;
}
return 0;
}
/** Mapping **/
objects_array_t *
objects_array_map_elements (objects_array_t * array,
void *(*fcn) (void *, void *),
void *user_data)
{
/* FIXME: Code this. */
return array;
}
/** Miscellaneous **/
objects_hash_t *
objects_hash_init_from_array (objects_hash_t * hash, objects_array_t * array)
{
objects_array_enumerator_t enumerator;
void *element;
/* NOTE: If ARRAY contains multiple elements of the same equivalence
* class, it is indeterminate which will end up in HASH. This
* shouldn't matter, though. */
enumerator = objects_array_enumerator (array);
/* Just walk through ARRAY's elements and add them to HASH. */
while (objects_array_enumerator_next_element (&enumerator, &element))
objects_hash_add_element (hash, element);
return hash;
}
// objects_chash_t *
// objects_chash_init_from_array (objects_chash_t * chash, objects_array_t * array)
// {
// objects_array_enumerator_t enumerator;
// void *element;
//
// /* NOTE: If ARRAY contains multiple elements of the same equivalence
// * class, it is indeterminate which will end up in CHASH. This
// * shouldn't matter, though. */
// enumerator = objects_array_enumerator (array);
//
// /* Just walk through ARRAY's elements and add them to CHASH. */
// while (objects_array_enumerator_next_element (&enumerator, &element))
// objects_chash_add_element (chash, element);
//
// return chash;
// }

77
Source/atoz.m Normal file
View file

@ -0,0 +1,77 @@
/* Handling the interface between allocs and zones.
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Sat Oct 15 10:34:02 EDT 1994
* Updated: Sat Feb 10 15:20:41 EST 1996
* Serial: 96.02.10.02
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <Foundation/NSObject.h>
#include <Foundation/NSString.h>
#include <Foundation/NSZone.h>
#include <objects/allocs.h>
/**** Function Implementations ***********************************************/
/** Handling Libobjects Allocs **/
void *
_objects_zone_malloc(size_t s, void *z)
{
return NSZoneMalloc((NSZone *)z, s);
}
void *
_objects_zone_calloc(size_t n, size_t s, void *z)
{
return NSZoneCalloc((NSZone *)z, n, s);
}
void *
_objects_zone_realloc(void *p, size_t s, void *z)
{
return NSZoneRealloc((NSZone *)z, p, s);
}
void
_objects_zone_free(void *p, void *z)
{
NSZoneFree((NSZone *)z, p);
return;
}
objects_allocs_t
objects_allocs_for_zone(NSZone *zone)
{
objects_allocs_t allocs =
{
_objects_zone_malloc,
_objects_zone_calloc,
_objects_zone_realloc,
_objects_zone_free,
zone
};
return allocs;
}

129
Source/callbacks-char_p.c Normal file
View file

@ -0,0 +1,129 @@
/* Callbacks for strings of `char'.
* Copyright (C) 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Sat Feb 10 22:04:38 EST 1996
* Updated: Sun Feb 11 01:40:09 EST 1996
* Serial: 96.02.11.05
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <stdlib.h>
#include <objects/callbacks.h>
/**** Type, Constant, and Macro Definitions **********************************/
objects_callbacks_t objects_callbacks_for_char_p =
{
(objects_hash_func_t) objects_char_p_hash,
(objects_compare_func_t) objects_char_p_compare,
(objects_is_equal_func_t) objects_char_p_is_equal,
(objects_retain_func_t) objects_char_p_retain,
(objects_release_func_t) objects_char_p_release,
(objects_describe_func_t) objects_char_p_describe,
0
};
/**** Function Implementations ***********************************************/
size_t
objects_char_p_hash(void *cptr)
{
register char *s = (char *) cptr;
register size_t h = 0;
register size_t c = 0;
while (*s != '\0')
h ^= *(s++) << (c++);
return h;
}
int
objects_char_p_compare(void *cptr, void *dptr)
{
register char *s = (char *) cptr;
register char *t = (char *) dptr;
if (s == t)
{
return 0;
}
else
{
register char c;
register char d;
while ((c = *(s++)) == (d = *(s++)))
if (c == '\0')
return 0;
return (c - d);
}
}
/* Determines whether or not CPTR is the same (`NUL'-terminated)
* character string as DPTR. Returns true if CPTR and DPTR are the same,
* and false otherwise. Note that we are performing no
* internationalization here. CPTR and DPTR are taken to be C strings
* in the default (seven or) eight bit character encoding. */
int
objects_char_p_is_equal(register void *cptr, register void *dptr)
{
register char *s = (char *) cptr;
register char *t = (char *) dptr;
if (s == t)
{
return 1;
}
else
{
register char c;
register char d;
while ((c = *(s++)) == (d = *(t++)))
if (c == '\0')
return 1;
return 0;
}
}
void *
objects_char_p_retain(void *cptr)
{
return cptr;
}
void
objects_char_p_release(void *cptr)
{
return;
}
void *
objects_char_p_describe(void *cptr)
{
/* FIXME: Code this. But first, figure out what it should do, OK? */
return 0;
}

93
Source/callbacks-id.m Normal file
View file

@ -0,0 +1,93 @@
/* Callbacks for the Objective-C object type.
* Copyright (C) 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Sat Feb 10 15:55:51 EST 1996
* Updated: Sun Feb 11 01:42:20 EST 1996
* Serial: 96.02.11.05
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <stdlib.h>
#include <objects/callbacks.h>
#include <objects/stdobjects.h>
/**** Type, Constant, and Macro Definitions **********************************/
objects_callbacks_t objects_callbacks_for_id =
{
(objects_hash_func_t) objects_id_hash,
(objects_compare_func_t) objects_id_compare,
(objects_is_equal_func_t) objects_id_is_equal,
(objects_retain_func_t) objects_id_retain,
(objects_release_func_t) objects_id_release,
(objects_describe_func_t) objects_id_describe,
0
};
/**** Function Implementations ***********************************************/
/* FIXME: It sure would be nice if we had a way of checking whether
* or not these objects responded to the messages we're sending them here.
* We need a way that is independent of whether we have GNUStep objects,
* NEXTSTEP objects, or GNU objects. We could certainly just use the
* same trick that the `respondsToSelector:' method uses, but I'd hoped
* that there was already a built-in call to do this sort of thing. */
size_t
objects_id_hash(void *obj)
{
return (size_t)[(id)obj hash];
}
int
objects_id_compare(void *obj, void *jbo)
{
return (int)[(id)obj compare:(id)jbo];
}
int
objects_id_is_equal(void *obj, void *jbo)
{
return (int)[(id)obj isEqual:(id)jbo];
}
void *
objects_id_retain(void *obj)
{
return [(id)obj retain];
}
void
objects_id_release(void *obj)
{
[(id)obj release];
return;
}
void *
objects_id_describe(void *obj)
{
/* FIXME: Harrumph. Make all of these describe functions live
* in harmony. Please. */
return [(id)obj describe];
}

84
Source/callbacks-int.c Normal file
View file

@ -0,0 +1,84 @@
/* Callbacks for `int' (and smaller) things.
* Copyright (C) 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Sat Feb 10 15:55:51 EST 1996
* Updated: Sun Feb 11 01:47:14 EST 1996
* Serial: 96.02.11.03
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <stdlib.h>
#include <objects/callbacks.h>
/**** Type, Constant, and Macro Definitions **********************************/
objects_callbacks_t objects_callbacks_for_int =
{
(objects_hash_func_t) objects_int_hash,
(objects_compare_func_t) objects_int_compare,
(objects_is_equal_func_t) objects_int_is_equal,
(objects_retain_func_t) objects_int_retain,
(objects_release_func_t) objects_int_release,
(objects_describe_func_t) objects_int_describe,
0
};
/**** Function Implementations ***********************************************/
size_t
objects_int_hash(void *i)
{
return (size_t)((int)i);
}
int
objects_int_compare(void *i, void *j)
{
return ((int)i) - ((int)j);
}
int
objects_int_is_equal(void *i, void *j)
{
return ((int)i) == ((int)j);
}
void *
objects_int_retain(void *i)
{
return i;
}
void
object_int_release(void *i)
{
return;
}
void *
objects_int_describe(void *i)
{
/* FIXME: Code this. */
return 0;
}

87
Source/callbacks-int_p.c Normal file
View file

@ -0,0 +1,87 @@
/* Callbacks for pointers to `int' and (maybe) structures whose first
* field is an `int'. Maybe.
* Copyright (C) 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Sat Feb 10 15:55:51 EST 1996
* Updated: Sun Feb 11 01:49:55 EST 1996
* Serial: 96.02.11.04
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <stdlib.h>
#include <objects/callbacks.h>
/**** Type, Constant, and Macro Definitions **********************************/
objects_callbacks_t objects_callbacks_for_int_p =
{
(objects_hash_func_t) objects_int_p_hash,
(objects_compare_func_t) objects_int_p_compare,
(objects_is_equal_func_t) objects_int_p_is_equal,
(objects_retain_func_t) objects_int_p_retain,
(objects_release_func_t) objects_int_p_release,
(objects_describe_func_t) objects_int_p_describe,
0
};
/**** Function Implementations ***********************************************/
size_t
objects_int_p_hash(void *iptr)
{
return (size_t)(*((int *)iptr));
}
/* FIXME: Are these next two correct? These seem rather useless to me. */
int
objects_int_p_compare(void *iptr, void *jptr)
{
return *((int *)iptr) - *((int *)jptr);
}
int
objects_int_p_is_equal(void *iptr, void *jptr)
{
return *((int *)iptr) == *((int *)jptr);
}
void *
objects_int_p_retain(void *iptr)
{
return iptr;
}
void
objects_int_p_release(void *iptr)
{
return;
}
void *
objects_int_p_describe(void *iptr)
{
/* FIXME: Code this. */
return 0;
}

129
Source/callbacks-void_p.c Normal file
View file

@ -0,0 +1,129 @@
/* Callbacks for pointers to `void'.
* Copyright (C) 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Sat Feb 10 22:04:38 EST 1996
* Updated: Sun Feb 11 01:09:34 EST 1996
* Serial: 96.02.11.03
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <stdlib.h>
#include <objects/callbacks.h>
/**** Type, Constant, and Macro Definitions **********************************/
objects_callbacks_t objects_callbacks_for_void_p =
{
(objects_hash_func_t) objects_void_p_hash,
(objects_compare_func_t) objects_void_p_compare,
(objects_is_equal_func_t) objects_void_p_is_equal,
(objects_retain_func_t) objects_void_p_retain,
(objects_release_func_t) objects_void_p_release,
0
};
objects_callbacks_t objects_callbacks_for_owned_void_p =
{
(objects_hash_func_t) objects_owned_void_p_hash,
(objects_compare_func_t) objects_owned_void_p_compare,
(objects_is_equal_func_t) objects_owned_void_p_is_equal,
(objects_retain_func_t) objects_owned_void_p_retain,
(objects_release_func_t) objects_owned_void_p_release,
0
};
/**** Function Implementations ***********************************************/
size_t
objects_void_p_hash(void *cptr)
{
return ((size_t) cptr)/4;
}
int
objects_void_p_compare(void *cptr, void *dptr)
{
if (cptr == dptr)
return 0;
else if (cptr < dptr)
return -1;
else /* if (cptr > dptr) */
return 1;
}
int
objects_void_p_is_equal(register void *cptr, register void *dptr)
{
return (cptr == dptr);
}
void *
objects_void_p_retain(void *cptr)
{
return cptr;
}
void
objects_void_p_release(void *cptr)
{
return;
}
size_t
objects_owned_void_p_hash(void *cptr)
{
/* We divide by 4 because many machines align
* memory on word boundaries. */
return ((size_t) cptr)/4;
}
int
objects_owned_void_p_compare(void *cptr, void *dptr)
{
if (cptr == dptr)
return 0;
else if (cptr < dptr)
return -1;
else /* if (cptr > dptr) */
return 1;
}
int
objects_owned_void_p_is_equal(register void *cptr, register void *dptr)
{
return (cptr == dptr);
}
void *
objects_owned_void_p_retain(void *cptr)
{
return cptr;
}
void
objects_owned_void_p_release(void *cptr)
{
free(cptr);
return;
}

141
Source/callbacks.c Normal file
View file

@ -0,0 +1,141 @@
/* Handling various types in a uniform manner.
* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Sun Oct 9 13:14:41 EDT 1994
* Updated: Sun Feb 11 01:33:41 EST 1996
* Serial: 96.02.10.07
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <objects/callbacks.h>
/**** Type, Constant, and Macro Definitions **********************************/
/* WARNING: Don't change this unless you know what you're getting into! */
static objects_callbacks_t ___objects_callbacks_standard =
{
(objects_hash_func_t) objects_void_p_hash,
(objects_compare_func_t) objects_void_p_compare,
(objects_is_equal_func_t) objects_void_p_is_equal,
(objects_retain_func_t) objects_void_p_retain,
(objects_release_func_t) objects_void_p_release,
(objects_describe_func_t) objects_void_p_describe,
0
};
/**** Function Implementations ***********************************************/
/** Getting the standard callbacks **/
objects_callbacks_t
objects_callbacks_standard(void)
{
return ___objects_callbacks_standard;
}
/** Standardizing callbacks **/
objects_callbacks_t
objects_callbacks_standardize(objects_callbacks_t callbacks)
{
if (callbacks.hash == 0)
callbacks.hash = objects_callbacks_standard().hash;
if (callbacks.compare == 0 && callbacks.is_equal == 0)
{
callbacks.compare = objects_callbacks_standard().compare;
callbacks.is_equal = objects_callbacks_standard().is_equal;
}
if (callbacks.retain == 0)
callbacks.retain = objects_callbacks_standard().retain;
if (callbacks.release == 0)
callbacks.release = objects_callbacks_standard().release;
return callbacks;
}
/** Using callbacks **/
size_t
objects_hash (objects_callbacks_t callbacks, void *thing, void *user_data)
{
if (callbacks.hash != 0)
return callbacks.hash(thing, user_data);
else
return objects_callbacks_standard().hash(thing, user_data);
}
int
objects_compare (objects_callbacks_t callbacks,
void *thing1,
void *thing2,
void *user_data)
{
if (callbacks.compare != 0)
return callbacks.compare(thing1, thing2, user_data);
else if (callbacks.is_equal != 0)
return !(callbacks.is_equal(thing1, thing2, user_data));
else
return objects_callbacks_standard().compare(thing1, thing2, user_data);
}
int
objects_is_equal (objects_callbacks_t callbacks,
void *thing1,
void *thing2,
void *user_data)
{
if (callbacks.is_equal != 0)
return callbacks.is_equal(thing1, thing2, user_data);
else if (callbacks.compare != 0)
return !(callbacks.compare(thing1, thing2, user_data));
else
return objects_callbacks_standard().is_equal(thing1, thing2, user_data);
}
void *
objects_retain (objects_callbacks_t callbacks, void *thing, void *user_data)
{
if (callbacks.retain != 0)
return callbacks.retain(thing, user_data);
else
return objects_callbacks_standard().retain(thing, user_data);
}
void
objects_release (objects_callbacks_t callbacks, void *thing, void *user_data)
{
if (callbacks.release != 0)
callbacks.release(thing, user_data);
else
objects_callbacks_standard().release(thing, user_data);
return;
}
void *
objects_describe(objects_callbacks_t callbacks, void *thing, void *user_data)
{
if (callbacks.release != 0)
return callbacks.describe(thing, user_data);
else
return objects_callbacks_standard().describe(thing, user_data);
}

1026
Source/data.c Normal file

File diff suppressed because it is too large Load diff

1037
Source/hash.c Normal file

File diff suppressed because it is too large Load diff

906
Source/list.c Normal file
View file

@ -0,0 +1,906 @@
/* A (pretty good) list implementation.
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Tue Sep 5 17:23:50 EDT 1995
* Updated: Sat Feb 10 14:50:36 EST 1996
* Serial: 96.02.10.03
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <objects/allocs.h>
#include <objects/callbacks.h>
#include <objects/list.h>
#include <objects/hash.h>
/**** Function Implementations ***********************************************/
/** Background functions **/
inline void
_objects_list_remove_node_from_its_list (objects_list_node_t * node)
{
if (node->list->first_node == node)
node->list->first_node = node->next_in_list;
if (node->list->last_node == node)
node->list->last_node = node->prev_in_list;
if (node->next_in_list != NULL)
node->next_in_list->prev_in_list = node->prev_in_list;
if (node->prev_in_list != NULL)
node->prev_in_list->next_in_list = node->next_in_list;
node->list->node_count -= 1;
node->list->element_count -= 1;
return;
}
objects_list_node_t *
_objects_list_new_node (objects_list_t * list, void *element)
{
objects_list_node_t *node;
node = objects_malloc (objects_list_allocs (list), sizeof (objects_list_node_t));
if (node != NULL)
{
node->list = list;
node->next_in_list = NULL;
node->prev_in_list = NULL;
objects_retain (objects_list_element_callbacks (list), element, list);
node->element = element;
}
return node;
}
void
_objects_list_free_node (objects_list_t * list, objects_list_node_t * node)
{
objects_release (objects_list_element_callbacks (node->list), node->element, node->list);
objects_free (objects_list_allocs (list), node);
return;
}
inline objects_list_node_t *
_objects_list_nth_node (objects_list_t * list, long int n)
{
objects_list_node_t *node;
if (n < 0)
{
node = list->last_node;
++n;
while (node != NULL && n != 0)
{
node = node->prev_in_list;
++n;
}
}
else
/* (n >= 0) */
{
node = list->first_node;
while (node != NULL && n != 0)
{
node = node->next_in_list;
--n;
}
}
return node;
}
inline objects_list_node_t *
_objects_list_nth_node_for_element (objects_list_t * list,
long int n,
void *element)
{
objects_list_node_t *node;
if (n < 0)
{
node = list->last_node;
++n;
while (node != NULL && n != 0)
{
if (objects_is_equal (objects_list_element_callbacks (list), element, node->element, list))
++n;
if (n != 0)
node = node->prev_in_list;
}
}
else
{
node = list->first_node;
while (node != NULL && n != 0)
{
if (objects_is_equal (objects_list_element_callbacks (list), element, node->element, list))
--n;
if (n != 0)
node = node->next_in_list;
}
}
return node;
}
inline objects_list_node_t *
_objects_list_enumerator_next_node (objects_list_enumerator_t * enumerator)
{
objects_list_node_t *node;
/* Remember ENUMERATOR's current node. */
node = enumerator->node;
/* If NODE is a real node, then we need to increment ENUMERATOR's
* current node to the next node in ENUMERATOR's list. */
if (node != NULL)
{
if (enumerator->forward)
enumerator->node = enumerator->node->next_in_list;
else /* (!enumerator->forward) */
enumerator->node = enumerator->node->prev_in_list;
}
/* Send back NODE. */
return node;
}
/** Gathering statistics **/
size_t
objects_list_count (objects_list_t * list)
{
return list->element_count;
}
size_t
objects_list_capacity (objects_list_t * list)
{
return list->element_count;
}
int
objects_list_check (objects_list_t * list)
{
return 0;
}
int
objects_list_contains_element (objects_list_t * list, void *element)
{
objects_list_enumerator_t enumerator;
void *member;
objects_list_enumerator (list);
while (objects_list_enumerator_next_element (&enumerator, &member))
if (objects_compare (objects_list_element_callbacks (list), element, member, list))
return 1;
return 0;
}
int
objects_list_is_empty (objects_list_t * list)
{
return objects_list_count (list) == 0;
}
/** Enumerating **/
objects_list_enumerator_t
objects_list_enumerator (objects_list_t * list)
{
return objects_list_forward_enumerator (list);
}
objects_list_enumerator_t
objects_list_forward_enumerator (objects_list_t * list)
{
objects_list_enumerator_t enumerator;
/* Update the access time. */
_objects_list_set_access_time (list);
/* Make sure ENUMERATOR knows its list. */
enumerator.list = list;
/* Start ENUMERATOR at LIST's first node. */
enumerator.node = list->first_node;
/* ENUMERATOR walks forward. */
enumerator.forward = 1;
return enumerator;
}
objects_list_enumerator_t
objects_list_reverse_enumerator (objects_list_t * list)
{
objects_list_enumerator_t enumerator;
/* Make sure ENUMERATOR knows its list. */
enumerator.list = list;
/* Start ENUMERATOR at LIST's first node. */
enumerator.node = list->last_node;
/* ENUMERATOR walks backward. */
enumerator.forward = 0;
return enumerator;
}
int
objects_list_enumerator_next_element (objects_list_enumerator_t * enumerator,
void **element)
{
objects_list_node_t *node;
/* Try and get the next node in the enumeration represented by
* ENUMERATOR. */
node = _objects_list_enumerator_next_node (enumerator);
if (node != NULL)
{
/* If NODE is real, then return the element it contains. */
if (element != NULL)
*element = node->element;
/* Indicate that the enumeration continues. */
return 1;
}
else
{
/* If NODE isn't real, then we return the ``bogus'' indicator. */
if (element != NULL)
*element = objects_list_not_an_element_marker (enumerator->list);
/* Indicate that the enumeration is over. */
return 0;
}
}
/** Searching **/
void *
objects_list_element (objects_list_t * list, void *element)
{
objects_list_node_t *node;
node = _objects_list_nth_node_for_element (list, 0, element);
if (node != NULL)
return node->element;
else
return objects_list_not_an_element_marker (list);
}
void *
objects_list_nth_element (objects_list_t * list, long int n)
{
objects_list_node_t *node;
node = _objects_list_nth_node (list, n);
if (node != NULL)
return node->element;
else
return objects_list_not_an_element_marker (list);
}
void *
objects_list_first_element (objects_list_t * list)
{
if (list->first_node != NULL)
return list->first_node->element;
else
return objects_list_not_an_element_marker (list);
}
void *
objects_list_last_element (objects_list_t * list)
{
if (list->last_node != NULL)
return list->last_node->element;
else
return objects_list_not_an_element_marker (list);
}
/** Obtaining elements **/
void **
objects_list_all_elements (objects_list_t * list)
{
objects_list_enumerator_t enumerator;
void **array;
size_t i;
array = objects_calloc (objects_list_allocs (list),
objects_list_count (list) + 1,
sizeof (void *));
for (i = 0; objects_list_enumerator_next_element (&enumerator, array + i); ++i);
return array;
}
/** Adding elements **/
void *
objects_list_append_element (objects_list_t * list, void *element)
{
return objects_list_at_index_insert_element (list, -1, element);
}
void *
objects_list_append_element_if_absent (objects_list_t * list, void *element)
{
return objects_list_at_index_insert_element_if_absent (list, -1, element);
}
void *
objects_list_prepend_element (objects_list_t * list, void *element)
{
return objects_list_at_index_insert_element (list, 0, element);
}
void *
objects_list_prepend_element_if_absent (objects_list_t * list, void *element)
{
return objects_list_at_index_insert_element_if_absent (list, 0, element);
}
void *
objects_list_at_index_insert_element (objects_list_t * list,
long int n,
void *element)
{
objects_list_node_t *anode, *bnode, *new_node, *node;
node = _objects_list_nth_node (list, n);
new_node = _objects_list_new_node (list, element);
if (new_node == NULL)
objects_abort ();
if (n < 0)
{
if (node == NULL)
{
anode = NULL;
bnode = list->first_node;
}
else
/* (node != NULL) */
{
anode = node;
bnode = node->next_in_list;
}
}
else
/* (n >= 0) */
{
if (node == NULL)
{
anode = list->last_node;
bnode = NULL;
}
else
/* (node != NULL) */
{
anode = node->prev_in_list;
bnode = node;
}
}
new_node->prev_in_list = anode;
new_node->next_in_list = bnode;
if (anode != NULL)
anode->next_in_list = new_node;
if (bnode != NULL)
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;
}
void *
objects_list_at_index_insert_element_if_absent (objects_list_t * list,
long int n,
void *element)
{
if (!objects_list_contains_element (list, element))
return objects_list_at_index_insert_element (list, n, element);
else
return objects_list_element (list, element);
}
/** Removing elements **/
void
objects_list_remove_nth_occurrance_of_element (objects_list_t * list,
long int n,
void *element)
{
objects_list_node_t *node;
node = _objects_list_nth_node_for_element (list, n, element);
if (node != NULL)
{
_objects_list_remove_node_from_its_list (node);
_objects_list_free_node (list, node);
}
return;
}
void
objects_list_remove_element (objects_list_t * list, void *element)
{
objects_list_remove_nth_occurrance_of_element (list, 0, element);
return;
}
inline void
objects_list_remove_nth_element (objects_list_t * list, long int n)
{
objects_list_node_t *node;
node = _objects_list_nth_node (list, n);
if (node != NULL)
{
_objects_list_remove_node_from_its_list (node);
_objects_list_free_node (list, node);
}
return;
}
void
objects_list_remove_first_element (objects_list_t * list)
{
objects_list_remove_nth_element (list, 0);
return;
}
void
objects_list_remove_last_element (objects_list_t * list)
{
objects_list_remove_nth_element (list, -1);
return;
}
/** Emptying **/
void
objects_list_empty (objects_list_t * list)
{
objects_list_enumerator_t enumerator;
objects_list_node_t *node;
enumerator = objects_list_enumerator (list);
while ((node = _objects_list_enumerator_next_node (&enumerator)) != NULL)
{
_objects_list_remove_node_from_its_list (node);
_objects_list_free_node (list, node);
}
return;
}
/** Replacing **/
void
objects_list_replace_nth_occurrance_of_element (objects_list_t * list,
long int n,
void *old_element,
void *new_element)
{
objects_list_node_t *node;
node = _objects_list_nth_node_for_element (list, n, old_element);
if (node != NULL)
{
objects_retain (objects_list_element_callbacks (list), new_element, list);
objects_release (objects_list_element_callbacks (list), node->element, list);
node->element = new_element;
}
return;
}
void
objects_list_replace_element (objects_list_t * list,
void *old_element,
void *new_element)
{
objects_list_replace_nth_occurrance_of_element (list, 0, old_element, new_element);
return;
}
void
objects_list_replace_nth_element (objects_list_t * list,
long int n,
void *new_element)
{
objects_list_node_t *node;
node = _objects_list_nth_node (list, n);
if (node != NULL)
{
objects_retain (objects_list_element_callbacks (list), new_element, list);
objects_release (objects_list_element_callbacks (list), node->element, list);
node->element = new_element;
}
return;
}
void
objects_list_replace_first_element (objects_list_t * list,
void *new_element)
{
objects_list_replace_nth_element (list, 0, new_element);
return;
}
void
objects_list_replace_last_element (objects_list_t * list,
void *new_element)
{
objects_list_replace_nth_element (list, -1, new_element);
return;
}
/** Creating **/
objects_list_t *
objects_list_alloc_with_allocs (objects_allocs_t allocs)
{
objects_list_t *list;
list = _objects_list_alloc_with_allocs (allocs);
return list;
}
objects_list_t *
objects_list_alloc (void)
{
return objects_list_alloc_with_allocs (objects_allocs_standard ());
}
objects_list_t *
objects_list (void)
{
return objects_list_init (objects_list_alloc ());
}
objects_list_t *
objects_list_with_allocs (objects_allocs_t allocs)
{
return objects_list_init (objects_list_alloc_with_allocs (allocs));
}
objects_list_t *
objects_list_with_allocs_with_callbacks (objects_allocs_t allocs,
objects_callbacks_t callbacks)
{
return objects_list_init_with_callbacks (objects_list_alloc_with_allocs (allocs),
callbacks);
}
objects_list_t *
objects_list_with_callbacks (objects_callbacks_t callbacks)
{
return objects_list_init_with_callbacks (objects_list_alloc (), callbacks);
}
objects_list_t *
objects_list_of_char_p (void)
{
return objects_list_with_callbacks (objects_callbacks_for_char_p);
}
objects_list_t *
objects_list_of_int (void)
{
return objects_list_with_callbacks (objects_callbacks_for_int);
}
objects_list_t *
objects_list_of_void_p (void)
{
return objects_list_with_callbacks (objects_callbacks_for_void_p);
}
objects_list_t *
objects_list_of_owned_void_p (void)
{
return objects_list_with_callbacks (objects_callbacks_for_owned_void_p);
}
objects_list_t *
objects_list_of_id (void)
{
return objects_list_with_callbacks (objects_callbacks_for_id);
}
/** Initializing **/
objects_list_t *
objects_list_init (objects_list_t * list)
{
return objects_list_init_with_callbacks (list, objects_callbacks_standard());
}
objects_list_t *
objects_list_init_with_callbacks (objects_list_t * list, objects_callbacks_t callbacks)
{
if (list != NULL)
{
list->callbacks = callbacks;
list->element_count = 0;
list->node_count = 0;
list->first_node = NULL;
list->last_node = NULL;
}
return list;
}
objects_list_t *
objects_list_init_from_list (objects_list_t * list, objects_list_t * old_list)
{
objects_list_enumerator_t enumerator;
void *element;
if (list != NULL)
{
list->callbacks = objects_list_element_callbacks (old_list);
list->element_count = 0;
list->node_count = 0;
list->first_node = NULL;
list->last_node = NULL;
if (old_list != NULL)
{
/* Get a forward enumerator for OLD_LIST. */
enumerator = objects_list_forward_enumerator (old_list);
/* Walk from the beginning to the end of OLD_LIST, and add each
* element to the end of LIST. */
while (objects_list_enumerator_next_element (&enumerator, &element))
objects_list_at_index_insert_element (list, -1, element);
}
}
return list;
}
/** Destroying **/
void
objects_list_dealloc (objects_list_t * list)
{
/* Empty LIST out. */
objects_list_empty (list);
/* Get rid of LIST. */
_objects_list_dealloc (list);
return;
}
/** Comparing **/
int
objects_list_is_equal_to_list (objects_list_t * list, objects_list_t * other_list)
{
/* FIXME: Code this. */
return 0;
}
/** Concatenating **/
objects_list_t *
objects_list_append_list (objects_list_t * base_list, objects_list_t * suffix_list)
{
return objects_list_at_index_insert_list (base_list, -1, suffix_list);
}
objects_list_t *
objects_list_prepend_list (objects_list_t * base_list, objects_list_t * prefix_list)
{
return objects_list_at_index_insert_list (base_list, 0, prefix_list);
}
/* FIXME: I was lazy when I wrote this next one. It can easily be
* sped up. Do it. */
objects_list_t *
objects_list_at_index_insert_list (objects_list_t * base_list,
long int n,
objects_list_t * infix_list)
{
objects_list_enumerator_t enumerator;
void *element;
if (n < 0)
enumerator = objects_list_forward_enumerator (infix_list);
else /* (n >= 0) */
enumerator = objects_list_reverse_enumerator (infix_list);
while (objects_list_enumerator_next_element (&enumerator, &element))
objects_list_at_index_insert_element (base_list, n, element);
return base_list;
}
/** Copying **/
objects_list_t *
objects_list_copy (objects_list_t * old_list)
{
/* FIXME: Should I be using `objects_allocs_standard()' or
* `objects_list_allocs(old_list)'? */
return objects_list_copy_with_allocs (old_list, objects_list_allocs (old_list));
}
objects_list_t *
objects_list_copy_with_allocs (objects_list_t * old_list, objects_allocs_t allocs)
{
objects_list_t *list;
/* Allocate a new (low-level) copy of OLD_LIST. */
list = _objects_list_copy_with_allocs (old_list, allocs);
/* Fill it in. */
return objects_list_init_from_list (list, old_list);
}
/** Mapping **/
objects_list_t *
objects_list_map_elements (objects_list_t * list,
void *(*fcn) (void *, void *),
void *user_data)
{
objects_list_enumerator_t enumerator;
objects_list_node_t *node;
enumerator = objects_list_enumerator (list);
while ((node = _objects_list_enumerator_next_node (&enumerator)) != NULL)
{
void *element;
element = (*fcn) (node->element, user_data);
/* NOTE: I'm accessing the callbacks directly for a little
* efficiency. */
objects_retain (list->callbacks, element, list);
objects_release (list->callbacks, node->element, list);
node->element = element;
}
return list;
}
/** Creating other collections from lists **/
objects_hash_t *
objects_hash_init_from_list (objects_hash_t * hash, objects_list_t * list)
{
if (hash != NULL)
{
objects_list_enumerator_t enumerator;
void *element;
/* Make a note of the callbacks for HASH. */
hash->callbacks = objects_list_element_callbacks (list);
/* Zero out the various counts. */
hash->node_count = 0;
hash->bucket_count = 0;
hash->element_count = 0;
/* Zero out the pointers. */
hash->first_node = NULL;
hash->buckets = NULL;
/* Resize HASH to the given CAPACITY. */
objects_hash_resize (hash, objects_list_capacity (list));
/* Get an element enumerator for LIST. */
enumerator = objects_list_enumerator (list);
/* Add LIST's elements to HASH, one at a time. Note that if LIST
* contains multiple elements from the same equivalence class, it
* is indeterminate which will end up in HASH. But this shouldn't
* be a problem. */
while (objects_list_enumerator_next_element (&enumerator, &element))
objects_hash_add_element (hash, element);
}
/* Return the newly initialized HASH. */
return hash;
}
// objects_chash_t *
// objects_chash_init_from_list (objects_chash_t * chash, objects_list_t * list)
// {
// if (chash != NULL)
// {
// objects_list_enumerator_t enumerator;
// void *element;
//
// /* Make a note of the callbacks for CHASH. */
// chash->callbacks = objects_list_element_callbacks (list);
//
// /* Zero out the various counts. */
// chash->node_count = 0;
// chash->bucket_count = 0;
// chash->element_count = 0;
//
// /* Zero out the pointers. */
// chash->first_node = NULL;
// chash->buckets = NULL;
//
// /* Resize CHASH to the given CAPACITY. */
// objects_chash_resize (chash, objects_list_capacity (list));
//
// /* Get an element enumerator for LIST. */
// enumerator = objects_list_enumerator (list);
//
// /* Add LIST's elements to CHASH, one at a time. Note that if LIST
// * contains multiple elements from the same equivalence class, it
// * is indeterminate which will end up in CHASH. But this shouldn't
// * be a problem. */
// while (objects_list_enumerator_next_element (&enumerator, &element))
// objects_chash_add_element (chash, element);
// }
//
// /* Return the newly initialized CHASH. */
// return chash;
// }

1235
Source/map.c Normal file

File diff suppressed because it is too large Load diff

368
Source/md5.c Normal file
View file

@ -0,0 +1,368 @@
/* md5.c - Functions to compute MD5 message digest of files or memory blocks
according to the definition of MD5 in RFC 1321 from April 1992.
Copyright (C) 1995 Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#if STDC_HEADERS
#include <stdlib.h>
#include <string.h>
#else
#ifndef HAVE_MEMCPY
#define memcpy(d, s, n) bcopy ((s), (d), (n))
#endif
#endif
#include "md5.h"
#ifdef WORDS_BIGENDIAN
#define SWAP(n) \
(((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
#else
#define SWAP(n) (n)
#endif
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. (RFC 1321, 3.1: Step 1) */
static const unsigned char fillbuf[64] =
{0x80, 0 /* , 0, 0, ... */ };
/* Initialize structure containing state of computation.
(RFC 1321, 3.3: Step 3) */
void
md5_init_ctx (ctx)
struct md5_ctx *ctx;
{
ctx->A = 0x67452301;
ctx->B = 0xefcdab89;
ctx->C = 0x98badcfe;
ctx->D = 0x10325476;
}
/* Put result from CTX in first 16 bytes following RESBUF. The result must
be in little endian byte order. */
void *
md5_read_ctx (ctx, resbuf)
const struct md5_ctx *ctx;
void *resbuf;
{
((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
return resbuf;
}
/* Compute MD5 message digest for bytes read from STREAM. The
resulting message digest number will be written into the 16 bytes
beginning at RESBLOCK. */
int
md5_stream (stream, resblock)
FILE *stream;
void *resblock;
{
/* Important: BLOCKSIZE must be a multiple of 64. */
#define BLOCKSIZE 4096
struct md5_ctx ctx;
md5_uint32 len[2];
char buffer[BLOCKSIZE + 72];
size_t pad, sum;
/* Initialize the computation context. */
md5_init_ctx (&ctx);
len[0] = 0;
len[1] = 0;
/* Iterate over full file contents. */
while (1)
{
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
computation function processes the whole buffer so that with the
next round of the loop another block can be read. */
size_t n;
sum = 0;
/* Read block. Take care for partial reads. */
do
{
n = fread (buffer, 1, BLOCKSIZE - sum, stream);
sum += n;
}
while (sum < BLOCKSIZE && n != 0);
if (n == 0 && ferror (stream))
return 1;
/* RFC 1321 specifies the possible length of the file up to 2^64 bits.
Here we only compute the number of bytes. Do a double word
increment. */
len[0] += sum;
if (len[0] < sum)
++len[1];
/* If end of file is reached, end the loop. */
if (n == 0)
break;
/* Process buffer with BLOCKSIZE bytes. Note that
BLOCKSIZE % 64 == 0
*/
md5_process_block (buffer, BLOCKSIZE, &ctx);
}
/* We can copy 64 byte because the buffer is always big enough. FILLBUF
contains the needed bits. */
memcpy (&buffer[sum], fillbuf, 64);
/* Compute amount of padding bytes needed. Alignment is done to
(N + PAD) % 64 == 56
There is always at least one byte padded. I.e. even the alignment
is correctly aligned 64 padding bytes are added. */
pad = sum & 63;
pad = pad >= 56 ? 64 + 56 - pad : 56 - pad;
/* Put the 64-bit file length in *bits* at the end of the buffer. */
*(md5_uint32 *) & buffer[sum + pad] = SWAP (len[0] << 3);
*(md5_uint32 *) & buffer[sum + pad + 4] = SWAP ((len[1] << 3)
| (len[0] >> 29));
/* Process last bytes. */
md5_process_block (buffer, sum + pad + 8, &ctx);
/* Construct result in desired memory. */
md5_read_ctx (&ctx, resblock);
return 0;
}
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
void *
md5_buffer (buffer, len, resblock)
const char *buffer;
size_t len;
void *resblock;
{
struct md5_ctx ctx;
char restbuf[64 + 72];
size_t blocks = len & ~63;
size_t pad, rest;
/* Initialize the computation context. */
md5_init_ctx (&ctx);
/* Process whole buffer but last len % 64 bytes. */
md5_process_block (buffer, blocks, &ctx);
/* REST bytes are not processed yet. */
rest = len - blocks;
/* Copy to own buffer. */
memcpy (restbuf, &buffer[blocks], rest);
/* Append needed fill bytes at end of buffer. We can copy 64 byte
because the buffer is always big enough. */
memcpy (&restbuf[rest], fillbuf, 64);
/* PAD bytes are used for padding to correct alignment. Note that
always at least one byte is padded. */
pad = rest >= 56 ? 64 + 56 - rest : 56 - rest;
/* Put length of buffer in *bits* in last eight bytes. */
*(md5_uint32 *) & restbuf[rest + pad] = (md5_uint32) SWAP (len << 3);
*(md5_uint32 *) & restbuf[rest + pad + 4] = (md5_uint32) SWAP (len >> 29);
/* Process last bytes. */
md5_process_block (restbuf, rest + pad + 8, &ctx);
/* Put result in desired memory area. */
return md5_read_ctx (&ctx, resblock);
}
/* These are the four functions used in the four steps of the MD5 algorithm
and defined in the RFC 1321. The first function is a little bit optimized
(as found in Colin Plumbs public domain implementation). */
/* #define FF(b, c, d) ((b & c) | (~b & d)) */
#define FF(b, c, d) (d ^ (b & (c ^ d)))
#define FG(b, c, d) FF (d, b, c)
#define FH(b, c, d) (b ^ c ^ d)
#define FI(b, c, d) (c ^ (b | ~d))
/* Process LEN bytes of BUFFER, accumulating context into CTX.
It is assumed that LEN % 64 == 0. */
void
md5_process_block (buffer, len, ctx)
const void *buffer;
size_t len;
struct md5_ctx *ctx;
{
md5_uint32 correct_words[16];
const md5_uint32 *words = buffer;
size_t nwords = len / sizeof (md5_uint32);
const md5_uint32 *endp = words + nwords;
md5_uint32 A = ctx->A;
md5_uint32 B = ctx->B;
md5_uint32 C = ctx->C;
md5_uint32 D = ctx->D;
/* Process all bytes in the buffer with 64 bytes in each round of
the loop. */
while (words < endp)
{
md5_uint32 *cwp = correct_words;
md5_uint32 A_save = A;
md5_uint32 B_save = B;
md5_uint32 C_save = C;
md5_uint32 D_save = D;
/* First round: using the given function, the context and a constant
the next context is computed. Because the algorithms processing
unit is a 32-bit word and it is determined to work on words in
little endian byte order we perhaps have to change the byte order
before the computation. To reduce the work for the next steps
we store the swapped words in the array CORRECT_WORDS. */
#define OP(a, b, c, d, s, T) \
do \
{ \
a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
++words; \
CYCLIC (a, s); \
a += b; \
} \
while (0)
/* It is unfortunate that C does not provide an operator for
cyclic rotation. Hope the C compiler is smart enough. */
#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
/* Before we start, one word to the strange constants.
They are defined in RFC 1321 as
T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
*/
/* Round 1. */
OP (A, B, C, D, 7, 0xd76aa478);
OP (D, A, B, C, 12, 0xe8c7b756);
OP (C, D, A, B, 17, 0x242070db);
OP (B, C, D, A, 22, 0xc1bdceee);
OP (A, B, C, D, 7, 0xf57c0faf);
OP (D, A, B, C, 12, 0x4787c62a);
OP (C, D, A, B, 17, 0xa8304613);
OP (B, C, D, A, 22, 0xfd469501);
OP (A, B, C, D, 7, 0x698098d8);
OP (D, A, B, C, 12, 0x8b44f7af);
OP (C, D, A, B, 17, 0xffff5bb1);
OP (B, C, D, A, 22, 0x895cd7be);
OP (A, B, C, D, 7, 0x6b901122);
OP (D, A, B, C, 12, 0xfd987193);
OP (C, D, A, B, 17, 0xa679438e);
OP (B, C, D, A, 22, 0x49b40821);
/* For the second to fourth round we have the possibly swapped words
in CORRECT_WORDS. Redefine the macro to take an additional first
argument specifying the function to use. */
#undef OP
#define OP(f, a, b, c, d, k, s, T) \
do \
{ \
a += f (b, c, d) + correct_words[k] + T; \
CYCLIC (a, s); \
a += b; \
} \
while (0)
/* Round 2. */
OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
OP (FG, D, A, B, C, 6, 9, 0xc040b340);
OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
OP (FG, D, A, B, C, 10, 9, 0x02441453);
OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
/* Round 3. */
OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
OP (FH, D, A, B, C, 8, 11, 0x8771f681);
OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
OP (FH, B, C, D, A, 6, 23, 0x04881d05);
OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
/* Round 4. */
OP (FI, A, B, C, D, 0, 6, 0xf4292244);
OP (FI, D, A, B, C, 7, 10, 0x432aff97);
OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
OP (FI, C, D, A, B, 6, 15, 0xa3014314);
OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
/* Add the starting values of the context. */
A += A_save;
B += B_save;
C += C_save;
D += D_save;
}
/* Put checksum in context given as argument. */
ctx->A = A;
ctx->B = B;
ctx->C = C;
ctx->D = D;
}

115
Source/md5.h Normal file
View file

@ -0,0 +1,115 @@
/* md5.h - Declaration of functions and data types used for MD5 sum
computing library functions.
Copyright (C) 1995 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _MD5_H
#define _MD5_H
#include <stdio.h>
#if defined HAVE_LIMITS_H || _LIBC
#include <limits.h>
#endif
/* The following contortions are an attempt to use the C preprocessor
to determine an unsigned integral type that is 32 bits wide. An
alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
doing that would require that the configure script compile and *run*
the resulting executable. Locally running cross-compiled executables
is usually not possible. */
#if defined __STDC__ && __STDC__
#define UINT_MAX_32_BITS 4294967295U
#else
#define UINT_MAX_32_BITS 0xFFFFFFFF
#endif
/* If UINT_MAX isn't defined, assume it's a 32-bit type.
This should be valid for all systems GNU cares about because
that doesn't include 16-bit systems, and only modern systems
(that certainly have <limits.h>) have 64+-bit integral types. */
#ifndef UINT_MAX
#define UINT_MAX UINT_MAX_32_BITS
#endif
#if UINT_MAX == UINT_MAX_32_BITS
typedef unsigned int md5_uint32;
#else
#if USHRT_MAX == UINT_MAX_32_BITS
typedef unsigned short md5_uint32;
#else
#if ULONG_MAX == UINT_MAX_32_BITS
typedef unsigned long md5_uint32;
#else
/* The following line is intended to evoke an error.
Using #error is not portable enough. */
"Cannot determine unsigned 32-bit data type."
#endif
#endif
#endif
#undef __P
#if defined (__STDC__) && __STDC__
#define __P(x) x
#else
#define __P(x) ()
#endif
/* Structure to save state of computation between the single steps. */
struct md5_ctx
{
md5_uint32 A;
md5_uint32 B;
md5_uint32 C;
md5_uint32 D;
};
/*
* The following three functions are build up the low level used in
* the functions `md5_stream' and `md5_buffer'.
*/
/* Initialize structure containing state of computation.
(RFC 1321, 3.3: Step 3) */
void md5_init_ctx __P ((struct md5_ctx * ctx));
/* Starting with the result of former calls of this function (or the
initialzation function update the context for the next LEN bytes
starting at BUFFER.
It is necessary that LEN is a multiple of 64!!! */
void md5_process_block __P ((const void *buffer, size_t len,
struct md5_ctx * ctx));
/* Put result from CTX in first 16 bytes following RESBUF. The result is
always in little endian byte order, so that a byte-wise output yields
to the wanted ASCII representation of the message digest. */
void *md5_read_ctx __P ((const struct md5_ctx * ctx, void *resbuf));
/* Compute MD5 message digest for bytes read from STREAM. The
resulting message digest number will be written into the 16 bytes
beginning at RESBLOCK. */
int md5_stream __P ((FILE * stream, void *resblock));
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
void *md5_buffer __P ((const char *buffer, size_t len, void *resblock));
#endif

59
Source/number.c Normal file
View file

@ -0,0 +1,59 @@
/* Structure counters and functions for getting at them.
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Sun Dec 3 00:23:13 EST 1995
* Updated: Sat Feb 10 13:52:15 EST 1996
* Serial: 96.02.10.01
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <objects/number.h>
/**** Type, Constant, and Macro Definitions **********************************/
size_t ___objects_number_allocated = 0;
size_t ___objects_number_deallocated = 0;
size_t ___objects_number_serial = 0;
/**** Function Implementations ***********************************************/
/* Returns the number of Libobjects structures allocated. */
size_t
objects_number_allocated(void)
{
return ___objects_number_allocated;
}
/* Returns the number of Libobjects structures deallocated. */
size_t
objects_number_deallocated(void)
{
return ___objects_number_deallocated;
}
/* Returns the next serial number to be handed out. */
size_t
objects_number_serial(void)
{
return ___objects_number_serial;
}

276
Source/x-basics.c.in Normal file
View file

@ -0,0 +1,276 @@
/* Basic functions for @XX@ structures.
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Tue Dec 12 12:33:01 EST 1995
* Updated: Sat Feb 10 09:08:35 EST 1996
* Serial: 96.02.10.01
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <objects/allocs.h>
#include <objects/number.h>
#include <objects/magic.h>
#include <objects/@XX@.h>
/**** Type, Constant, and Macro Definitions **********************************/
#define __@XX@__ 1
/**** Function Implementations ***********************************************/
/** Magic **/
/* Returns XX's magic number. */
int
objects_@XX@_magic (objects_@XX@_t *xx)
{
return xx->magic;
}
/** Allocs **/
/* Returns the allocs used to create and maintain XX. */
objects_allocs_t
objects_@XX@_allocs (objects_@XX@_t *xx)
{
return xx->allocs;
}
/** Names **/
/* Returns the name that was given to XX. */
const char *
objects_@XX@_name (objects_@XX@_t *xx)
{
return xx->name;
}
/* Gives XX a name. Space is allocated, and the contents of the
* NUL-terminated NAME are copied. Deallocating XX frees up the
* space. I.e., it is not the responsibility of the programmer to
* keep track of space allocated for this procedure. */
const char *
objects_@XX@_set_name (objects_@XX@_t *xx, const char *name)
{
/* Figure out how much space we need. */
size_t len = strlen (name);
char *old_name = xx->name;
/* Allocate space for the new name. (Don't forget the extra space
* for the terminating `NUL'. */
xx->name = (char *) objects_malloc (xx->allocs, len + 1);
/* If the allocation was successful, copy the new name over and get
* rid of the old name. */
if (xx->name != NULL)
{
/* Copy over the new name. */
strncpy (xx->name, name, len);
/* Free up any space we set aside for any older name. */
if (old_name != NULL)
objects_free (xx->allocs, old_name);
}
return xx->name;
}
/* Takes away XX's name. */
void
objects_@XX@_unset_name (objects_@XX@_t *xx)
{
/* Free it. */
if (xx->name != NULL)
objects_free (xx->allocs, xx->name);
/* Reset it. */
xx->name = NULL;
return;
}
/** Number **/
/* Returns the (process-wide) unique number given to the Libobjects
* structure XX. See <objects/number.h> for more info. */
size_t
objects_@XX@_number (objects_@XX@_t *xx)
{
return xx->number;
}
/* Gives XX a new (process-wide) unique number. Numbers are not
* reused. See <objects/number.h> for more info. */
size_t
_objects_@XX@_set_serial_number (objects_@XX@_t *xx)
{
size_t old_number;
old_number = xx->number;
xx->number = (___objects_number_serial)++;
return old_number;
}
/** Extras **/
/* Sets the callbacks associated with XX's ``extra''. NOTE: This must
* be done before calling `objects_@XX@_set_extra()', as these callbacks
* are used in that routine. */
objects_callbacks_t
objects_@XX@_set_extra_callbacks (objects_@XX@_t *xx, objects_callbacks_t callbacks)
{
objects_callbacks_t old_callbacks;
/* Remember the old callbacks for later. */
old_callbacks = xx->extra_callbacks;
/* Set the new callbacks. */
xx->extra_callbacks = callbacks;
/* Release the old contents. */
objects_release (old_callbacks, xx->extra, xx);
/* Set the contents to something noticible. */
xx->extra = (xx->extra_callbacks).not_an_item_marker;
return old_callbacks;
}
/* Returns the callbacks associated with XX's ``extra''. */
objects_callbacks_t
objects_@XX@_extra_callbacks (objects_@XX@_t *xx, objects_callbacks_t callbacks)
{
return xx->extra_callbacks;
}
/* Returns XX's ``extra'', a little extra space that each Libobjects
* structure carries around with it. Its use is
* implementation-dependent. */
void *
objects_@XX@_extra (objects_@XX@_t *xx)
{
return xx->extra;
}
/* Sets XX's ``extra'', a little extra space that each Libobjects structure
* carries around with it. Its use is implementation-dependent. */
void *
objects_@XX@_set_extra (objects_@XX@_t *xx, void *extra)
{
void *old_extra;
/* Out with the old, and in with the new. */
old_extra = xx->extra;
xx->extra = objects_retain (xx->extra_callbacks, extra, xx);
objects_release (xx->extra_callbacks, old_extra, xx);
return old_extra;
}
/* Resets XX's ``extra''. */
void
objects_@XX@_unset_extra (objects_@XX@_t *xx)
{
/* Release XX's extra. */
objects_release (xx->extra_callbacks, xx->extra, xx);
/* Reset XX's extra. */
xx->extra = (xx->extra_callbacks).not_an_item_marker;
return;
}
/** Low-level Creation and Destruction **/
/* Handles the universal, low-level allocation of Libobjects structures. */
objects_@XX@_t *
_objects_@XX@_alloc_with_allocs (objects_allocs_t allocs)
{
objects_@XX@_t *xx;
/* Try to allocate some space for XX. */
xx = objects_malloc (allocs, sizeof (objects_@XX@_t));
/* The `objects_malloc()' was successful. */
if (xx != NULL)
{
_objects_@XX@_set_serial_number (xx);
xx->magic = _OBJECTS_MAGIC_@XX@;
xx->name = NULL;
xx->allocs = allocs;
xx->extra_callbacks = objects_callbacks_for_void_p;
xx->extra = 0;
/* Increment the counter of allocated Libobjects structures. */
++(___objects_number_allocated);
}
return xx;
}
/* Handles the universal, low-level deallocation of Libobjects structures. */
void
_objects_@XX@_dealloc (objects_@XX@_t *xx)
{
/* Make sure XX is valid. */
if (xx != NULL)
{
/* Free up any space we needed to keep track of XX's name. */
if (xx->name != NULL)
objects_free (objects_@XX@_allocs (xx), xx->name);
/* Release XX's extra. */
objects_@XX@_unset_extra (xx);
/* Free up XX itself. */
objects_free (objects_@XX@_allocs (xx), xx);
/* Increment the counter of deallocated Libobjects structures. */
++(___objects_number_deallocated);
}
return;
}
/* Handles the low-level copying of Libobjects structures. */
objects_@XX@_t *
_objects_@XX@_copy_with_allocs (objects_@XX@_t *xx, objects_allocs_t allocs)
{
objects_@XX@_t *new;
/* Create a new structure. */
new = _objects_@XX@_alloc_with_allocs (allocs);
if (new != NULL)
{
/* Copy over XX's name. */
objects_@XX@_set_name (new, objects_@XX@_name (xx));
/* Copy over XX's extras. */
objects_@XX@_set_extra_callbacks (new, xx->extra_callbacks);
objects_@XX@_set_extra (new, xx->extra);
}
return new;
}

89
Source/x-callbacks.c.in Normal file
View file

@ -0,0 +1,89 @@
/* Getting callbacks from @YY@ structures.
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
*
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
* Created: Mon Dec 11 02:44:09 EST 1995
* Updated: Sat Feb 10 10:08:59 EST 1996
* Serial: 96.02.10.01
*
* This file is part of the GNU Objective C Class Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/**** Included Headers *******************************************************/
#include <objects/callbacks.h>
#include <objects/@YY@.h>
/**** Type, Constant, and Macro Definitions **********************************/
#define __@YY@__ 1
/**** Function Implementations ***********************************************/
#ifdef __map__
/** Callbacks **/
/* Returns the callbacks associated with YY's keys. */
objects_callbacks_t
objects_@YY@_key_callbacks (objects_@YY@_t * yy)
{
return yy->key_callbacks;
}
/* Returns the ``bogus'' marker associated with YY's keys. */
void *
objects_@YY@_not_a_key_marker (objects_@YY@_t *yy)
{
return (yy->key_callbacks).not_an_item_marker;
}
/* Returns the callbacks associated with YY's values. */
objects_callbacks_t
objects_@YY@_value_callbacks (objects_@YY@_t *yy)
{
return yy->value_callbacks;
}
/* Returns the ``bogus'' marker associated with YY's values. */
void *
objects_@YY@_not_a_value_marker (objects_@YY@_t *yy)
{
return (yy->value_callbacks).not_an_item_marker;
}
#else /* !__map__ */
/** Callbacks **/
/* Returns the callbacks associated with YY's elements. */
objects_callbacks_t
objects_@YY@_element_callbacks (objects_@YY@_t *yy)
{
return yy->callbacks;
}
/* Returns the ``bogus'' marker associated with YY's elements. */
void *
objects_@YY@_not_an_element_marker (objects_@YY@_t *yy)
{
return (yy->callbacks).not_an_item_marker;
}
#endif /* __map__ */