1 /*---------------------------------------------------------------------------*
2 * SymbolTable.c *
3 * *
4 * Copyright 2007, 2008 Nuance Communciations, Inc. *
5 * *
6 * Licensed under the Apache License, Version 2.0 (the 'License'); *
7 * you may not use this file except in compliance with the License. *
8 * *
9 * You may obtain a copy of the License at *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, software *
13 * distributed under the License is distributed on an 'AS IS' BASIS, *
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15 * See the License for the specific language governing permissions and *
16 * limitations under the License. *
17 * *
18 *---------------------------------------------------------------------------*/
19
20 #include "SR_SymbolTable.h"
21 #include "plog.h"
22 #include "pmemory.h"
23
24
25 static const char* MTAG = __FILE__;
26
ST_Init(SymbolTable ** ptr)27 ESR_ReturnCode ST_Init(SymbolTable **ptr)
28 {
29 ESR_ReturnCode rc;
30
31 if (ptr == NULL)
32 {
33 PLogError(L("ESR_INVALID_ARGUMENT"));
34 return ESR_INVALID_ARGUMENT;
35 }
36 *ptr = NEW(SymbolTable, MTAG);
37
38 if (*ptr == NULL)
39 {
40 PLogError(L("ESR_OUT_OF_MEMORY"));
41 return ESR_OUT_OF_MEMORY;
42 }
43 CHKLOG(rc, HashMapCreate(&(*ptr)->hashmap));
44
45 (*ptr)->num_special_symbols = 0;
46
47 /* init the memory for the hashtable */
48 return ST_reset(*ptr);
49 CLEANUP:
50 return rc;
51 }
52
ST_Free(SymbolTable * self)53 ESR_ReturnCode ST_Free(SymbolTable *self)
54 {
55 ESR_ReturnCode rc;
56
57 if (self == NULL)
58 {
59 PLogError(L("ESR_INVALID_ARGUMENT"));
60 return ESR_INVALID_ARGUMENT;
61 }
62
63 /* free all the slots that were used
64 and remove all hashtable entries */
65 ST_reset(self);
66
67 /* delete the hash table */
68 if (self->hashmap)
69 CHKLOG(rc, HashMapDestroy(self->hashmap));
70
71 /* delete the symbol table */
72 if (self != NULL)
73 FREE(self);
74 return ESR_SUCCESS;
75 CLEANUP:
76 return rc;
77 }
78
ST_putKeyValue(SymbolTable * self,const LCHAR * key,const LCHAR * value)79 ESR_ReturnCode ST_putKeyValue(SymbolTable* self, const LCHAR* key, const LCHAR* value)
80 {
81 Symbol* symbol;
82 LCHAR* buf;
83 ESR_ReturnCode rc;
84
85 if (self == NULL || key == NULL || value == NULL)
86 {
87 PLogError(L("ESR_INVALID_ARGUMENT"));
88 return ESR_INVALID_ARGUMENT;
89 }
90 /* reuse the old entry if it exists
91 but if no old entry exists for this key then I need to create a new one */
92 rc = HashMapGet(self->hashmap, key, (void**) & buf);
93 if (rc == ESR_NO_MATCH_ERROR)
94 {
95 CHKLOG(rc, ST_getSymbolSlot(self, &symbol));
96
97 /* copy the key */
98 MEMCHK(rc, LSTRLEN(key), MAX_SEMPROC_KEY);
99 LSTRCPY(symbol->key, key);
100
101 /* creates a new entry if it does not already exist */
102 CHKLOG(rc, HashMapPut(self->hashmap, symbol->key, symbol->value));
103
104 /* for later */
105 buf = symbol->value;
106 }
107 else if (rc != ESR_SUCCESS)
108 return rc;
109
110 if (LSTRLEN(value) >= MAX_SEMPROC_VALUE)
111 PLogError("Warning: chopping length of value len %d > %d (%s)\n", LSTRLEN(value), MAX_SEMPROC_VALUE, value);
112 LSTRNCPY(buf, value, MAX_SEMPROC_VALUE);
113 buf[MAX_SEMPROC_VALUE-1] = 0;
114 /* MEMCHK(rc, LSTRLEN(value), MAX_SEMPROC_VALUE);
115 LSTRCPY(buf, value); */
116 return ESR_SUCCESS;
117 CLEANUP:
118 return rc;
119 }
120
ST_Copy(SymbolTable * self,HashMap * dst)121 ESR_ReturnCode ST_Copy(SymbolTable* self, HashMap* dst)
122 {
123 static const LCHAR* _MTAG = L("semproc.st.copy");
124 size_t i, size;
125 LCHAR *pkey;
126 LCHAR *pvalue;
127 LCHAR *copyValue;
128
129 if (!dst) return ESR_INVALID_ARGUMENT;
130
131 HashMapGetSize(self->hashmap, &size);
132 for (i = 0;i < size;i++)
133 {
134 HashMapGetKeyAtIndex(self->hashmap, i, &pkey);
135 HashMapGet(self->hashmap, pkey, (void **)&pvalue);
136 /* add one more space */
137 copyValue = (LCHAR*) CALLOC(LSTRLEN(pvalue) + 1, sizeof(LCHAR), _MTAG);
138 if (!copyValue)
139 {
140 PLogError(L("ESR_OUT_OF_MEMORY"));
141 return ESR_OUT_OF_MEMORY;
142 }
143 LSTRCPY(copyValue, pvalue);
144 HashMapPut(dst, pkey, copyValue);
145 }
146 return ESR_SUCCESS;
147 }
148
ST_getKeyValue(SymbolTable * self,const LCHAR * key,LCHAR ** value)149 ESR_ReturnCode ST_getKeyValue(SymbolTable* self, const LCHAR* key, LCHAR** value)
150 {
151 ESR_ReturnCode rc;
152 LCHAR *dot;
153 size_t i;
154
155 if (self == NULL || key == NULL || value == NULL)
156 {
157 PLogError(L("ESR_INVALID_ARGUMENT"));
158 return ESR_INVALID_ARGUMENT;
159 }
160
161 rc = HashMapGet(self->hashmap, key, (void**)value);
162
163 if (rc == ESR_SUCCESS || rc != ESR_NO_MATCH_ERROR)
164 return rc;
165
166 if (rc == ESR_NO_MATCH_ERROR)
167 {
168 /* handle SPECIAL CASEs */
169 for (i = 0;i < self->num_special_symbols; i++)
170 {
171 /* try as is */
172 if (!LSTRCMP(key, self->SpecialSymbols[i].key))
173 {
174 *value = self->SpecialSymbols[i].value;
175 return ESR_SUCCESS;
176 }
177
178 /* try without dot */
179 dot = LSTRCHR(key, L('.'));
180 if (dot)
181 key = ++dot;
182
183 /* is it a match? */
184 if (!LSTRCMP(key, self->SpecialSymbols[i].key))
185 {
186 *value = self->SpecialSymbols[i].value;
187 return ESR_SUCCESS;
188 }
189 }
190 }
191
192 *value = UNDEFINED_SYMBOL;
193 return ESR_SUCCESS;
194 }
195
ST_getSymbolSlot(SymbolTable * ptr,Symbol ** slot)196 ESR_ReturnCode ST_getSymbolSlot(SymbolTable* ptr, Symbol** slot)
197 {
198 ESR_ReturnCode rc;
199
200 if (ptr == NULL || slot == NULL)
201 {
202 PLogError(L("ESR_INVALID_ARGUMENT"));
203 return ESR_INVALID_ARGUMENT;
204 }
205
206 *slot = ptr->next++;
207 MEMCHK(rc, ptr->next, &ptr->Symbols[MAX_SYMBOLS-1]);
208 return ESR_SUCCESS;
209 CLEANUP:
210 return rc;
211 }
212
ST_reset(SymbolTable * ptr)213 ESR_ReturnCode ST_reset(SymbolTable *ptr)
214 {
215 int i;
216 ESR_ReturnCode rc;
217
218 if (ptr == NULL)
219 {
220 PLogError(L("ESR_INVALID_ARGUMENT"));
221 return ESR_INVALID_ARGUMENT;
222 }
223 CHKLOG(rc, HashMapRemoveAll(ptr->hashmap));
224 ptr->next = &ptr->Symbols[0];
225 for (i = 0; i < MAX_SYMBOLS; i++)
226 {
227 ptr->Symbols[i].key[0] = 0;
228 ptr->Symbols[i].value[0] = 0;
229 }
230 return ESR_SUCCESS;
231 CLEANUP:
232 return rc;
233 }
234
ST_reset_all(SymbolTable * ptr)235 ESR_ReturnCode ST_reset_all(SymbolTable *ptr)
236 {
237 int i;
238 ESR_ReturnCode rc;
239
240 if (ptr == NULL)
241 {
242 PLogError(L("ESR_INVALID_ARGUMENT"));
243 return ESR_INVALID_ARGUMENT;
244 }
245 CHKLOG(rc, HashMapRemoveAll(ptr->hashmap));
246 ptr->next = &ptr->Symbols[0
247 ];
248 for (i = 0; i < MAX_SYMBOLS; i++)
249 {
250 ptr->Symbols[i].key[0] = 0;
251 ptr->Symbols[i].value[0] = 0;
252 }
253 for (i = 0; i < MAX_SPECIAL_SYMBOLS; i++)
254 {
255 ptr->SpecialSymbols[i].key[0] = 0;
256 ptr->SpecialSymbols[i].value[0] = 0;
257 }
258 ptr->num_special_symbols = 0;
259 return ESR_SUCCESS;
260 CLEANUP:
261 return rc;
262 }
263
ST_putSpecialKeyValue(SymbolTable * self,const LCHAR * key,const LCHAR * value)264 ESR_ReturnCode ST_putSpecialKeyValue(SymbolTable* self, const LCHAR* key, const LCHAR* value)
265 {
266 size_t i;
267
268 if (self == NULL || key == NULL || value == NULL)
269 {
270 PLogError(L("ESR_INVALID_ARGUMENT"));
271 return ESR_INVALID_ARGUMENT;
272 }
273
274 /* see if already there, and overwrite */
275 for (i = 0;i < self->num_special_symbols;i++)
276 {
277 if (!LSTRCMP(self->SpecialSymbols[i].key, key))
278 {
279 LSTRCPY(self->SpecialSymbols[i].value, value);
280 return ESR_SUCCESS;
281 }
282 }
283
284 if (self->num_special_symbols < MAX_SPECIAL_SYMBOLS)
285 {
286 LSTRCPY(self->SpecialSymbols[self->num_special_symbols].key, key);
287 LSTRCPY(self->SpecialSymbols[self->num_special_symbols].value, value);
288 ++self->num_special_symbols;
289 return ESR_SUCCESS;
290 }
291 PLogError(L("Semproc: Symbol table has too many special symbols"));
292 return ESR_BUFFER_OVERFLOW;
293 }
294