https://swig.svn.sourceforge.net/svnroot/swig/trunk ........ r10498 | talby | 2008-05-26 22:09:56 +0200 (Pn, 26 maj 2008) | 2 lines run test cases in the Perl set by the --with-perl5 configure option. ........ r10499 | talby | 2008-05-26 23:04:06 +0200 (Pn, 26 maj 2008) | 3 lines The perl5 minherit runtime test will work better if the classes are actually built under SWIGPERL. ........ r10503 | wsfulton | 2008-05-28 11:44:37 +0200 (Śr, 28 maj 2008) | 1 line Fix variable wrappers when using -proxy. Patch from Jan Jezabek ........ r10504 | bhy | 2008-05-28 19:27:48 +0200 (Śr, 28 maj 2008) | 2 lines Fixed SF #1971977: typo in pycontainer.swg (related to -extranative option) ........ r10506 | wsfulton | 2008-05-29 02:45:28 +0200 (Cz, 29 maj 2008) | 1 line Fix variable wrappers when using -noproxy ........ r10508 | bhy | 2008-05-30 15:53:33 +0200 (Pt, 30 maj 2008) | 1 line Fixed SF #1976978, apply the macros for primitive types to std::wstring ........ r10511 | olly | 2008-05-30 18:11:27 +0200 (Pt, 30 maj 2008) | 4 lines Fix typo in handling of /*@SWIG[...]*/ comments in the scanner. This just meant we were only actually looking for /*@SWI at the start of the comment, so was pretty harmless in practice. ........ r10515 | wsfulton | 2008-06-02 22:10:40 +0200 (Pn, 02 cze 2008) | 1 line Fix samename testcase for c# and java ........ r10516 | wsfulton | 2008-06-02 22:15:39 +0200 (Pn, 02 cze 2008) | 1 line Fix enums when using -noproxy ........ r10518 | bhy | 2008-06-07 13:20:07 +0200 (So, 07 cze 2008) | 4 lines Added a test case for keyword renaming. Now it works for Python in SWIG's -c++ mode, but in C mode it doesn't work! (you can try with make keyword_rename.ctest) ........ r10519 | bhy | 2008-06-07 15:40:51 +0200 (So, 07 cze 2008) | 1 line fixed keyword_rename.ctest tese case, caused by a mistake in Swig/naming.c ........ r10527 | mgossage | 2008-06-17 04:57:15 +0200 (Wt, 17 cze 2008) | 1 line [lua] bugfix 1938142 (bool& and bool* support) ........ r10530 | wsfulton | 2008-06-19 22:02:13 +0200 (Cz, 19 cze 2008) | 1 line Add R keyword support. Rename keywords for successful compilation of Java and C# code. More consistent keyword warnings across the different languages. ........ r10531 | wsfulton | 2008-06-19 23:15:48 +0200 (Cz, 19 cze 2008) | 1 line add complete list of R reserved words ........ r10536 | wsfulton | 2008-06-21 13:35:33 +0200 (So, 21 cze 2008) | 1 line better terminology for static types ........ r10537 | wsfulton | 2008-06-21 13:42:48 +0200 (So, 21 cze 2008) | 1 line remove raise as keyword test- it conflicts with _raise in LIBCMT on windows ........ r10539 | wsfulton | 2008-06-21 17:21:29 +0200 (So, 21 cze 2008) | 1 line Lua example warning removal fixes for vc++ ........ r10540 | wsfulton | 2008-06-21 17:23:02 +0200 (So, 21 cze 2008) | 1 line Remove some vc++ /W4 warnings ........ r10541 | wsfulton | 2008-06-21 18:04:55 +0200 (So, 21 cze 2008) | 1 line minor vc++ /W4 warning fixes ........ r10542 | wsfulton | 2008-06-21 21:07:51 +0200 (So, 21 cze 2008) | 1 line 'byte' is already used in Ruby on windows, so use another keyword ........ r10543 | wsfulton | 2008-06-21 22:45:32 +0200 (So, 21 cze 2008) | 1 line Fix crashing in the Ruby reject method in the STL wrappers ........ r10544 | wsfulton | 2008-06-21 22:48:28 +0200 (So, 21 cze 2008) | 1 line Fix crashing in the Ruby reject method in the STL wrappers ........ r10545 | wsfulton | 2008-06-21 22:49:10 +0200 (So, 21 cze 2008) | 1 line remove unnecessary variable int the char **STRING_ARRAY out typemap ........ r10546 | wsfulton | 2008-06-21 23:07:49 +0200 (So, 21 cze 2008) | 1 line Fix Ruby C++ example dependencies in dsp files ........ r10547 | wsfulton | 2008-06-22 00:25:36 +0200 (N, 22 cze 2008) | 1 line Fix unused parameter warnings in python when using gcc's -W -Wall options ........ r10548 | wsfulton | 2008-06-22 00:26:35 +0200 (N, 22 cze 2008) | 1 line Fix virtual destructor ........ r10549 | wsfulton | 2008-06-22 01:25:20 +0200 (N, 22 cze 2008) | 1 line various warning fixes ........ r10550 | wsfulton | 2008-06-22 02:09:11 +0200 (N, 22 cze 2008) | 1 line Another fix for the JVM hanging on exit problem when using directors ........ r10551 | wsfulton | 2008-06-22 02:09:51 +0200 (N, 22 cze 2008) | 1 line documentation sections update ........ r10552 | wsfulton | 2008-06-22 02:18:10 +0200 (N, 22 cze 2008) | 1 line more docs on defining macros for the thread hanging problem ........ r10558 | wsfulton | 2008-06-22 23:30:20 +0200 (N, 22 cze 2008) | 1 line fix unused parms in last commit for C code ........ r10559 | wsfulton | 2008-06-23 00:12:43 +0200 (Pn, 23 cze 2008) | 1 line Suppress unused methods warning for VC++ ........ r10560 | wsfulton | 2008-06-23 22:26:07 +0200 (Pn, 23 cze 2008) | 1 line fix partialcheck-test-suite and parallel make for r, chicken, tcl and php ........ r10561 | wsfulton | 2008-06-23 22:39:41 +0200 (Pn, 23 cze 2008) | 1 line correct message display when running the partialcheck-test-suite make target ........ r10562 | wsfulton | 2008-06-23 23:14:53 +0200 (Pn, 23 cze 2008) | 1 line fix typo ........ r10563 | olly | 2008-06-23 23:23:54 +0200 (Pn, 23 cze 2008) | 3 lines Fix bad use of Python API (untested, since I can't even compile this code on x86-64!) ........ r10564 | olly | 2008-06-24 00:58:03 +0200 (Wt, 24 cze 2008) | 3 lines [PHP] Fix segfault when wrapping a non-class function marked with %newobject (testcase char_strings). ........ r10565 | olly | 2008-06-24 02:27:34 +0200 (Wt, 24 cze 2008) | 3 lines [PHP] Fix assertion failure when handling %typemap(in,numinputs=0) (testcase ignore_parameter). ........ r10566 | olly | 2008-06-24 02:33:08 +0200 (Wt, 24 cze 2008) | 2 lines [PHP] Fix typemap_namespace.i to not try to copy a non-existent typemap. ........ r10567 | olly | 2008-06-24 02:41:07 +0200 (Wt, 24 cze 2008) | 3 lines Clean up dead and unused code in SwigToPhpType(), and rename to GetShadowReturnType(). ........ r10568 | olly | 2008-06-24 02:42:29 +0200 (Wt, 24 cze 2008) | 2 lines Fix cosmetic typo in string constant. ........ r10574 | wsfulton | 2008-06-24 22:10:28 +0200 (Wt, 24 cze 2008) | 1 line zap last entry ........ r10575 | wsfulton | 2008-06-24 22:11:46 +0200 (Wt, 24 cze 2008) | 1 line variable name changes to remove php keywords ........ r10576 | wsfulton | 2008-06-24 22:12:08 +0200 (Wt, 24 cze 2008) | 1 line variable name hiding fix ........ r10577 | wsfulton | 2008-06-24 22:12:43 +0200 (Wt, 24 cze 2008) | 1 line More info about numobjects added ........ r10578 | wsfulton | 2008-06-24 22:13:41 +0200 (Wt, 24 cze 2008) | 1 line update for 1.3.36 release ........ r10579 | wsfulton | 2008-06-24 23:48:46 +0200 (Wt, 24 cze 2008) | 1 line remove deprecated -c commandline option (runtime library generation) ........ r10580 | wsfulton | 2008-06-24 23:53:12 +0200 (Wt, 24 cze 2008) | 1 line correct comment about deprecated option ........ r10582 | wsfulton | 2008-06-25 01:00:27 +0200 (Śr, 25 cze 2008) | 1 line use rsync and ssh to upload releases to SourceForge as ftp no longer works ........ r10584 | wsfulton | 2008-06-25 01:24:48 +0200 (Śr, 25 cze 2008) | 1 line correction for 1.3.36 ........ r10588 | wsfulton | 2008-06-25 02:16:04 +0200 (Śr, 25 cze 2008) | 1 line section update ........ r10589 | wsfulton | 2008-06-25 02:16:40 +0200 (Śr, 25 cze 2008) | 1 line bump version to 1.3.37 ........ r10594 | wsfulton | 2008-06-26 20:33:06 +0200 (Cz, 26 cze 2008) | 1 line correct typo in first entry about %fragment ........ git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2008-maciekd@10606 626c5289-ae23-0410-ae9c-e8d60b6d4f22
551 lines
13 KiB
C
551 lines
13 KiB
C
/* -----------------------------------------------------------------------------
|
|
* hash.c
|
|
*
|
|
* Implements a simple hash table object.
|
|
*
|
|
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
|
*
|
|
* Copyright (C) 1999-2000. The University of Chicago
|
|
* See the file LICENSE for information on usage and redistribution.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
char cvsroot_hash_c[] = "$Id$";
|
|
|
|
#include "dohint.h"
|
|
|
|
extern DohObjInfo DohHashType;
|
|
|
|
/* Hash node */
|
|
typedef struct HashNode {
|
|
DOH *key;
|
|
DOH *object;
|
|
struct HashNode *next;
|
|
} HashNode;
|
|
|
|
/* Hash object */
|
|
typedef struct Hash {
|
|
DOH *file;
|
|
int line;
|
|
HashNode **hashtable;
|
|
int hashsize;
|
|
int nitems;
|
|
} Hash;
|
|
|
|
/* Key interning structure */
|
|
typedef struct KeyValue {
|
|
char *cstr;
|
|
DOH *sstr;
|
|
struct KeyValue *left;
|
|
struct KeyValue *right;
|
|
} KeyValue;
|
|
|
|
static KeyValue *root = 0;
|
|
|
|
/* Find or create a key in the interned key table */
|
|
static DOH *find_key(DOH *doh_c) {
|
|
char *c = (char *) doh_c;
|
|
KeyValue *r, *s;
|
|
int d = 0;
|
|
/* OK, sure, we use a binary tree for maintaining interned
|
|
symbols. Then we use their hash values for accessing secondary
|
|
hash tables. */
|
|
r = root;
|
|
s = 0;
|
|
while (r) {
|
|
s = r;
|
|
d = strcmp(r->cstr, c);
|
|
if (d == 0)
|
|
return r->sstr;
|
|
if (d < 0)
|
|
r = r->left;
|
|
else
|
|
r = r->right;
|
|
}
|
|
/* fprintf(stderr,"Interning '%s'\n", c); */
|
|
r = (KeyValue *) DohMalloc(sizeof(KeyValue));
|
|
r->cstr = (char *) DohMalloc(strlen(c) + 1);
|
|
strcpy(r->cstr, c);
|
|
r->sstr = NewString(c);
|
|
DohIntern(r->sstr);
|
|
r->left = 0;
|
|
r->right = 0;
|
|
if (!s) {
|
|
root = r;
|
|
} else {
|
|
if (d < 0)
|
|
s->left = r;
|
|
else
|
|
s->right = r;
|
|
}
|
|
return r->sstr;
|
|
}
|
|
|
|
#define HASH_INIT_SIZE 7
|
|
|
|
/* Create a new hash node */
|
|
static HashNode *NewNode(DOH *k, void *obj) {
|
|
HashNode *hn = (HashNode *) DohMalloc(sizeof(HashNode));
|
|
hn->key = k;
|
|
Incref(hn->key);
|
|
hn->object = obj;
|
|
Incref(obj);
|
|
hn->next = 0;
|
|
return hn;
|
|
}
|
|
|
|
/* Delete a hash node */
|
|
static void DelNode(HashNode *hn) {
|
|
Delete(hn->key);
|
|
Delete(hn->object);
|
|
DohFree(hn);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* DelHash()
|
|
*
|
|
* Delete a hash table.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static void DelHash(DOH *ho) {
|
|
Hash *h = (Hash *) ObjData(ho);
|
|
HashNode *n, *next;
|
|
int i;
|
|
|
|
for (i = 0; i < h->hashsize; i++) {
|
|
n = h->hashtable[i];
|
|
while (n) {
|
|
next = n->next;
|
|
DelNode(n);
|
|
n = next;
|
|
}
|
|
}
|
|
DohFree(h->hashtable);
|
|
h->hashtable = 0;
|
|
h->hashsize = 0;
|
|
DohFree(h);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Hash_clear()
|
|
*
|
|
* Clear all of the entries in the hash table.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static void Hash_clear(DOH *ho) {
|
|
Hash *h = (Hash *) ObjData(ho);
|
|
HashNode *n, *next;
|
|
int i;
|
|
|
|
for (i = 0; i < h->hashsize; i++) {
|
|
n = h->hashtable[i];
|
|
while (n) {
|
|
next = n->next;
|
|
DelNode(n);
|
|
n = next;
|
|
}
|
|
h->hashtable[i] = 0;
|
|
}
|
|
h->nitems = 0;
|
|
}
|
|
|
|
/* resize the hash table */
|
|
static void resize(Hash *h) {
|
|
HashNode *n, *next, **table;
|
|
int oldsize, newsize;
|
|
int i, p, hv;
|
|
|
|
if (h->nitems < 2 * h->hashsize)
|
|
return;
|
|
|
|
/* Too big. We have to rescale everything now */
|
|
oldsize = h->hashsize;
|
|
|
|
/* Calculate a new size */
|
|
newsize = 2 * oldsize + 1;
|
|
p = 3;
|
|
while (p < (newsize >> 1)) {
|
|
if (((newsize / p) * p) == newsize) {
|
|
newsize += 2;
|
|
p = 3;
|
|
continue;
|
|
}
|
|
p = p + 2;
|
|
}
|
|
|
|
table = (HashNode **) DohMalloc(newsize * sizeof(HashNode *));
|
|
for (i = 0; i < newsize; i++) {
|
|
table[i] = 0;
|
|
}
|
|
|
|
/* Walk down the old set of nodes and re-place */
|
|
h->hashsize = newsize;
|
|
for (i = 0; i < oldsize; i++) {
|
|
n = h->hashtable[i];
|
|
while (n) {
|
|
hv = Hashval(n->key) % newsize;
|
|
next = n->next;
|
|
n->next = table[hv];
|
|
table[hv] = n;
|
|
n = next;
|
|
}
|
|
}
|
|
DohFree(h->hashtable);
|
|
h->hashtable = table;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Hash_setattr()
|
|
*
|
|
* Set an attribute in the hash table. Deletes the existing entry if it already
|
|
* exists.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static int Hash_setattr(DOH *ho, DOH *k, DOH *obj) {
|
|
int hv;
|
|
HashNode *n, *prev;
|
|
Hash *h = (Hash *) ObjData(ho);
|
|
|
|
if (!obj) {
|
|
return DohDelattr(ho, k);
|
|
}
|
|
if (!DohCheck(k))
|
|
k = find_key(k);
|
|
if (!DohCheck(obj)) {
|
|
obj = NewString((char *) obj);
|
|
Decref(obj);
|
|
}
|
|
hv = (Hashval(k)) % h->hashsize;
|
|
n = h->hashtable[hv];
|
|
prev = 0;
|
|
while (n) {
|
|
if (Cmp(n->key, k) == 0) {
|
|
/* Node already exists. Just replace its contents */
|
|
if (n->object == obj) {
|
|
/* Whoa. Same object. Do nothing */
|
|
return 1;
|
|
}
|
|
Delete(n->object);
|
|
n->object = obj;
|
|
Incref(obj);
|
|
return 1; /* Return 1 to indicate a replacement */
|
|
} else {
|
|
prev = n;
|
|
n = n->next;
|
|
}
|
|
}
|
|
/* Add this to the table */
|
|
n = NewNode(k, obj);
|
|
if (prev)
|
|
prev->next = n;
|
|
else
|
|
h->hashtable[hv] = n;
|
|
h->nitems++;
|
|
resize(h);
|
|
return 0;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Hash_getattr()
|
|
*
|
|
* Get an attribute from the hash table. Returns 0 if it doesn't exist.
|
|
* ----------------------------------------------------------------------------- */
|
|
typedef int (*binop) (DOH *obj1, DOH *obj2);
|
|
|
|
|
|
static DOH *Hash_getattr(DOH *h, DOH *k) {
|
|
DOH *obj = 0;
|
|
Hash *ho = (Hash *) ObjData(h);
|
|
DOH *ko = DohCheck(k) ? k : find_key(k);
|
|
int hv = Hashval(ko) % ho->hashsize;
|
|
DohObjInfo *k_type = ((DohBase*)ko)->type;
|
|
HashNode *n = ho->hashtable[hv];
|
|
if (k_type->doh_equal) {
|
|
binop equal = k_type->doh_equal;
|
|
while (n) {
|
|
DohBase *nk = (DohBase *)n->key;
|
|
if ((k_type == nk->type) && equal(ko, nk)) obj = n->object;
|
|
n = n->next;
|
|
}
|
|
} else {
|
|
binop cmp = k_type->doh_cmp;
|
|
while (n) {
|
|
DohBase *nk = (DohBase *)n->key;
|
|
if ((k_type == nk->type) && (cmp(ko, nk) == 0)) obj = n->object;
|
|
n = n->next;
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Hash_delattr()
|
|
*
|
|
* Delete an object from the hash table.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static int Hash_delattr(DOH *ho, DOH *k) {
|
|
HashNode *n, *prev;
|
|
int hv;
|
|
Hash *h = (Hash *) ObjData(ho);
|
|
|
|
if (!DohCheck(k))
|
|
k = find_key(k);
|
|
hv = Hashval(k) % h->hashsize;
|
|
n = h->hashtable[hv];
|
|
prev = 0;
|
|
while (n) {
|
|
if (Cmp(n->key, k) == 0) {
|
|
/* Found it, kill it */
|
|
|
|
if (prev) {
|
|
prev->next = n->next;
|
|
} else {
|
|
h->hashtable[hv] = n->next;
|
|
}
|
|
DelNode(n);
|
|
h->nitems--;
|
|
return 1;
|
|
}
|
|
prev = n;
|
|
n = n->next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static DohIterator Hash_firstiter(DOH *ho) {
|
|
DohIterator iter;
|
|
Hash *h = (Hash *) ObjData(ho);
|
|
iter.object = ho;
|
|
iter._current = 0;
|
|
iter.item = 0;
|
|
iter.key = 0;
|
|
iter._index = 0; /* Index in hash table */
|
|
while ((iter._index < h->hashsize) && !h->hashtable[iter._index])
|
|
iter._index++;
|
|
|
|
if (iter._index >= h->hashsize) {
|
|
return iter;
|
|
}
|
|
iter._current = h->hashtable[iter._index];
|
|
iter.item = ((HashNode *) iter._current)->object;
|
|
iter.key = ((HashNode *) iter._current)->key;
|
|
|
|
/* Actually save the next slot in the hash. This makes it possible to
|
|
delete the item being iterated over without trashing the universe */
|
|
iter._current = ((HashNode *) iter._current)->next;
|
|
return iter;
|
|
}
|
|
|
|
static DohIterator Hash_nextiter(DohIterator iter) {
|
|
Hash *h = (Hash *) ObjData(iter.object);
|
|
if (!iter._current) {
|
|
iter._index++;
|
|
while ((iter._index < h->hashsize) && !h->hashtable[iter._index]) {
|
|
iter._index++;
|
|
}
|
|
if (iter._index >= h->hashsize) {
|
|
iter.item = 0;
|
|
iter.key = 0;
|
|
iter._current = 0;
|
|
return iter;
|
|
}
|
|
iter._current = h->hashtable[iter._index];
|
|
}
|
|
iter.key = ((HashNode *) iter._current)->key;
|
|
iter.item = ((HashNode *) iter._current)->object;
|
|
|
|
/* Store the next node to iterator on */
|
|
iter._current = ((HashNode *) iter._current)->next;
|
|
return iter;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Hash_keys(DOH *)
|
|
*
|
|
* Return a list of keys
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static DOH *Hash_keys(DOH *so) {
|
|
DOH *keys;
|
|
Iterator i;
|
|
|
|
keys = NewList();
|
|
for (i = First(so); i.key; i = Next(i)) {
|
|
Append(keys, i.key);
|
|
}
|
|
return keys;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Hash_str()
|
|
*
|
|
* Create a string representation of a hash table (mainly for debugging).
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static DOH *Hash_str(DOH *ho) {
|
|
int i, j;
|
|
HashNode *n;
|
|
DOH *s;
|
|
static int indent = 4;
|
|
Hash *h = (Hash *) ObjData(ho);
|
|
|
|
s = NewStringEmpty();
|
|
if (ObjGetMark(ho)) {
|
|
Printf(s, "Hash(0x%x)", ho);
|
|
return s;
|
|
}
|
|
ObjSetMark(ho, 1);
|
|
Printf(s, "Hash {\n");
|
|
for (i = 0; i < h->hashsize; i++) {
|
|
n = h->hashtable[i];
|
|
while (n) {
|
|
for (j = 0; j < indent; j++)
|
|
Putc(' ', s);
|
|
indent += 4;
|
|
Printf(s, "'%s' : %s, \n", n->key, n->object);
|
|
indent -= 4;
|
|
n = n->next;
|
|
}
|
|
}
|
|
for (j = 0; j < (indent - 4); j++)
|
|
Putc(' ', s);
|
|
Printf(s, "}\n");
|
|
ObjSetMark(ho, 0);
|
|
return s;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Hash_len()
|
|
*
|
|
* Return number of entries in the hash table.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static int Hash_len(DOH *ho) {
|
|
Hash *h = (Hash *) ObjData(ho);
|
|
return h->nitems;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* CopyHash()
|
|
*
|
|
* Make a copy of a hash table. Note: this is a shallow copy.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static DOH *CopyHash(DOH *ho) {
|
|
Hash *h, *nh;
|
|
HashNode *n;
|
|
DOH *nho;
|
|
|
|
int i;
|
|
h = (Hash *) ObjData(ho);
|
|
nh = (Hash *) DohMalloc(sizeof(Hash));
|
|
nh->hashsize = h->hashsize;
|
|
nh->hashtable = (HashNode **) DohMalloc(nh->hashsize * sizeof(HashNode *));
|
|
for (i = 0; i < nh->hashsize; i++) {
|
|
nh->hashtable[i] = 0;
|
|
}
|
|
nh->nitems = 0;
|
|
nh->line = h->line;
|
|
nh->file = h->file;
|
|
if (nh->file)
|
|
Incref(nh->file);
|
|
|
|
nho = DohObjMalloc(&DohHashType, nh);
|
|
for (i = 0; i < h->hashsize; i++) {
|
|
n = h->hashtable[i];
|
|
while (n) {
|
|
Hash_setattr(nho, n->key, n->object);
|
|
n = n->next;
|
|
}
|
|
}
|
|
return nho;
|
|
}
|
|
|
|
|
|
|
|
static void Hash_setfile(DOH *ho, DOH *file) {
|
|
DOH *fo;
|
|
Hash *h = (Hash *) ObjData(ho);
|
|
|
|
if (!DohCheck(file)) {
|
|
fo = NewString(file);
|
|
Decref(fo);
|
|
} else
|
|
fo = file;
|
|
Incref(fo);
|
|
Delete(h->file);
|
|
h->file = fo;
|
|
}
|
|
|
|
static DOH *Hash_getfile(DOH *ho) {
|
|
Hash *h = (Hash *) ObjData(ho);
|
|
return h->file;
|
|
}
|
|
|
|
static void Hash_setline(DOH *ho, int line) {
|
|
Hash *h = (Hash *) ObjData(ho);
|
|
h->line = line;
|
|
}
|
|
|
|
static int Hash_getline(DOH *ho) {
|
|
Hash *h = (Hash *) ObjData(ho);
|
|
return h->line;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* type information
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static DohHashMethods HashHashMethods = {
|
|
Hash_getattr,
|
|
Hash_setattr,
|
|
Hash_delattr,
|
|
Hash_keys,
|
|
};
|
|
|
|
DohObjInfo DohHashType = {
|
|
"Hash", /* objname */
|
|
DelHash, /* doh_del */
|
|
CopyHash, /* doh_copy */
|
|
Hash_clear, /* doh_clear */
|
|
Hash_str, /* doh_str */
|
|
0, /* doh_data */
|
|
0, /* doh_dump */
|
|
Hash_len, /* doh_len */
|
|
0, /* doh_hash */
|
|
0, /* doh_cmp */
|
|
0, /* doh_equal */
|
|
Hash_firstiter, /* doh_first */
|
|
Hash_nextiter, /* doh_next */
|
|
Hash_setfile, /* doh_setfile */
|
|
Hash_getfile, /* doh_getfile */
|
|
Hash_setline, /* doh_setline */
|
|
Hash_getline, /* doh_getline */
|
|
&HashHashMethods, /* doh_mapping */
|
|
0, /* doh_sequence */
|
|
0, /* doh_file */
|
|
0, /* doh_string */
|
|
0, /* doh_positional */
|
|
0,
|
|
};
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* NewHash()
|
|
*
|
|
* Create a new hash table.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
DOH *DohNewHash() {
|
|
Hash *h;
|
|
int i;
|
|
h = (Hash *) DohMalloc(sizeof(Hash));
|
|
h->hashsize = HASH_INIT_SIZE;
|
|
h->hashtable = (HashNode **) DohMalloc(h->hashsize * sizeof(HashNode *));
|
|
for (i = 0; i < h->hashsize; i++) {
|
|
h->hashtable[i] = 0;
|
|
}
|
|
h->nitems = 0;
|
|
h->file = 0;
|
|
h->line = 0;
|
|
return DohObjMalloc(&DohHashType, h);
|
|
}
|