Home | History | Annotate | Download | only in src
      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