Home | History | Annotate | Download | only in src
      1 /*---------------------------------------------------------------------------*
      2  *  SessionTypeImpl.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 
     21 #include "ESR_SessionType.h"
     22 #include "ESR_SessionTypeImpl.h"
     23 #include "HashMap.h"
     24 #include "IntArrayList.h"
     25 #include "LCHAR.h"
     26 #include "lstring.h"
     27 #include "passert.h"
     28 #include "pendian.h"
     29 #include "PFile.h"
     30 #include "PFileSystem.h"
     31 #include "plog.h"
     32 #include "pmemory.h"
     33 #include "pstdio.h"
     34 #include "string.h"
     35 #include "ESR_SessionTypeListener.h"
     36 
     37 #define MTAG NULL
     38 
     39 ESR_ReturnCode ESR_SessionTypeCreate(ESR_SessionType** self)
     40 {
     41   ESR_SessionType* Interface;
     42   ESR_SessionTypeData* data;
     43   ESR_ReturnCode rc;
     44 
     45   if (self == NULL)
     46   {
     47     PLogError(L("ESR_OUT_OF_MEMORY"));
     48     return ESR_OUT_OF_MEMORY;
     49   }
     50   Interface = NEW(ESR_SessionType, MTAG);
     51   if (Interface == NULL)
     52   {
     53     PLogError(L("ESR_OUT_OF_MEMORY"));
     54     return ESR_OUT_OF_MEMORY;
     55   }
     56   data = NEW(ESR_SessionTypeData, MTAG);
     57   if (data == NULL)
     58   {
     59     rc = ESR_OUT_OF_MEMORY;
     60     goto CLEANUP;
     61   }
     62 
     63 
     64   Interface->addListener = &ESR_SessionTypeAddListenerImpl;
     65   Interface->contains = &ESR_SessionTypeContainsImpl;
     66   Interface->convertToBool = &ESR_SessionTypeConvertToBoolImpl;
     67   Interface->convertToFloat = &ESR_SessionTypeConvertToFloatImpl;
     68   Interface->convertToInt = &ESR_SessionTypeConvertToIntImpl;
     69   Interface->convertToUint16_t = &ESR_SessionTypeConvertToUint16_tImpl;
     70   Interface->convertToSize_t = &ESR_SessionTypeConvertToSize_tImpl;
     71   Interface->destroy = &ESR_SessionTypeDestroyImpl;
     72   Interface->getBool = &ESR_SessionTypeGetBoolImpl;
     73   Interface->getFloat = &ESR_SessionTypeGetFloatImpl;
     74   Interface->getInt = &ESR_SessionTypeGetIntImpl;
     75   Interface->getUint16_t = &ESR_SessionTypeGetUint16_tImpl;
     76   Interface->getKeyAtIndex = &ESR_SessionTypeGetKeyAtIndexImpl;
     77   Interface->getLCHAR = &ESR_SessionTypeGetLCHARImpl;
     78   Interface->getProperty = &ESR_SessionTypeGetPropertyImpl;
     79   Interface->getPropertyType = &ESR_SessionTypeGetPropertyTypeImpl;
     80   Interface->getSize = &ESR_SessionTypeGetSizeImpl;
     81   Interface->getSize_t = &ESR_SessionTypeGetSize_tImpl;
     82   Interface->importCommandLine = &ESR_SessionTypeImportCommandLineImpl;
     83   Interface->importParFile = &ESR_SessionTypeImportParFileImpl;
     84   Interface->removeProperty = &ESR_SessionTypeRemovePropertyImpl;
     85   Interface->removeAndFreeProperty = &ESR_SessionTypeRemoveAndFreePropertyImpl;
     86   Interface->setBool = &ESR_SessionTypeSetBoolImpl;
     87   Interface->setBoolIfEmpty = &ESR_SessionTypeSetBoolIfEmptyImpl;
     88   Interface->setFloat = &ESR_SessionTypeSetFloatImpl;
     89   Interface->setFloatIfEmpty = &ESR_SessionTypeSetFloatIfEmptyImpl;
     90   Interface->setInt = &ESR_SessionTypeSetIntImpl;
     91   Interface->setIntIfEmpty = &ESR_SessionTypeSetIntIfEmptyImpl;
     92   Interface->setUint16_t = &ESR_SessionTypeSetUint16_tImpl;
     93   Interface->setUint16_tIfEmpty = &ESR_SessionTypeSetUint16_tIfEmptyImpl;
     94   Interface->setLCHAR = &ESR_SessionTypeSetLCHARImpl;
     95   Interface->setLCHARIfEmpty = &ESR_SessionTypeSetLCHARIfEmptyImpl;
     96   Interface->setProperty = &ESR_SessionTypeSetPropertyImpl;
     97   Interface->setSize_t = &ESR_SessionTypeSetSize_tImpl;
     98   Interface->setSize_tIfEmpty = &ESR_SessionTypeSetSize_tIfEmptyImpl;
     99   Interface->removeListener = &ESR_SessionTypeRemoveListenerImpl;
    100 
    101   Interface->data = data;
    102   data->value = NULL;
    103   data->listeners = NULL;
    104 
    105   CHK(rc, HashMapCreate(&data->value));
    106   CHK(rc, ArrayListCreate(&data->listeners));
    107   *self = Interface;
    108   return ESR_SUCCESS;
    109 CLEANUP:
    110   Interface->destroy(Interface);
    111   return rc;
    112 }
    113 
    114 /*
    115  * Because there are no functions to set and get int size_t parameters and because most if not
    116  * all int parameters should be size_t anyway, I am adding code to allow size_t and int parameters
    117  * to be considered equal. Besides, this check is kind of overkill anyway. SteveR
    118  */
    119 
    120 ESR_ReturnCode ESR_SessionTypeGetPropertyImpl(ESR_SessionType* self,
    121     const LCHAR* name, void** value,
    122     VariableTypes type)
    123 {
    124   ESR_SessionTypeData* data = self->data;
    125   ESR_SessionPair* pair;
    126   ESR_ReturnCode rc;
    127 
    128   CHK(rc, HashMapGet(data->value, name, (void **)&pair));
    129   if ( ( pair->type != type) && ( ( ( pair->type != TYPES_INT ) && ( type != TYPES_SIZE_T ) ) ||
    130       ( ( type != TYPES_INT ) && ( pair->type != TYPES_SIZE_T ) ) ) )
    131   {
    132     PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), type, pair->type);
    133     return ESR_INVALID_RESULT_TYPE;
    134   }
    135   *value = pair->value;
    136   return ESR_SUCCESS;
    137 CLEANUP:
    138   return rc;
    139 }
    140 
    141 ESR_ReturnCode ESR_SessionTypeGetIntImpl(ESR_SessionType* self,
    142     const LCHAR* name, int* value)
    143 {
    144   ESR_ReturnCode rc;
    145   ESR_SessionTypeData* data;
    146   ESR_SessionPair* pair;
    147 
    148   data = self->data;
    149   CHK(rc, HashMapGet(data->value, name, (void **)&pair));
    150   if ( ( pair->type != TYPES_INT ) && ( pair->type != TYPES_SIZE_T ) )
    151   {
    152     PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), TYPES_INT, pair->type);
    153     return ESR_INVALID_RESULT_TYPE;
    154   }
    155   *value = *((int*) pair->value);
    156   return ESR_SUCCESS;
    157 CLEANUP:
    158   return rc;
    159 }
    160 
    161 ESR_ReturnCode ESR_SessionTypeGetUint16_tImpl(ESR_SessionType* self,
    162     const LCHAR* name, asr_uint16_t* value)
    163 {
    164   ESR_ReturnCode rc;
    165   ESR_SessionTypeData* data;
    166   ESR_SessionPair* pair;
    167 
    168   data = self->data;
    169   CHK(rc, HashMapGet(data->value, name, (void **)&pair));
    170   if (pair->type != TYPES_UINT16_T)
    171   {
    172     PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), TYPES_UINT16_T, pair->type);
    173     return ESR_INVALID_RESULT_TYPE;
    174   }
    175   *value = *((asr_uint16_t*) pair->value);
    176   return ESR_SUCCESS;
    177 CLEANUP:
    178   return rc;
    179 }
    180 
    181 ESR_ReturnCode ESR_SessionTypeGetSize_tImpl(ESR_SessionType* self,
    182     const LCHAR* name,
    183     size_t* value)
    184 {
    185   ESR_ReturnCode rc;
    186   ESR_SessionTypeData* data;
    187   ESR_SessionPair* pair;
    188 
    189   data = self->data;
    190   CHKLOG(rc, HashMapGet(data->value, name, (void **)&pair));
    191   if ( ( pair->type != TYPES_INT ) && ( pair->type != TYPES_SIZE_T ) )
    192   {
    193     PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), TYPES_SIZE_T, pair->type);
    194     return ESR_INVALID_RESULT_TYPE;
    195   }
    196   *value = *((size_t*) pair->value);
    197   return ESR_SUCCESS;
    198 CLEANUP:
    199   return rc;
    200 }
    201 
    202 ESR_ReturnCode ESR_SessionTypeGetFloatImpl(ESR_SessionType* self,
    203     const LCHAR* name, float* value)
    204 {
    205   ESR_ReturnCode rc;
    206   ESR_SessionTypeData* data;
    207   ESR_SessionPair* pair;
    208 
    209   data = self->data;
    210   CHK(rc, HashMapGet(data->value, name, (void **)&pair));
    211   if (pair->type != TYPES_FLOAT)
    212   {
    213     PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), TYPES_FLOAT, pair->type);
    214     return ESR_INVALID_RESULT_TYPE;
    215   }
    216   *value = *((float*) pair->value);
    217   return ESR_SUCCESS;
    218 CLEANUP:
    219   return rc;
    220 }
    221 
    222 ESR_ReturnCode ESR_SessionTypeGetBoolImpl(ESR_SessionType* self,
    223     const LCHAR* name, ESR_BOOL* value)
    224 {
    225   ESR_ReturnCode rc;
    226   ESR_SessionTypeData* data;
    227   ESR_SessionPair* pair;
    228 
    229   data = self->data;
    230   CHK(rc, HashMapGet(data->value, name, (void **)&pair));
    231   if (pair->type != TYPES_BOOL)
    232   {
    233     PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), TYPES_BOOL, pair->type);
    234     return ESR_INVALID_RESULT_TYPE;
    235   }
    236   *value = *((ESR_BOOL*) pair->value);
    237   return ESR_SUCCESS;
    238 CLEANUP:
    239   return rc;
    240 }
    241 
    242 ESR_ReturnCode ESR_SessionTypeGetLCHARImpl(ESR_SessionType* self,
    243     const LCHAR* name,
    244     LCHAR* value, size_t* len)
    245 {
    246   LCHAR* lValue;
    247   ESR_ReturnCode rc;
    248   ESR_SessionTypeData* data;
    249   ESR_SessionPair* pair;
    250 
    251   if (name == NULL || value == NULL || len == NULL)
    252     return ESR_INVALID_ARGUMENT;
    253   data = self->data;
    254 
    255   CHK(rc, HashMapGet(data->value, name, (void **)&pair));
    256   if (pair->type != TYPES_PLCHAR)
    257   {
    258     PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), TYPES_PLCHAR, pair->type);
    259     return ESR_INVALID_RESULT_TYPE;
    260   }
    261   lValue = (LCHAR*) pair->value;
    262   if (LSTRLEN(pair->value) + 1 > *len)
    263   {
    264     *len = LSTRLEN(lValue) + 1;
    265     return ESR_BUFFER_OVERFLOW;
    266   }
    267   LSTRCPY(value, lValue);
    268   return ESR_SUCCESS;
    269 CLEANUP:
    270   return rc;
    271 }
    272 
    273 ESR_ReturnCode ESR_SessionTypeContainsImpl(ESR_SessionType* self,
    274     const LCHAR* name, ESR_BOOL* exists)
    275 {
    276   ESR_SessionTypeData* data = self->data;
    277 
    278   return HashMapContainsKey(data->value, name, exists);
    279 }
    280 
    281 static ESR_ReturnCode firePropertyChanged(ESR_SessionType* self, const LCHAR* name,
    282     const void* oldValue, const void* newValue,
    283     enum VariableTypes_t type)
    284 {
    285   ESR_SessionTypeData* data = self->data;
    286   ArrayList* list = data->listeners;
    287   size_t size, i;
    288   ESR_SessionTypeListenerPair* listener;
    289   ESR_ReturnCode rc;
    290 
    291   CHKLOG(rc, list->getSize(list, &size));
    292   for (i = 0; i < size; ++i)
    293   {
    294     CHKLOG(rc, list->get(list, i, (void **)&listener));
    295     CHKLOG(rc, listener->listener->propertyChanged(listener->listener, name, oldValue, newValue, type, listener->data));
    296   }
    297   return ESR_SUCCESS;
    298 CLEANUP:
    299   return rc;
    300 }
    301 
    302 ESR_ReturnCode ESR_SessionTypeSetPropertyImpl(ESR_SessionType* self,
    303     const LCHAR* name, void* value,
    304     VariableTypes type)
    305 {
    306   ESR_SessionTypeData* data = self->data;
    307   ESR_SessionPair* pair = NULL;
    308   ESR_BOOL exists;
    309   ESR_ReturnCode rc;
    310 
    311   CHKLOG(rc, HashMapContainsKey(data->value, name, &exists));
    312   if ( exists )
    313   {
    314 /* We allow change of parameters through the recognizer and we rely on the recognizer to do
    315  * all of the needed validation. SteveR
    316  */
    317 /* Deleting the old entry seems stupid, but it's the only way to prevent a memory leak,
    318  * since the old data is not returned when you add the new data. SteveR
    319  */
    320     CHKLOG ( rc, ESR_SessionTypeRemoveAndFreePropertyImpl ( self, name ) );
    321   }
    322   pair = NEW(ESR_SessionPair, MTAG);
    323   if (pair == NULL)
    324   {
    325     PLogError(L("ESR_OUT_OF_MEMORY"));
    326     return ESR_OUT_OF_MEMORY;
    327   }
    328   pair->value = value;
    329   pair->type = type;
    330 
    331   CHKLOG(rc, firePropertyChanged(self, name, NULL, value, type));
    332   CHKLOG(rc, HashMapPut(data->value, name, pair));
    333   return ESR_SUCCESS;
    334 CLEANUP:
    335 /* The cleanup potentially leaks memory which could be cleard up with  FREE ( pair->value );
    336  * but you can't guarantee that the value was allocated. A leak is better than a crash. SteveR
    337  */
    338   FREE(pair);
    339   return rc;
    340 }
    341 
    342 ESR_ReturnCode ESR_SessionTypeSetIntImpl(ESR_SessionType* self,
    343     const LCHAR* name, int value)
    344 {
    345   ESR_SessionTypeData* data;
    346   int* clone;
    347 
    348   data = self->data;
    349   clone = MALLOC(sizeof(int), MTAG);
    350   if (clone == NULL)
    351   {
    352     PLogError(L("ESR_OUT_OF_MEMORY"));
    353     return ESR_OUT_OF_MEMORY;
    354   }
    355 
    356   *clone = value;
    357   return self->setProperty(self, name, clone, TYPES_INT);
    358 }
    359 
    360 ESR_ReturnCode ESR_SessionTypeSetUint16_tImpl(ESR_SessionType* self,
    361     const LCHAR* name, asr_uint16_t value)
    362 {
    363   ESR_SessionTypeData* data;
    364   asr_uint16_t* clone;
    365 
    366   data = self->data;
    367   clone = MALLOC(sizeof(asr_uint16_t), MTAG);
    368   if (clone == NULL)
    369   {
    370     PLogError(L("ESR_OUT_OF_MEMORY"));
    371     return ESR_OUT_OF_MEMORY;
    372   }
    373 
    374   *clone = value;
    375   return self->setProperty(self, name, clone, TYPES_UINT16_T);
    376 }
    377 
    378 ESR_ReturnCode ESR_SessionTypeSetSize_tImpl(ESR_SessionType* self,
    379     const LCHAR* name, size_t value)
    380 {
    381   ESR_SessionTypeData* data;
    382   int* clone;
    383 
    384   data = self->data;
    385   clone = MALLOC(sizeof(size_t), MTAG);
    386   if (clone == NULL)
    387   {
    388     PLogError(L("ESR_OUT_OF_MEMORY"));
    389     return ESR_OUT_OF_MEMORY;
    390   }
    391 
    392   *clone = value;
    393   return self->setProperty(self, name, clone, TYPES_SIZE_T);
    394 }
    395 
    396 ESR_ReturnCode ESR_SessionTypeSetFloatImpl(ESR_SessionType* self,
    397     const LCHAR* name, float value)
    398 {
    399   ESR_SessionTypeData* data;
    400   float* clone;
    401 
    402   data = self->data;
    403   clone = MALLOC(sizeof(float), MTAG);
    404   if (clone == NULL)
    405   {
    406     PLogError(L("ESR_OUT_OF_MEMORY"));
    407     return ESR_OUT_OF_MEMORY;
    408   }
    409 
    410   *clone = value;
    411   return self->setProperty(self, name, clone, TYPES_FLOAT);
    412 }
    413 
    414 ESR_ReturnCode ESR_SessionTypeSetBoolImpl(ESR_SessionType* self,
    415     const LCHAR* name, ESR_BOOL value)
    416 {
    417   ESR_SessionTypeData* data;
    418   ESR_BOOL* clone;
    419 
    420   data = self->data;
    421   clone = MALLOC(sizeof(ESR_BOOL), MTAG);
    422   if (clone == NULL)
    423   {
    424     PLogError(L("ESR_OUT_OF_MEMORY"));
    425     return ESR_OUT_OF_MEMORY;
    426   }
    427 
    428   *clone = value;
    429   return self->setProperty(self, name, clone, TYPES_BOOL);
    430 }
    431 
    432 ESR_ReturnCode ESR_SessionTypeSetLCHARImpl(ESR_SessionType* self,
    433     const LCHAR* name, LCHAR* value)
    434 {
    435   ESR_SessionTypeData* data;
    436   LCHAR* clone;
    437 
    438   data = self->data;
    439   clone = MALLOC(sizeof(LCHAR) * (LSTRLEN(value) + 1), MTAG);
    440   if (clone == NULL)
    441   {
    442     PLogError(L("ESR_OUT_OF_MEMORY"));
    443     return ESR_OUT_OF_MEMORY;
    444   }
    445 
    446   LSTRCPY(clone, value);
    447   return self->setProperty(self, name, clone, TYPES_PLCHAR);
    448 }
    449 
    450 ESR_ReturnCode ESR_SessionTypeSetIntIfEmptyImpl(ESR_SessionType* self,
    451     const LCHAR* name, int value)
    452 {
    453   ESR_BOOL exists;
    454   ESR_ReturnCode rc;
    455 
    456   CHK(rc, self->contains(self, name, &exists));
    457   if (exists)
    458     return ESR_SUCCESS;
    459   return self->setInt(self, name, value);
    460 CLEANUP:
    461   return rc;
    462 }
    463 
    464 ESR_ReturnCode ESR_SessionTypeSetUint16_tIfEmptyImpl(ESR_SessionType* self,
    465     const LCHAR* name, asr_uint16_t value)
    466 {
    467   ESR_BOOL exists;
    468   ESR_ReturnCode rc;
    469 
    470   CHK(rc, self->contains(self, name, &exists));
    471   if (exists)
    472     return ESR_SUCCESS;
    473   return self->setInt(self, name, value);
    474 CLEANUP:
    475   return rc;
    476 }
    477 
    478 ESR_ReturnCode ESR_SessionTypeSetSize_tIfEmptyImpl(ESR_SessionType* self,
    479     const LCHAR* name, size_t value)
    480 {
    481   ESR_BOOL exists;
    482   ESR_ReturnCode rc;
    483 
    484   CHK(rc, self->contains(self, name, &exists));
    485   if (exists)
    486     return ESR_SUCCESS;
    487   return self->setSize_t(self, name, value);
    488 CLEANUP:
    489   return rc;
    490 }
    491 
    492 ESR_ReturnCode ESR_SessionTypeSetFloatIfEmptyImpl(ESR_SessionType* self,
    493     const LCHAR* name, float value)
    494 {
    495   ESR_BOOL exists;
    496   ESR_ReturnCode rc;
    497 
    498   CHK(rc, self->contains(self, name, &exists));
    499   if (exists)
    500     return ESR_SUCCESS;
    501   return self->setFloat(self, name, value);
    502 CLEANUP:
    503   return rc;
    504 }
    505 
    506 ESR_ReturnCode ESR_SessionTypeSetBoolIfEmptyImpl(ESR_SessionType* self,
    507     const LCHAR* name, ESR_BOOL value)
    508 {
    509   ESR_BOOL exists;
    510   ESR_ReturnCode rc;
    511 
    512   CHK(rc, self->contains(self, name, &exists));
    513   if (exists)
    514     return ESR_SUCCESS;
    515   return self->setBool(self, name, value);
    516 CLEANUP:
    517   return rc;
    518 }
    519 
    520 ESR_ReturnCode ESR_SessionTypeSetLCHARIfEmptyImpl(ESR_SessionType* self,
    521     const LCHAR* name, LCHAR* value)
    522 {
    523   ESR_BOOL exists;
    524   ESR_ReturnCode rc;
    525 
    526   CHK(rc, self->contains(self, name, &exists));
    527   if (exists)
    528     return ESR_SUCCESS;
    529   return self->setLCHAR(self, name, value);
    530 CLEANUP:
    531   return rc;
    532 }
    533 
    534 ESR_ReturnCode ESR_SessionTypeRemovePropertyImpl(ESR_SessionType* self,
    535     const LCHAR* name)
    536 {
    537   ESR_ReturnCode rc;
    538   ESR_SessionTypeData* data = self->data;
    539   ESR_SessionPair* pair;
    540 
    541   CHK(rc, HashMapGet(data->value, name, (void **)&pair));
    542   CHKLOG(rc, firePropertyChanged(self, name, pair->value, NULL, pair->type));
    543   CHK(rc, HashMapRemove(data->value, name));
    544   FREE(pair);
    545   return ESR_SUCCESS;
    546 CLEANUP:
    547   return rc;
    548 }
    549 
    550 ESR_ReturnCode ESR_SessionTypeRemoveAndFreePropertyImpl(ESR_SessionType* self,
    551     const LCHAR* name)
    552 {
    553   ESR_ReturnCode rc;
    554   ESR_SessionTypeData* data = self->data;
    555   ESR_SessionPair* pair;
    556   ESR_SessionPair temp;
    557   IntArrayList* intList;
    558 
    559   CHK(rc, data->value->get(data->value, name, (void **)&pair));
    560   temp = *pair;
    561   CHK(rc, self->removeProperty(self, name));
    562   if (temp.value)
    563   {
    564     if (temp.type == TYPES_INTARRAYLIST)
    565     {
    566       intList = temp.value;
    567       intList->destroy(intList);
    568     }
    569     else
    570       FREE(temp.value);
    571   }
    572   return ESR_SUCCESS;
    573 CLEANUP:
    574   return rc;
    575 }
    576 
    577 ESR_ReturnCode ESR_SessionTypeImportCommandLineImpl(ESR_SessionType* self,
    578     int argc, LCHAR* argv[])
    579 {
    580   char* key = NULL;
    581   char* value = NULL;
    582   VariableTypes type;
    583   ESR_ReturnCode rc;
    584 
    585   while (--argc > 0 && **++argv)
    586   {
    587     if (**argv != '-')
    588     {
    589       /* got value */
    590       if (key == NULL)
    591       {
    592         /* but we don't have any key to associate it with */
    593         pfprintf(PSTDERR, "Options must be prefixed by '-'%s\n", *argv);
    594       }
    595       else
    596       {
    597         rc = self->getPropertyType(self, key, &type);
    598         if (rc == ESR_SUCCESS)
    599         {
    600           CHKLOG(rc, self->getProperty(self, key, (void **)&value, type));
    601           CHKLOG(rc, self->removeProperty(self, key));
    602           FREE(value);
    603           value = NULL;
    604         }
    605         else if (rc != ESR_NO_MATCH_ERROR)
    606         {
    607           PLogError(ESR_rc2str(rc));
    608           goto CLEANUP;
    609         }
    610         value = MALLOC(sizeof(LCHAR) * (strlen(*argv) + 1), MTAG);
    611         if (value == NULL)
    612         {
    613           rc = ESR_OUT_OF_MEMORY;
    614           PLogError(L("ESR_OUT_OF_MEMORY"));
    615           goto CLEANUP;
    616         }
    617         LSTRCPY(value, *argv);
    618         CHKLOG(rc, self->setProperty(self, key, value, TYPES_PLCHAR));
    619         FREE(key);
    620         key = NULL;
    621         value = NULL;
    622       }
    623     }
    624     else
    625     {
    626       /* got key */
    627       if (key != NULL)
    628       {
    629         /* But we already have a key without a value, so set the old key's value to "" */
    630         rc = self->getPropertyType(self, key, &type);
    631         if (rc == ESR_SUCCESS)
    632         {
    633           CHKLOG(rc, self->getProperty(self, key, (void **)&value, type));
    634           CHKLOG(rc, self->removeProperty(self, key));
    635           FREE(value);
    636           value = NULL;
    637         }
    638         else if (rc != ESR_NO_MATCH_ERROR)
    639         {
    640           PLogError(ESR_rc2str(rc));
    641           goto CLEANUP;
    642         }
    643         value = MALLOC(sizeof(LCHAR) + 1, MTAG);
    644         strcpy(value, "");
    645         CHKLOG(rc, self->setProperty(self, key, value, TYPES_PLCHAR));
    646         FREE(key);
    647         value = NULL;
    648       }
    649       key = MALLOC(sizeof(LCHAR) * (LSTRLEN("cmdline.") + LSTRLEN(*argv) + 1), MTAG);
    650       if (key == NULL)
    651       {
    652         rc = ESR_OUT_OF_MEMORY;
    653         PLogError(L("ESR_OUT_OF_MEMORY"));
    654         goto CLEANUP;
    655       }
    656       LSTRCPY(key, "cmdline.");
    657       LSTRCAT(key, *argv + 1);
    658     }
    659   }
    660   return ESR_SUCCESS;
    661 CLEANUP:
    662   if (key != NULL)
    663     FREE(key);
    664   if (value != NULL)
    665     FREE(value);
    666   return rc;
    667 }
    668 
    669 ESR_ReturnCode ESR_SessionTypeGetSizeImpl(ESR_SessionType* self, size_t* size)
    670 {
    671   ESR_SessionTypeData* data = self->data;
    672   ESR_ReturnCode rc;
    673 
    674   CHK(rc, HashMapGetSize(data->value, size));
    675   return ESR_SUCCESS;
    676 CLEANUP:
    677   return rc;
    678 }
    679 
    680 ESR_ReturnCode ESR_SessionTypeGetKeyAtIndexImpl(ESR_SessionType* self,
    681     size_t index, LCHAR** key)
    682 {
    683   ESR_SessionTypeData* data = self->data;
    684   ESR_ReturnCode rc;
    685 
    686   CHK(rc, HashMapGetKeyAtIndex(data->value, index, key));
    687   return ESR_SUCCESS;
    688 CLEANUP:
    689   return rc;
    690 }
    691 
    692 ESR_ReturnCode ESR_SessionTypeConvertToIntImpl(ESR_SessionType* self,
    693     const LCHAR* key)
    694 {
    695   LCHAR* value;
    696   int *newValue = NULL;
    697   ESR_ReturnCode rc;
    698 
    699   CHK(rc, self->getProperty(self, key, (void **)&value, TYPES_PLCHAR));
    700   if (value == NULL)
    701     return ESR_SUCCESS;
    702   newValue = MALLOC(sizeof(long), MTAG);
    703   if (newValue == NULL)
    704   {
    705     rc = ESR_OUT_OF_MEMORY;
    706     goto CLEANUP;
    707   }
    708   CHKLOG(rc, lstrtoi(value, newValue, 10));
    709   CHKLOG(rc, self->setProperty(self, key, newValue, TYPES_INT));
    710   FREE(value);
    711   return ESR_SUCCESS;
    712 CLEANUP:
    713   if (newValue != NULL)
    714     FREE(newValue);
    715   return rc;
    716 }
    717 
    718 ESR_ReturnCode ESR_SessionTypeConvertToUint16_tImpl(ESR_SessionType* self,
    719     const LCHAR* key)
    720 {
    721   LCHAR* value;
    722   int *newValue = NULL;
    723   ESR_ReturnCode rc;
    724 
    725   CHK(rc, self->getProperty(self, key, (void **)&value, TYPES_PLCHAR));
    726   if (value == NULL)
    727     return ESR_SUCCESS;
    728   newValue = MALLOC(sizeof(long), MTAG);
    729   if (newValue == NULL)
    730   {
    731     rc = ESR_OUT_OF_MEMORY;
    732     goto CLEANUP;
    733   }
    734   CHKLOG(rc, lstrtoi(value, newValue, 10));
    735   CHKLOG(rc, self->setProperty(self, key, newValue, TYPES_UINT16_T));
    736   FREE(value);
    737   return ESR_SUCCESS;
    738 CLEANUP:
    739   if (newValue != NULL)
    740     FREE(newValue);
    741   return rc;
    742 }
    743 
    744 ESR_ReturnCode ESR_SessionTypeConvertToSize_tImpl(ESR_SessionType* self,
    745     const LCHAR* key)
    746 {
    747   LCHAR* value;
    748   size_t* newValue = NULL;
    749   ESR_ReturnCode rc;
    750 
    751   CHK(rc, self->getProperty(self, key, (void **)&value, TYPES_PLCHAR));
    752   if (value == NULL)
    753     return ESR_SUCCESS;
    754   newValue = MALLOC(sizeof(size_t), MTAG);
    755   if (newValue == NULL)
    756   {
    757     rc = ESR_OUT_OF_MEMORY;
    758     goto CLEANUP;
    759   }
    760   CHKLOG(rc, lstrtoui(value, (unsigned int *)newValue, 10));
    761   CHKLOG(rc, self->setProperty(self, key, newValue, TYPES_SIZE_T));
    762   FREE(value);
    763   return ESR_SUCCESS;
    764 CLEANUP:
    765   if (newValue != NULL)
    766     FREE(newValue);
    767   return rc;
    768 }
    769 
    770 ESR_ReturnCode ESR_SessionTypeConvertToFloatImpl(ESR_SessionType* self,
    771     const LCHAR* key)
    772 {
    773   LCHAR* value;
    774   float *newValue = NULL;
    775   ESR_ReturnCode rc;
    776 
    777   CHK(rc, self->getProperty(self, key, (void **)&value, TYPES_PLCHAR));
    778   if (value == NULL)
    779     return ESR_SUCCESS;
    780   newValue = MALLOC(sizeof(double), MTAG);
    781   if (newValue == NULL)
    782   {
    783     rc = ESR_OUT_OF_MEMORY;
    784     goto CLEANUP;
    785   }
    786   CHKLOG(rc, lstrtof(value, newValue));
    787   CHKLOG(rc, self->setProperty(self, key, newValue, TYPES_FLOAT));
    788   FREE(value);
    789   return ESR_SUCCESS;
    790 CLEANUP:
    791   if (newValue != NULL)
    792     FREE(newValue);
    793   return rc;
    794 }
    795 
    796 ESR_ReturnCode ESR_SessionTypeConvertToBoolImpl(ESR_SessionType* self,
    797     const LCHAR* key)
    798 {
    799   LCHAR* value;
    800   ESR_BOOL *newValue = NULL;
    801   ESR_ReturnCode rc;
    802 
    803   CHK(rc, self->getProperty(self, key, (void **)&value, TYPES_PLCHAR));
    804   if (value == NULL)
    805     return ESR_SUCCESS;
    806   newValue = MALLOC(sizeof(ESR_BOOL), MTAG);
    807   if (newValue == NULL)
    808   {
    809     rc = ESR_OUT_OF_MEMORY;
    810     goto CLEANUP;
    811   }
    812   rc = lstrtob(value, newValue);
    813   if (rc != ESR_SUCCESS)
    814   {
    815     FREE(newValue);
    816     return rc;
    817   }
    818   rc = self->setProperty(self, key, newValue, TYPES_BOOL);
    819   if (rc != ESR_SUCCESS)
    820   {
    821     FREE(newValue);
    822     return rc;
    823   }
    824   FREE(value);
    825   return ESR_SUCCESS;
    826 CLEANUP:
    827   if (newValue != NULL)
    828     FREE(newValue);
    829   return rc;
    830 }
    831 
    832 /**
    833  * Imports file containing [key, value] pairs into session.
    834  *
    835  * @param self ESR_SessionType handle
    836  * @param filename File to read session from
    837  * @param addMapping Function used to map keys to their type and add them to the session
    838  * @param data Data used by the mapping function
    839  */
    840 static ESR_ReturnCode importKeyValueFile(ESR_SessionType* self,
    841     const LCHAR* filename,
    842     ESR_ReturnCode(*addMapping)(ESR_SessionType* self, const LCHAR* key, LCHAR* value, void* data),
    843     void* data)
    844 {
    845   const size_t LINE_SIZE = 512;
    846   LCHAR key[512];
    847   LCHAR buffer[512];
    848   LCHAR* value;
    849   LCHAR* ending;
    850   LCHAR* line;
    851   PFile* file = NULL;
    852   ESR_BOOL lineSpan = ESR_FALSE;
    853   LString* valueBuffer = NULL;
    854   ESR_ReturnCode rc = ESR_SUCCESS;
    855 
    856   if (filename == NULL)
    857     return ESR_INVALID_ARGUMENT;
    858 
    859   file = pfopen ( filename, L("r") );
    860 /*  CHKLOG(rc, PFileSystemCreatePFile(filename, ESR_TRUE, &file));
    861   CHKLOG(rc, PFileOpen(file, L("r")));*/
    862 
    863   if (file == NULL)
    864   {
    865     LCHAR msg[P_PATH_MAX + 30];
    866     LCHAR cwd[P_PATH_MAX];
    867     size_t len;
    868 
    869     len = P_PATH_MAX;
    870     CHKLOG(rc, pf_get_cwd (cwd, &len));
    871     psprintf(msg, L("ESR_OPEN_FILE_ERROR(filename=%s, cwd=%s)"), filename, cwd);
    872     rc = ESR_OPEN_ERROR;
    873     PLogError(msg);
    874     goto CLEANUP;
    875   }
    876 
    877   rc = LStringCreate(&valueBuffer);
    878   if (rc != ESR_SUCCESS)
    879     goto CLEANUP;
    880 
    881   line = buffer;
    882   while (ESR_TRUE)
    883   {
    884     line = pfgets(line, LINE_SIZE, file);
    885     if (line == NULL)
    886     {
    887       if (pfeof(file))
    888         break;
    889       rc = ESR_READ_ERROR;
    890       PLogError(ESR_rc2str(rc));
    891       goto CLEANUP;
    892     }
    893     if (LSTRLEN(line) == LINE_SIZE)
    894     {
    895       PLogError(L("%s: line surpasses %d character limit: '%s'"), filename, line);
    896       continue;
    897     }
    898     lstrtrim(line);
    899     if (LSTRLEN(line) == 0 || line[0] == '#')
    900       continue;
    901 
    902     if (!lineSpan)
    903     {
    904       if (rc != ESR_SUCCESS) goto CLEANUP;
    905 
    906       /* locate the key and value pair */
    907       ending = LSTRCHR(line, '=');
    908       if (ending == NULL)
    909       {
    910         fprintf(stderr, "Missing equal sign on line '%s'\n", line);
    911         continue;
    912       }
    913       *ending = L('\0');
    914       value = ending + 1;
    915     }
    916     else
    917       value = line;
    918 
    919     /* Optionally use ';' to denote end of value */
    920     ending = LSTRCHR(value, L(';'));
    921     if (ending != NULL)
    922       *ending = L('\0');
    923     else
    924     {
    925       ending = LSTRCHR(value, L('\n'));
    926       if (ending != NULL)
    927         *ending = L('\0');
    928     }
    929     if (!lineSpan)
    930     {
    931       LSTRCPY(key, line);
    932       lstrtrim(key);
    933     }
    934     if (LSTRLEN(value) == 0)
    935     {
    936       pfprintf(PSTDERR, L("Missing value for '%s'\n"), key);
    937       continue;
    938     }
    939     lstrtrim(value);
    940     if ((ending = LSTRCHR(value, '\\')) == (value + LSTRLEN(value) - 1))
    941     {
    942       /* found '\\' at end of line which means data will span to the next line */
    943       lineSpan = ESR_TRUE;
    944       *ending = L('\0');
    945     }
    946     else
    947       lineSpan = ESR_FALSE;
    948     rc = LStringAppend(valueBuffer, value);
    949     if (rc != ESR_SUCCESS)
    950     {
    951       PLogError(ESR_rc2str(rc));
    952       goto CLEANUP;
    953     }
    954     if (!lineSpan)
    955     {
    956       rc = LStringToLCHAR(valueBuffer, &value);
    957       valueBuffer = NULL;
    958       if (rc != ESR_SUCCESS)
    959       {
    960         PLogError(ESR_rc2str(rc));
    961         goto CLEANUP;
    962       }
    963       rc = addMapping(self, key, value, data);
    964       if (value != NULL)
    965       {
    966         FREE(value);
    967         value = NULL;
    968       }
    969       if (rc != ESR_SUCCESS)
    970       {
    971         PLogError(ESR_rc2str(rc));
    972         goto CLEANUP;
    973       }
    974       rc = LStringCreate(&valueBuffer);
    975       if (rc != ESR_SUCCESS)
    976       {
    977         PLogError(ESR_rc2str(rc));
    978         goto CLEANUP;
    979       }
    980     }
    981   }
    982 
    983   if (pferror(file))
    984   {
    985     rc = ESR_READ_ERROR;
    986     PLogError(ESR_rc2str(rc));
    987     goto CLEANUP;
    988   }
    989   if (pfclose(file) != 0)
    990   {
    991     rc = ESR_CLOSE_ERROR;
    992     PLogError(ESR_rc2str(rc));
    993     goto CLEANUP;
    994   }
    995   if (valueBuffer != NULL)
    996     LStringDestroy(valueBuffer);
    997   return ESR_SUCCESS;
    998 CLEANUP:
    999   if (file != NULL)
   1000     pfclose(file);
   1001   if (valueBuffer != NULL)
   1002     LStringDestroy(valueBuffer);
   1003   return rc;
   1004 }
   1005 
   1006 /**
   1007  * Appends a collection of integers stored in string format to an IntArrayList.
   1008  *
   1009  * @param self ESR_SessionType handle
   1010  * @param text Text containing integers
   1011  * @param list List to be populated
   1012  */
   1013 static ESR_ReturnCode parseIntList(ESR_SessionType* self,
   1014                                    LCHAR* text, IntArrayList* list)
   1015 {
   1016   size_t size, pos, beginning;
   1017   int value;
   1018   ESR_ReturnCode rc;
   1019 
   1020   size = LSTRLEN(text);
   1021   pos = 0;
   1022   while (ESR_TRUE)
   1023   {
   1024     /* Scan for beginning of next token */
   1025     for (; pos < size && LISSPACE(text[pos]); ++pos);
   1026 
   1027     if (pos >= size)
   1028     {
   1029       /* Reached end of string while looking for beginning of next token */
   1030       break;
   1031     }
   1032     beginning = pos;
   1033 
   1034     /* Scan for ending of current token */
   1035     for (; pos < size && !LISSPACE(text[pos]); ++pos);
   1036     text[pos] = L('\0');
   1037     CHKLOG(rc, lstrtoi(text + beginning, &value, 10));
   1038     CHKLOG(rc, IntArrayListAdd(list, value));
   1039     ++pos;
   1040   }
   1041   return ESR_SUCCESS;
   1042 CLEANUP:
   1043   return rc;
   1044 }
   1045 
   1046 ESR_ReturnCode ESR_SessionTypeGetPropertyTypeImpl(ESR_SessionType* self,
   1047     const LCHAR* name, VariableTypes* type)
   1048 {
   1049   ESR_SessionTypeData* data = self->data;
   1050   ESR_SessionPair* pair;
   1051   ESR_ReturnCode rc;
   1052 
   1053   CHK(rc, HashMapGet(data->value, name, (void **)&pair));
   1054   *type = pair->type;
   1055   return ESR_SUCCESS;
   1056 CLEANUP:
   1057   return rc;
   1058 }
   1059 
   1060 /**
   1061  * Maps key -> type for PAR files.
   1062  *
   1063  * @param self ESR_Session handle
   1064  * @param key Key name
   1065  * @param value The value
   1066  */
   1067 static ESR_ReturnCode addParMapping(ESR_SessionType* self,
   1068                                     const LCHAR* key, LCHAR* value, void* data)
   1069 {
   1070   IntArrayList* iList;
   1071   ESR_ReturnCode rc;
   1072   HashMap* map;
   1073   VariableTypes* type;
   1074   int iValue;
   1075   size_t size_tValue;
   1076   float fValue;
   1077   ESR_BOOL bValue;
   1078   ESR_BOOL exists;
   1079 
   1080   map = (HashMap*) data;
   1081   rc = HashMapGet(data, key, (void **)&type);
   1082   if (rc == ESR_NO_MATCH_ERROR)
   1083   {
   1084     /* If type is unknown, assume LCHAR* */
   1085     PLogMessage(L("Unknown parfile key '%s'"), key);
   1086     CHKLOG(rc, self->setLCHAR(self, key, value));
   1087   }
   1088   else if (rc == ESR_SUCCESS)
   1089   {
   1090     switch (*type)
   1091     {
   1092       case TYPES_INT:
   1093         CHKLOG(rc, lstrtoi(value, &iValue, 10));
   1094         CHKLOG(rc, self->contains(self, key, &exists));
   1095         if (exists)
   1096           CHKLOG(rc, self->removeAndFreeProperty(self, key));
   1097         CHKLOG(rc, self->setInt(self, key, iValue));
   1098         break;
   1099       case TYPES_UINT16_T:
   1100         CHKLOG(rc, lstrtoui(value, (unsigned int *)&size_tValue, 10));
   1101         passert(size_tValue >= UINT16_TMIN && size_tValue <= UINT16_TMAX);
   1102         CHKLOG(rc, self->contains(self, key, &exists));
   1103         if (exists)
   1104           CHKLOG(rc, self->removeAndFreeProperty(self, key));
   1105         CHKLOG(rc, self->setUint16_t(self, key, (asr_uint16_t) size_tValue));
   1106         break;
   1107       case TYPES_SIZE_T:
   1108         CHKLOG(rc, lstrtoui(value, (unsigned int *)&size_tValue, 10));
   1109         CHKLOG(rc, self->contains(self, key, &exists));
   1110         if (exists)
   1111           CHKLOG(rc, self->removeAndFreeProperty(self, key));
   1112         CHKLOG(rc, self->setSize_t(self, key, size_tValue));
   1113         break;
   1114       case TYPES_FLOAT:
   1115         CHKLOG(rc, lstrtof(value, &fValue));
   1116         CHKLOG(rc, self->contains(self, key, &exists));
   1117         if (exists)
   1118           CHKLOG(rc, self->removeAndFreeProperty(self, key));
   1119         CHKLOG(rc, self->setFloat(self, key, fValue));
   1120         break;
   1121       case TYPES_BOOL:
   1122         CHKLOG(rc, lstrtob(value, &bValue));
   1123         CHKLOG(rc, self->contains(self, key, &exists));
   1124         if (exists)
   1125           CHKLOG(rc, self->removeAndFreeProperty(self, key));
   1126         CHKLOG(rc, self->setBool(self, key, bValue));
   1127         break;
   1128       case TYPES_INTARRAYLIST:
   1129         CHKLOG(rc, self->contains(self, key, &exists));
   1130         if (exists)
   1131         {
   1132           CHKLOG(rc, self->getProperty(self, key, (void **)&iList, TYPES_INTARRAYLIST));
   1133           CHKLOG(rc, self->removeProperty(self, key));
   1134           CHKLOG(rc, iList->destroy(iList));
   1135         }
   1136         CHKLOG(rc, IntArrayListCreate(&iList));
   1137         CHKLOG(rc, parseIntList(self, value, iList));
   1138         CHKLOG(rc, self->setProperty(self, key, iList, TYPES_INTARRAYLIST));
   1139         break;
   1140       default:
   1141         passert(0); /* Unknown variable type. Assuming LCHAR* */
   1142       case TYPES_PLCHAR:
   1143         CHKLOG(rc, self->contains(self, key, &exists));
   1144         if (exists)
   1145           CHKLOG(rc, self->removeAndFreeProperty(self, key));
   1146         CHKLOG(rc, self->setLCHAR(self, key, value));
   1147         break;
   1148     }
   1149   }
   1150   return rc;
   1151 CLEANUP:
   1152   return rc;
   1153 }
   1154 
   1155 ESR_ReturnCode ESR_SessionTypeImportParFileImpl(ESR_SessionType* self,
   1156     const LCHAR* filename)
   1157 {
   1158   ESR_ReturnCode rc;
   1159   HashMap* parameterList;
   1160   VariableTypes Int = TYPES_INT;
   1161   VariableTypes UInt16_t = TYPES_UINT16_T;
   1162   VariableTypes Float = TYPES_FLOAT;
   1163   VariableTypes Bool = TYPES_BOOL;
   1164   VariableTypes IntArrayList = TYPES_INTARRAYLIST;
   1165   VariableTypes PLChar = TYPES_PLCHAR;
   1166   VariableTypes Size_t = TYPES_SIZE_T;
   1167 
   1168   /* Create [key, type] lookup table */
   1169   CHKLOG(rc, HashMapCreate(&parameterList));
   1170 
   1171   CHKLOG(rc, parameterList->put(parameterList, "cmdline.arbfile", &PLChar));
   1172   CHKLOG(rc, parameterList->put(parameterList, "cmdline.bgsniff", &Size_t));
   1173   CHKLOG(rc, parameterList->put(parameterList, "cmdline.channel", &PLChar));
   1174   CHKLOG(rc, parameterList->put(parameterList, "cmdline.datapath", &PLChar));
   1175   CHKLOG(rc, parameterList->put(parameterList, "cmdline.DataCaptureDirectory", &PLChar));
   1176   CHKLOG(rc, parameterList->put(parameterList, "cmdline.detail_res", &PLChar));
   1177   CHKLOG(rc, parameterList->put(parameterList, "cmdline.lda", &PLChar));
   1178   CHKLOG(rc, parameterList->put(parameterList, "cmdline.modelfiles", &PLChar));
   1179   CHKLOG(rc, parameterList->put(parameterList, "cmdline.modelfiles11", &PLChar));
   1180   CHKLOG(rc, parameterList->put(parameterList, "cmdline.modelfiles8", &PLChar));
   1181   CHKLOG(rc, parameterList->put(parameterList, "cmdline.lda11", &PLChar));
   1182   CHKLOG(rc, parameterList->put(parameterList, "cmdline.lda8", &PLChar));
   1183   CHKLOG(rc, parameterList->put(parameterList, "cmdline.results", &PLChar));
   1184   CHKLOG(rc, parameterList->put(parameterList, "cmdline.rules", &PLChar));
   1185   CHKLOG(rc, parameterList->put(parameterList, "cmdline.tcp", &PLChar));
   1186   CHKLOG(rc, parameterList->put(parameterList, "cmdline.multable", &PLChar));
   1187   CHKLOG(rc, parameterList->put(parameterList, "cmdline.parfile", &PLChar));
   1188   CHKLOG(rc, parameterList->put(parameterList, "cmdline.vocabulary", &PLChar));
   1189   CHKLOG(rc, parameterList->put(parameterList, "cmdline.use_image", &Int));
   1190   CHKLOG(rc, parameterList->put(parameterList, "cmdline.semproc_verbose", &Bool));
   1191   CHKLOG(rc, parameterList->put(parameterList, "cmdline.nametagPath", &PLChar));
   1192 
   1193   /* Beginning of speech detection stuff */
   1194   CHKLOG(rc, parameterList->put(parameterList, "cmdline.bgsniff_min", &Size_t));
   1195   CHKLOG(rc, parameterList->put(parameterList, "cmdline.silence_duration_in_frames", &Size_t));
   1196   CHKLOG(rc, parameterList->put(parameterList, "cmdline.end_of_utterance_hold_off_in_frames", &Size_t));
   1197   CHKLOG(rc, parameterList->put(parameterList, "cmdline.gatedmode", &Bool));
   1198 
   1199   /* new param from SREC that did not exist in CREC */
   1200   CHKLOG(rc, parameterList->put(parameterList, "SREC.Recognizer.utterance_timeout", &Size_t));
   1201   CHKLOG(rc, parameterList->put(parameterList, "SREC.Recognizer.osi_log_level", &Size_t));
   1202   CHKLOG(rc, parameterList->put(parameterList, "SREC.voice_enroll.bufsz_kB", &Size_t));
   1203   CHKLOG(rc, parameterList->put(parameterList, "SREC.voice_enroll.eos_comfort_frames", &Size_t));
   1204   CHKLOG(rc, parameterList->put(parameterList, "SREC.voice_enroll.bos_comfort_frames", &Size_t));
   1205 
   1206   CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.gdiff.one_nbest", &PLChar));
   1207   CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.gdiff.many_nbest", &PLChar));
   1208   CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.sd.one_nbest", &PLChar));
   1209   CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.sd.many_nbest", &PLChar));
   1210   CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.sd13.one_nbest", &PLChar));
   1211   CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.sd13.many_nbest", &PLChar));
   1212   CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.spf.one_nbest", &PLChar));
   1213   CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.spf.many_nbest", &PLChar));
   1214   CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.abs.one_nbest", &PLChar));
   1215   CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.abs.many_nbest", &PLChar));
   1216   CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.gdiffpf.one_nbest", &PLChar));
   1217   CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.gdiffpf.many_nbest", &PLChar));
   1218 
   1219   CHKLOG(rc, parameterList->put(parameterList, "CREC.ParVersion", &Float));
   1220   CHKLOG(rc, parameterList->put(parameterList, "CREC.useCREClogger", &Int));
   1221   CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.dimen", &Int));
   1222   CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.skip", &Int));
   1223   CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.stay", &Int));
   1224   CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.durscale", &Int));
   1225   CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.minvar", &Int));
   1226   CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.maxvar", &Int));
   1227   CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.frame_period", &Int));
   1228   CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.load_models", &PLChar));
   1229   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.mel_dim", &Int));
   1230   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.samplerate", &Size_t));
   1231   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.premel", &Float));
   1232   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.lowcut", &Int));
   1233   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.highcut", &Int));
   1234   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.window_factor", &Float));
   1235   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.offset", &Float));
   1236   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.ddmel", &Bool));
   1237   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.peakdecayup", &Float));
   1238   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.peakdecaydown", &Float));
   1239   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.do_skip_even_frames", &Bool));
   1240   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.do_smooth_c0", &Bool));
   1241   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.melA", &IntArrayList));
   1242   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.melB", &IntArrayList));
   1243   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.dmelA", &IntArrayList));
   1244   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.dmelB", &IntArrayList));
   1245   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.ddmelA", &IntArrayList));
   1246   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.ddmelB", &IntArrayList));
   1247 
   1248   /* new for S2G 3 (read from parfile instead of hardcoding) */
   1249   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.cmn", &IntArrayList));
   1250   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.cmn8", &IntArrayList));
   1251   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.cmn11", &IntArrayList));
   1252   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.tmn", &IntArrayList));
   1253   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.adjust", &IntArrayList));
   1254   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.debug", &Bool));
   1255   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.sbindex", &IntArrayList));
   1256   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.forget_factor", &IntArrayList));
   1257   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.cache_resolution", &IntArrayList));
   1258   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.inutt.forget_factor2", &IntArrayList));
   1259   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.inutt.disable_after", &IntArrayList));
   1260   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.inutt.enable_after", &IntArrayList));
   1261 
   1262 
   1263   /* zwz */
   1264   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.do_VN", &Bool));
   1265 
   1266   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.speech_detect", &Int));
   1267   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.ambient_within", &Int));
   1268   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.speech_above", &Int));
   1269   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.start_windback", &Int));
   1270   CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.utterance_allowance", &Int));
   1271 
   1272 
   1273   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.dimen", &Int));
   1274   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.whole_dimen", &Int));
   1275   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.mix_score_scale", &Float));
   1276   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.start", &Int));
   1277   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.chelt_imelda", &Bool));
   1278   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.vfrlimit", &Bool));
   1279   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.vfrthresh", &Bool));
   1280   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.mix_score_scale", &Float));
   1281   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.imelda_scale", &Float));
   1282   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.uni_score_scale", &Float));
   1283   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.uni_score_offset", &Float));
   1284   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.forget_speech", &Int));
   1285   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.forget_background", &Int));
   1286   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.rel_low", &Int));
   1287   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.rel_high", &Int));
   1288   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.gap_period", &Int));
   1289   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.click_period", &Int));
   1290   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.breath_period", &Int));
   1291   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.extend_annotation", &Int));
   1292   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.min_initial_quiet_frames", &Int));
   1293   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.min_annotation_frames", &Int));
   1294   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.min_initial_quiet_frames", &Int));
   1295   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.max_annotation_frames", &Int));
   1296   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.delete_leading_segments", &Int));
   1297   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.leading_segment_min_frames", &Int));
   1298   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.leading_segment_max_frames", &Int));
   1299   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.leading_segment_min_silence_gap_frames", &Int));
   1300   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.leading_segment_accept_if_not_found", &Int));
   1301   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.snr_holdoff", &Int));
   1302   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.min_acceptable_snr", &Int));
   1303   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.param", &Int));
   1304   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.beep_size", &Int));
   1305   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.beep_threshold", &Int));
   1306   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.partial_distance_dim", &Int));
   1307   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.partial_distance_threshold", &Int));
   1308   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.partial_distance_offset", &Int));
   1309   CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.global_model_means", &IntArrayList));
   1310 
   1311   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.NBest", &Int));
   1312   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.reject", &Int));
   1313   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.often", &Int));
   1314   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.partial_results", &Bool));
   1315   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.wordpen", &Int));
   1316   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.viterbi_prune_thresh", &Int));
   1317   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_hmm_tokens", &Int));
   1318   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_fsmnode_tokens", &Int));
   1319   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_word_tokens", &Int));
   1320   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_altword_tokens", &Int));
   1321   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.num_wordends_per_frame", &Int));
   1322   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_fsm_nodes", &Int));
   1323   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_fsm_arcs", &Int));
   1324   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_searches", &Int));
   1325   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.terminal_timeout", &Int));
   1326   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.optional_terminal_timeout", &Int));
   1327   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.non_terminal_timeout", &Int));
   1328   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.eou_threshold", &Int));
   1329   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_frames", &Int));
   1330   CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_model_states", &Int));
   1331   CHKLOG(rc, parameterList->put(parameterList, "thread.priority", &UInt16_t));
   1332   /* for G2P */
   1333   CHKLOG(rc, parameterList->put(parameterList, "G2P.Available", &Bool));
   1334   CHKLOG(rc, parameterList->put(parameterList, "G2P.Data", &PLChar));
   1335   CHKLOG(rc, parameterList->put(parameterList, "G2P.Dictionary", &PLChar));
   1336   /* Enable Get Waveform */
   1337   CHKLOG(rc, parameterList->put(parameterList, "enableGetWaveform", &Bool));
   1338 
   1339   rc = importKeyValueFile(self, filename, addParMapping, parameterList);
   1340   if (rc != ESR_SUCCESS)
   1341     goto CLEANUP;
   1342   CHKLOG(rc, HashMapDestroy(parameterList));
   1343   return ESR_SUCCESS;
   1344 CLEANUP:
   1345   HashMapDestroy(parameterList);
   1346   return rc;
   1347 }
   1348 
   1349 ESR_ReturnCode ESR_SessionTypeAddListenerImpl(ESR_SessionType* self, ESR_SessionTypeListenerPair* listener)
   1350 {
   1351   ESR_SessionTypeData* data = self->data;
   1352   ArrayList* listeners = data->listeners;
   1353   ESR_ReturnCode rc;
   1354 
   1355   CHKLOG(rc, listeners->add(listeners, listener));
   1356   return ESR_SUCCESS;
   1357 CLEANUP:
   1358   return rc;
   1359 }
   1360 
   1361 ESR_ReturnCode ESR_SessionTypeRemoveListenerImpl(ESR_SessionType* self, ESR_SessionTypeListenerPair* listener)
   1362 {
   1363   ESR_SessionTypeData* data = self->data;
   1364   ArrayList* listeners = data->listeners;
   1365   ESR_ReturnCode rc;
   1366 
   1367   CHKLOG(rc, listeners->remove(listeners, listener));
   1368   return ESR_SUCCESS;
   1369 CLEANUP:
   1370   return rc;
   1371 }
   1372 
   1373 ESR_ReturnCode ESR_SessionTypeDestroyImpl(ESR_SessionType* self)
   1374 {
   1375   ESR_SessionTypeData* data = self->data;
   1376   size_t hashSize;
   1377   ESR_SessionPair* pair;
   1378   ESR_ReturnCode rc;
   1379 
   1380   if (data != NULL)
   1381   {
   1382     if (data->value != NULL)
   1383     {
   1384       CHKLOG(rc, HashMapGetSize(data->value, &hashSize));
   1385       while (hashSize > 0)
   1386       {
   1387         CHKLOG(rc, HashMapGetValueAtIndex(data->value, 0, (void **)&pair));
   1388 
   1389         if (pair->value)
   1390         {
   1391           if (pair->type == TYPES_INTARRAYLIST)
   1392             CHKLOG(rc, IntArrayListDestroy((IntArrayList*) pair->value));
   1393           else
   1394             FREE(pair->value);
   1395         }
   1396         CHKLOG(rc, HashMapRemoveAtIndex(data->value, 0));
   1397         --hashSize;
   1398         FREE(pair);
   1399       }
   1400 
   1401       CHKLOG(rc, HashMapDestroy(data->value));
   1402       data->value = NULL;
   1403     }
   1404     if (data->listeners != NULL)
   1405     {
   1406       CHKLOG(rc, data->listeners->destroy(data->listeners));
   1407       data->listeners = NULL;
   1408     }
   1409     FREE(data);
   1410   }
   1411 
   1412   FREE(self);
   1413   return ESR_SUCCESS;
   1414 CLEANUP:
   1415   return rc;
   1416 }
   1417