Mercurial > projects > ddmd
diff dmd/StringTable.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 7427ded8caf7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/StringTable.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,108 @@ +module dmd.StringTable; + +import dmd.StringValue; +import dmd.StringEntry; +import dmd.Dchar; + +import core.stdc.stdlib; +import core.stdc.string; + +class StringTable +{ + void** table; + uint count; + uint tabledim; + + this(uint size = 37) + { + table = cast(void**)calloc(size, (void*).sizeof); + memset(table, 0, size * (void*).sizeof); + tabledim = size; + count = 0; + } + + ~this() + { + /// TODO: is it *really* needed? + // Zero out dangling pointers to help garbage collector. + // Should zero out StringEntry's too. + ///for (uint i = 0; i < count; i++) { + /// table[i] = null; + ///} + + free(table); + //table = null; + } + + StringValue* lookup(immutable(dchar_t)[] s) + { + StringEntry* se = *cast(StringEntry**)search(s); + if (se !is null) + return &se.value; + else + return null; + } + + StringValue* insert(immutable(dchar_t)[] s) + { + StringEntry** pse = cast(StringEntry**)search(s); + StringEntry* se = *pse; + if (se !is null) + return null; // error: already in table + else + { + se = new StringEntry(s); + *pse = se; + } + + return &se.value; + } + + StringValue* update(immutable(dchar_t)[] s) + { + StringEntry **pse; + StringEntry *se; + + pse = cast(StringEntry**)search(s); + se = *pse; + if (se is null) // not in table: so create new entry + { + se = new StringEntry(s); + *pse = se; + } + return &se.value; + } + +private: + void** search(immutable(dchar_t)[] s) + { + int cmp; + + //printf("StringTable::search(%p,%d)\n",s,len); + hash_t hash = Dchar.calcHash(s.ptr, s.length); + uint u = hash % tabledim; + StringEntry** se = cast(StringEntry**)&table[u]; + //printf("\thash = %d, u = %d\n",hash,u); + while (*se) + { + cmp = (*se).hash - hash; + if (cmp == 0) + { + cmp = (*se).value.lstring.len() - s.length; + if (cmp == 0) + { + cmp = Dchar.memcmp(s.ptr, (*se).value.lstring.toDchars().ptr, s.length); + if (cmp == 0) + break; + } + } + if (cmp < 0) + se = &(*se).left; + else + se = &(*se).right; + } + + //printf("\treturn %p, %p\n",se, (*se)); + return cast(void**)se; + } +} \ No newline at end of file