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 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 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 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 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 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 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 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 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 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