1996-02-13 02:31:48 +00:00
|
|
|
/* NSHashTable implementation for GNUStep.
|
1997-05-03 18:17:23 +00:00
|
|
|
* Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
|
1996-02-13 02:31:48 +00:00
|
|
|
*
|
|
|
|
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
|
|
|
* Created: Mon Dec 12 23:54:09 EST 1994
|
1996-03-22 00:36:13 +00:00
|
|
|
* Updated: Mon Mar 11 01:48:31 EST 1996
|
|
|
|
* Serial: 96.03.11.06
|
1996-02-13 02:31:48 +00:00
|
|
|
*
|
1996-05-12 00:56:10 +00:00
|
|
|
* This file is part of the GNUstep Base Library.
|
1996-02-13 02:31:48 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the Free
|
1999-09-09 02:56:20 +00:00
|
|
|
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
1996-02-13 02:31:48 +00:00
|
|
|
|
|
|
|
/**** Included Headers *******************************************************/
|
|
|
|
|
1997-11-06 00:51:23 +00:00
|
|
|
#include <config.h>
|
1996-03-22 00:36:13 +00:00
|
|
|
#include <Foundation/NSZone.h>
|
1996-02-13 02:31:48 +00:00
|
|
|
#include <Foundation/NSString.h>
|
|
|
|
#include <Foundation/NSArray.h>
|
|
|
|
#include <Foundation/NSException.h>
|
|
|
|
#include <Foundation/NSHashTable.h>
|
1998-12-20 21:27:47 +00:00
|
|
|
#include <base/o_hash.h>
|
1996-03-22 00:36:13 +00:00
|
|
|
#include "NSCallBacks.h"
|
1996-02-13 02:31:48 +00:00
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
/** Macros... **/
|
1996-02-13 02:31:48 +00:00
|
|
|
|
|
|
|
#define NSHT_CALLBACKS(T) \
|
1996-04-17 19:26:04 +00:00
|
|
|
(*((NSHashTableCallBacks *)(o_hash_extra((o_hash_t *)(T)))))
|
1996-02-13 02:31:48 +00:00
|
|
|
|
|
|
|
#define NSHT_DESCRIBE(T, P) \
|
1996-03-22 00:36:13 +00:00
|
|
|
(NSHT_CALLBACKS((T))).describe((T), (P))
|
1996-02-13 02:31:48 +00:00
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
/** Dummy callbacks... **/
|
1996-02-13 02:31:48 +00:00
|
|
|
|
|
|
|
size_t
|
1996-03-22 00:36:13 +00:00
|
|
|
_NSHT_hash(const void *element, NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-03-22 00:36:13 +00:00
|
|
|
return (NSHT_CALLBACKS(table)).hash((NSHashTable *)table, element);
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1996-03-22 00:36:13 +00:00
|
|
|
_NSHT_compare(const void *element1, const void *element2, NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-03-22 00:36:13 +00:00
|
|
|
return !((NSHT_CALLBACKS(table)).isEqual(table, element1, element2));
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1996-03-22 00:36:13 +00:00
|
|
|
_NSHT_is_equal(const void *element1, const void *element2, NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-03-22 00:36:13 +00:00
|
|
|
return (NSHT_CALLBACKS(table)).isEqual(table, element1, element2);
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
const void *
|
|
|
|
_NSHT_retain(const void *element, NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-03-22 00:36:13 +00:00
|
|
|
/* OpenStep (unlike we) does not allow for the possibility of
|
|
|
|
* substitution upon retaining. */
|
|
|
|
(NSHT_CALLBACKS(table)).retain(table, element);
|
|
|
|
return element;
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1996-03-22 00:36:13 +00:00
|
|
|
_NSHT_release(void *element, NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-03-22 00:36:13 +00:00
|
|
|
(NSHT_CALLBACKS(table)).release(table, element);
|
1996-02-13 02:31:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
NSString *
|
|
|
|
_NSHT_describe(const void *element, const void *table)
|
|
|
|
{
|
|
|
|
return ((NSHT_CALLBACKS(table)).describe((NSHashTable *)table, element));
|
|
|
|
}
|
|
|
|
|
1996-02-13 02:31:48 +00:00
|
|
|
/* These are wrappers for getting at the real callbacks. */
|
1996-04-17 19:26:04 +00:00
|
|
|
o_callbacks_t _NSHT_callbacks =
|
|
|
|
{
|
|
|
|
(o_hash_func_t) _NSHT_hash,
|
|
|
|
(o_compare_func_t) _NSHT_compare,
|
|
|
|
(o_is_equal_func_t) _NSHT_is_equal,
|
|
|
|
(o_retain_func_t) _NSHT_retain,
|
|
|
|
(o_release_func_t) _NSHT_release,
|
|
|
|
(o_describe_func_t) _NSHT_describe,
|
1996-03-22 00:36:13 +00:00
|
|
|
0 /* Note that OpenStep decrees that '0' is the (only) forbidden value. */
|
1996-02-13 02:31:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/** Extra, extra **/
|
|
|
|
|
|
|
|
/* Make a copy of a hash table's callbacks. */
|
1996-03-22 00:36:13 +00:00
|
|
|
const void *
|
|
|
|
_NSHT_extra_retain (const NSHashTableCallBacks *callBacks, NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
|
|
|
/* A pointer to some new callbacks. */
|
1996-02-22 15:25:44 +00:00
|
|
|
NSHashTableCallBacks *newCallBacks;
|
1996-02-13 02:31:48 +00:00
|
|
|
|
|
|
|
/* Set aside space for our new callbacks in the right zone. */
|
1996-04-17 19:26:04 +00:00
|
|
|
newCallBacks = (NSHashTableCallBacks *)NSZoneMalloc(o_hash_zone(table),
|
1996-03-22 00:36:13 +00:00
|
|
|
sizeof(NSHashTableCallBacks));
|
|
|
|
|
|
|
|
/* FIXME: Check for an invalid pointer? */
|
1996-02-13 02:31:48 +00:00
|
|
|
|
|
|
|
/* Copy CALLBACKS into NEWCALLBACKS. */
|
|
|
|
*newCallBacks = *callBacks;
|
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
/* Return our new callbacks. */
|
|
|
|
return (const void *) newCallBacks;
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1996-03-22 00:36:13 +00:00
|
|
|
_NSHT_extra_release(NSHashTableCallBacks *callBacks, NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-03-22 00:36:13 +00:00
|
|
|
if (callBacks != 0)
|
1996-04-17 19:26:04 +00:00
|
|
|
NSZoneFree(o_hash_zone(table), callBacks);
|
1996-02-13 02:31:48 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
NSString *
|
|
|
|
_NSHT_extra_describe(NSHashTableCallBacks *callBacks, NSHashTable *table)
|
|
|
|
{
|
|
|
|
/* FIXME: Code this. */
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
1996-02-13 02:31:48 +00:00
|
|
|
/* The idea here is that these callbacks ensure that the
|
|
|
|
* NSHashTableCallbacks which are associated with a given NSHashTable
|
1996-02-22 15:25:44 +00:00
|
|
|
* remain so associated throughout the life of the table and its copies. */
|
1996-04-17 19:26:04 +00:00
|
|
|
o_callbacks_t _NSHT_extra_callbacks =
|
|
|
|
{
|
|
|
|
(o_hash_func_t) o_non_owned_void_p_hash,
|
|
|
|
(o_compare_func_t) o_non_owned_void_p_compare,
|
|
|
|
(o_is_equal_func_t) o_non_owned_void_p_is_equal,
|
|
|
|
(o_retain_func_t) _NSHT_extra_retain,
|
|
|
|
(o_release_func_t) _NSHT_extra_release,
|
|
|
|
(o_describe_func_t) _NSHT_extra_describe,
|
1996-02-13 02:31:48 +00:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
/**** Function Implementations ***********************************************/
|
|
|
|
|
|
|
|
/** Creating NSHashTables **/
|
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
inline NSHashTable *
|
|
|
|
NSCreateHashTableWithZone(NSHashTableCallBacks callBacks,
|
|
|
|
unsigned int capacity,
|
|
|
|
NSZone *zone)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
|
|
|
NSHashTable *table;
|
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
/* Build the core table. See the above for the definitions of
|
|
|
|
* the funny callbacks. */
|
1996-04-17 19:26:04 +00:00
|
|
|
table = o_hash_with_zone_with_callbacks(zone, _NSHT_callbacks);
|
1996-02-13 02:31:48 +00:00
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
/* Check to make sure our allocation has succeeded. */
|
|
|
|
if (table != 0)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
|
|
|
/* Resize TABLE to CAPACITY. */
|
1996-04-17 19:26:04 +00:00
|
|
|
o_hash_resize(table, capacity);
|
1996-02-13 02:31:48 +00:00
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
/* Add CALLBACKS to TABLE. This takes care of everything for us. */
|
1996-04-17 19:26:04 +00:00
|
|
|
o_hash_set_extra_callbacks(table, _NSHT_extra_callbacks);
|
|
|
|
o_hash_set_extra(table, &callBacks);
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
/* Yah-hoo, kid! */
|
1996-02-13 02:31:48 +00:00
|
|
|
return table;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSHashTable *
|
1996-03-22 00:36:13 +00:00
|
|
|
NSCreateHashTable(NSHashTableCallBacks callBacks,
|
|
|
|
unsigned int capacity)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1997-01-06 21:35:01 +00:00
|
|
|
return NSCreateHashTableWithZone(callBacks, capacity, NSDefaultMallocZone());
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Copying **/
|
|
|
|
|
|
|
|
NSHashTable *
|
1996-03-22 00:36:13 +00:00
|
|
|
NSCopyHashTableWithZone(NSHashTable *table, NSZone *zone)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-03-22 00:36:13 +00:00
|
|
|
/* Due to the wonders of modern structure technology,
|
|
|
|
* everything we care about is automagically and safely destroyed. */
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_hash_copy_with_zone(table, zone);
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Destroying **/
|
|
|
|
|
|
|
|
void
|
1996-03-22 00:36:13 +00:00
|
|
|
NSFreeHashTable(NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-03-22 00:36:13 +00:00
|
|
|
/* Due to the wonders of modern technology,
|
1996-02-22 15:25:44 +00:00
|
|
|
* everything we care about is automagically and safely destroyed. */
|
1996-04-17 19:26:04 +00:00
|
|
|
o_hash_dealloc(table);
|
1996-02-13 02:31:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Resetting **/
|
|
|
|
|
|
|
|
void
|
1996-03-22 00:36:13 +00:00
|
|
|
NSResetHashTable(NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_hash_empty(table);
|
1996-02-13 02:31:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Comparing **/
|
|
|
|
|
|
|
|
BOOL
|
1996-03-22 00:36:13 +00:00
|
|
|
NSCompareHashTables(NSHashTable *table1, NSHashTable *table2)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return (o_hash_is_equal_to_hash(table1, table2) ? YES : NO);
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Counting **/
|
|
|
|
|
|
|
|
unsigned int
|
1996-03-22 00:36:13 +00:00
|
|
|
NSCountHashTable(NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return (unsigned int) o_hash_count(table);
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Retrieving **/
|
|
|
|
|
|
|
|
void *
|
1996-03-22 00:36:13 +00:00
|
|
|
NSHashGet(NSHashTable *table, const void *pointer)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-02-22 15:25:44 +00:00
|
|
|
/* Just make the call. You know the number. */
|
1996-04-17 19:26:04 +00:00
|
|
|
return (void *) o_hash_element(table, pointer);
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NSArray *
|
1996-02-22 15:25:44 +00:00
|
|
|
NSAllHashTableObjects (NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-02-22 15:25:44 +00:00
|
|
|
NSMutableArray *array;
|
|
|
|
NSHashEnumerator enumerator;
|
|
|
|
id element;
|
1996-02-13 02:31:48 +00:00
|
|
|
|
|
|
|
/* FIXME: We should really be locking TABLE somehow, to insure
|
|
|
|
* the thread-safeness of this method. */
|
|
|
|
|
1996-02-22 15:25:44 +00:00
|
|
|
/* Get us a mutable array with plenty of space. */
|
|
|
|
array = [NSMutableArray arrayWithCapacity:NSCountHashTable(table)];
|
1996-02-13 02:31:48 +00:00
|
|
|
|
1996-02-22 15:25:44 +00:00
|
|
|
/* Get an enumerator for TABLE. */
|
|
|
|
enumerator = NSEnumerateHashTable(table);
|
1996-02-13 02:31:48 +00:00
|
|
|
|
1996-02-22 15:25:44 +00:00
|
|
|
while ((element = NSNextHashEnumeratorItem(&enumerator)) != 0)
|
|
|
|
[array addObject:element];
|
1996-02-13 02:31:48 +00:00
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
/* ARRAY is already autoreleased. */
|
|
|
|
return (NSArray *) array;
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Enumerating **/
|
|
|
|
|
|
|
|
NSHashEnumerator
|
1996-03-22 00:36:13 +00:00
|
|
|
NSEnumerateHashTable(NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
return o_hash_enumerator_for_hash(table);
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
1996-03-22 00:36:13 +00:00
|
|
|
NSNextHashEnumeratorItem(NSHashEnumerator *enumerator)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-02-22 15:25:44 +00:00
|
|
|
const void *element;
|
1996-02-13 02:31:48 +00:00
|
|
|
|
|
|
|
/* Grab the next element. */
|
1996-04-17 19:26:04 +00:00
|
|
|
o_hash_enumerator_next_element(enumerator, &element);
|
1996-02-13 02:31:48 +00:00
|
|
|
|
1996-02-22 15:25:44 +00:00
|
|
|
/* Return ELEMENT. */
|
1996-03-22 00:36:13 +00:00
|
|
|
return (void *) element;
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Adding **/
|
|
|
|
|
|
|
|
void
|
1996-03-22 00:36:13 +00:00
|
|
|
NSHashInsert(NSHashTable *table, const void *pointer)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-02-22 15:25:44 +00:00
|
|
|
/* Place POINTER in TABLE. */
|
1996-04-17 19:26:04 +00:00
|
|
|
o_hash_add_element(table, pointer);
|
1996-02-13 02:31:48 +00:00
|
|
|
|
1996-02-22 15:25:44 +00:00
|
|
|
/* OpenStep doesn't care for any return value, so... */
|
1996-02-13 02:31:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1996-03-22 00:36:13 +00:00
|
|
|
NSHashInsertKnownAbsent(NSHashTable *table, const void *element)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
if (o_hash_contains_element(table, element))
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
|
|
|
/* FIXME: I should make this give the user/programmer more
|
|
|
|
* information. Not difficult to do, just something for a later
|
|
|
|
* date. */
|
|
|
|
[NSException raise:NSInvalidArgumentException
|
2001-03-19 23:53:23 +00:00
|
|
|
format:@"NSHashTable: illegal reinsertion of: %@",
|
|
|
|
NSHT_DESCRIBE(table, element)];
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1996-04-17 19:26:04 +00:00
|
|
|
o_hash_add_element_known_absent(table, element);
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
/* OpenStep doesn't care for any return value, so... */
|
1996-02-13 02:31:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
1996-03-22 00:36:13 +00:00
|
|
|
NSHashInsertIfAbsent(NSHashTable *table, const void *element)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-02-22 15:25:44 +00:00
|
|
|
const void *old_element;
|
1996-02-13 02:31:48 +00:00
|
|
|
|
|
|
|
/* Place ELEMENT in TABLE. */
|
1996-04-17 19:26:04 +00:00
|
|
|
old_element = o_hash_add_element_if_absent(table, element);
|
1996-02-13 02:31:48 +00:00
|
|
|
|
1996-02-22 15:25:44 +00:00
|
|
|
/* Return the version of ELEMENT in TABLE now. */
|
1996-03-22 00:36:13 +00:00
|
|
|
return (void *) old_element;
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Removing **/
|
|
|
|
|
|
|
|
void
|
1996-03-22 00:36:13 +00:00
|
|
|
NSHashRemove(NSHashTable *table, const void *element)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
|
|
|
/* Remove ELEMENT from TABLE. */
|
1996-04-17 19:26:04 +00:00
|
|
|
o_hash_remove_element(table, element);
|
1996-02-13 02:31:48 +00:00
|
|
|
|
1996-02-22 15:25:44 +00:00
|
|
|
/* OpenStep doesn't care about return values here, so... */
|
1996-02-13 02:31:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Describing **/
|
|
|
|
|
|
|
|
NSString *
|
1996-03-22 00:36:13 +00:00
|
|
|
NSStringFromHashTable(NSHashTable *table)
|
1996-02-13 02:31:48 +00:00
|
|
|
{
|
1996-02-22 15:25:44 +00:00
|
|
|
NSMutableString *string;
|
1996-02-13 02:31:48 +00:00
|
|
|
NSHashEnumerator enumerator;
|
1996-02-22 15:25:44 +00:00
|
|
|
const void *pointer;
|
1996-02-13 02:31:48 +00:00
|
|
|
|
|
|
|
/* This will be our string. */
|
1996-02-22 15:25:44 +00:00
|
|
|
string = [NSMutableString stringWithCapacity:0];
|
1996-02-13 02:31:48 +00:00
|
|
|
|
|
|
|
/* Get an enumerator for TABLE. */
|
|
|
|
enumerator = NSEnumerateHashTable(table);
|
|
|
|
|
|
|
|
/* Iterate over the elements of TABLE, appending the description of
|
|
|
|
* each to the mutable string STRING. */
|
1996-02-22 15:25:44 +00:00
|
|
|
while ((pointer = NSNextHashEnumeratorItem(&enumerator)) != 0)
|
2001-03-19 23:53:23 +00:00
|
|
|
[string appendFormat:@"%@;\n", NSHT_DESCRIBE(table, pointer)];
|
1996-02-13 02:31:48 +00:00
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
/* STRING is already autoreleased. */
|
|
|
|
return (NSString *) string;
|
1996-02-13 02:31:48 +00:00
|
|
|
}
|