1 /* Copyright (C) 2003,2004,2005,2006,2013 MORIOKA Tomohiko
2 This file is part of the CONCORD Library.
4 The CONCORD Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The CONCORD Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the CONCORD Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 unsigned long concord_hash_c_string (const unsigned char *ptr);
24 unsigned long cos_hash_c_string_n (const unsigned char *ptr, size_t size);
25 unsigned long cos_symbol_hash_string (COS_String string);
29 cos_make_symbol (COS_String string)
31 COS_Symbol obj = COS_ALLOCATE_OBJECT (Symbol);
42 cos_release_symbol (COS_Object obj)
47 if ( ((COS_Symbol)obj)->value != NULL)
48 cos_release_object (((COS_Symbol)obj)->value);
50 cos_release_object (((COS_Symbol)obj)->name);
56 cos_symbol_table_intern (COS_Symbol_Table table, COS_object name)
59 COS_String key_string;
60 unsigned long i, index;
66 if (COS_OBJECT_C_STRING_P (name))
68 key_string = cos_build_string ((char*)name);
72 key_string = (COS_String)name;
74 key = key_string->data;
75 index = cos_symbol_hash_string (key_string) % table->size;
76 for (i = index; i < table->size; i++)
78 entry = table->data[i];
81 entry = cos_make_symbol (key_string);
82 cos_retain_object ((COS_object)entry);
83 table->data[i] = entry;
86 else if ( (entry->name->size == key_string->size)
87 && (memcmp (entry->name->data,
88 key_string->data, key_string->size) == 0) )
93 if (cos_symbol_table_grow (table) == 0)
94 return cos_symbol_table_intern (table, key_string);
99 cos_symbol_name (COS_Symbol symbol)
105 COS_Symbol_Table cos_default_symbol_table = NULL;
107 COS_Symbol_Table cos_make_symbol_table_0 (size_t size);
108 void cos_destroy_symbol_table_0 (COS_Symbol_Table hash);
111 /* derived from hashpjw, Dragon Book P436. */
113 cos_hash_c_string_n (const unsigned char *ptr, size_t size)
115 unsigned long hash = 0;
118 for ( i = 0; i < size; i++ )
121 hash = (hash << 4) + ptr[i];
122 g = hash & 0xf0000000;
124 hash = (hash ^ (g >> 24)) ^ g;
126 return hash & 07777777777;
130 cos_symbol_hash_string (COS_String string)
132 return cos_hash_c_string_n (string->data, string->size);
137 cos_make_symbol_table_0 (size_t size)
139 COS_Symbol_Table hash
140 = (COS_Symbol_Table)malloc (sizeof (COS_Symbol_Table_ent));
146 = (COS_Symbol*) malloc (sizeof (COS_Symbol) * size);
147 if (hash->data == NULL)
154 memset (hash->data, 0, sizeof (COS_Symbol) * size);
159 cos_destroy_symbol_table_0 (COS_Symbol_Table table)
169 cos_make_symbol_table ()
171 return cos_make_symbol_table_0 (2 /* 256 */);
175 cos_destroy_symbol_table (COS_Symbol_Table table)
179 for (i = 0; i < table->size; i++)
181 COS_Symbol entry = table->data[i];
185 if (entry->name != NULL)
186 cos_release_object (entry->name);
187 if (entry->value != NULL)
188 cos_release_object (entry->value);
192 cos_destroy_symbol_table_0 (table);
196 cos_intern (COS_object name)
198 if (cos_default_symbol_table == NULL)
199 cos_default_symbol_table = cos_make_symbol_table();
201 return cos_symbol_table_intern (cos_default_symbol_table, name);
205 cos_symbol_table_set (COS_Symbol_Table table, COS_Symbol symbol)
213 index = cos_symbol_hash_string (symbol->name) % table->size;
214 for (i = index; i < table->size; i++)
216 entry = table->data[i];
220 cos_retain_object ((COS_object)entry);
221 table->data[i] = entry;
224 else if (entry == symbol)
229 if (cos_symbol_table_grow (table) == 0)
230 return cos_symbol_table_set (table, symbol);
235 cos_symbol_table_grow (COS_Symbol_Table table)
237 COS_Symbol_Table new_table
238 = cos_make_symbol_table_0 ( table->size * 2
239 /* - (table->size * 4 / 5) */ );
242 if (new_table == NULL)
245 for (i = 0; i < table->size; i++)
247 COS_Symbol entry = table->data[i];
251 int status = cos_symbol_table_set (new_table, entry);
255 cos_destroy_symbol_table_0 (new_table);
260 table->size = new_table->size;
261 table->data = new_table->data;