1
2/*---------------------------------------------------------------------------*
3 *  NametagImpl.c  *
4 *                                                                           *
5 *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
6 *                                                                           *
7 *  Licensed under the Apache License, Version 2.0 (the 'License');          *
8 *  you may not use this file except in compliance with the License.         *
9 *                                                                           *
10 *  You may obtain a copy of the License at                                  *
11 *      http://www.apache.org/licenses/LICENSE-2.0                           *
12 *                                                                           *
13 *  Unless required by applicable law or agreed to in writing, software      *
14 *  distributed under the License is distributed on an 'AS IS' BASIS,        *
15 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
16 *  See the License for the specific language governing permissions and      *
17 *  limitations under the License.                                           *
18 *                                                                           *
19 *---------------------------------------------------------------------------*/
20
21#include "SR_Nametag.h"
22#include "SR_NametagImpl.h"
23#include "SR_RecognizerImpl.h"
24#include "SR_VocabularyImpl.h"
25#include "plog.h"
26#include "pmemory.h"
27
28#define MTAG NULL
29#define MAX_STRING_LEN P_PATH_MAX
30
31ESR_ReturnCode SR_NametagCreate(const SR_RecognizerResult* result, const LCHAR* id, SR_Nametag** self)
32{
33  ESR_Locale locale;
34  ESR_ReturnCode rc;
35  size_t len;
36  LCHAR transcription[MAX_STRING_LEN];
37
38  if (self == NULL)
39  {
40    PLogError(L("ESR_INVALID_ARGUMENT"));
41    return ESR_INVALID_ARGUMENT;
42  }
43
44  rc = result->getSize(result, &len);
45  if (rc != ESR_SUCCESS)
46  {
47    PLogError(ESR_rc2str(rc));
48    goto CLEANUP;
49  }
50  if (len < 1)
51  {
52    PLogError(L("ESR_INVALID_ARGUMENT (recognition result nbest-list size=0)"));
53    rc = ESR_INVALID_ARGUMENT;
54    goto CLEANUP;
55  }
56  rc = result->getLocale(result, &locale);
57
58  len = MAX_STRING_LEN;
59
60  rc = result->getValue(result, 0, L("meaning"), transcription, &len);
61
62  if (rc != ESR_SUCCESS && rc != ESR_BUFFER_OVERFLOW)
63  {
64    PLogError(ESR_rc2str(rc));
65    goto CLEANUP;
66  }
67
68#if USE_HMM_BASED_ENROLLMENT /* srec_context.h */
69  len = LSTRLEN(transcription)+1;
70  rc = SR_NametagCreateFromValue(id, transcription, (int)len, self);
71  if(rc ) goto CLEANUP;
72#else
73
74  if(1) {
75    LCHAR short_pron[MAX_STRING_LEN], *short_pron_ptr;
76    LCHAR* long_pron = transcription;
77    LCHAR* multichar;
78    LCHAR* p;
79    LCHAR singlechar[2];
80
81    *short_pron = 0;
82    short_pron_ptr = short_pron;
83    len = LSTRLEN(L("ph_"));
84    for (multichar = strtok(long_pron, L(" \t\n\r")); multichar; multichar = strtok(NULL, L(" \t\n\r")))
85      {
86	p = multichar;
87	if (LSTRNCMP(p, L("ph_"), len) != 0)
88	  {
89	    PLogError(L("Expecting 'ph_' prefix, got=%s"), p);
90	    rc = ESR_INVALID_STATE;
91	    goto CLEANUP;
92	  }
93	p += len;
94	multichar = p;
95	while (*p)
96	  {
97	    if (isdigit(*p))
98	      {
99		*p = L('\0');
100		break;
101	      }
102	    ++p;
103	  }
104	if ((rc = SR_Vocabulary_etiinf_conv_from_multichar(locale, multichar, singlechar)) != ESR_SUCCESS)
105	  {
106	    PLogError(L("Could not convert long to short pron (input=%s, locale=%s)"), multichar, ESR_locale2str(locale));
107	    goto CLEANUP;
108	  }
109	singlechar[1] = 0;
110	if((short_pron_ptr - short_pron + 3) >= MAX_STRING_LEN) {
111	  PLogError(L("Chopping too long pron in SR_NametagCreate()\n"));
112	  break; // just cut if off
113	}
114	*short_pron_ptr++ = *singlechar;
115      }
116    *short_pron_ptr++ = 0; // null-term
117    *short_pron_ptr++ = 0; // double-null-term!
118
119    /* +2 = +1 for null, +1 for double-null */
120    rc = SR_NametagCreateFromValue(id, short_pron, (short_pron_ptr-short_pron), self);
121    if(rc ) goto CLEANUP;
122  }
123#endif
124
125  return ESR_SUCCESS;
126CLEANUP:
127  return rc;
128}
129
130ESR_ReturnCode SR_NametagCreateFromValue(const LCHAR* id, const char* value, size_t len, SR_Nametag** self)
131{
132  SR_NametagImpl* impl;
133  ESR_ReturnCode rc;
134
135  passert(self != NULL);
136  impl = NEW(SR_NametagImpl, MTAG);
137  if (impl == NULL)
138  {
139    PLogError(L("ESR_OUT_OF_MEMORY"));
140    return ESR_OUT_OF_MEMORY;
141  }
142
143  impl->Interface.setID = &SR_Nametag_SetID;
144  impl->Interface.getID = &SR_Nametag_GetID;
145  impl->Interface.getValue = &SR_Nametag_GetValue;
146  impl->Interface.clone = &SR_Nametag_Clone;
147  impl->Interface.destroy = &SR_Nametag_Destroy;
148  impl->id = NULL;
149  impl->value = NULL;
150  impl->value = (LCHAR*) MALLOC(sizeof(LCHAR) * (len), MTAG);
151
152  if (impl->value == NULL)
153  {
154    rc = ESR_OUT_OF_MEMORY;
155    PLogError(ESR_rc2str(rc));
156    goto CLEANUP;
157  }
158  impl->value_len = len;
159  // make sure we have a double-null term
160  memcpy( (void*)impl->value, value, len);
161  LSTRNCPY(impl->value, value, len);
162
163  rc = SR_NametagSetID(&impl->Interface, id);
164  if (rc != ESR_SUCCESS)
165  {
166    PLogError(ESR_rc2str(rc));
167    goto CLEANUP;
168  }
169
170  *self = (SR_Nametag*) impl;
171  return ESR_SUCCESS;
172CLEANUP:
173  impl->Interface.destroy(&impl->Interface);
174  return rc;
175}
176
177ESR_ReturnCode SR_Nametag_Destroy(SR_Nametag* self)
178{
179  SR_NametagImpl* impl = (SR_NametagImpl*) self;
180  if (impl->value != NULL)
181  {
182    FREE(impl->value);
183    impl->value = NULL;
184  }
185  if (impl->id != NULL)
186  {
187    FREE(impl->id);
188    impl->id = NULL;
189  }
190  FREE(impl);
191  return ESR_SUCCESS;
192}
193
194ESR_ReturnCode SR_Nametag_GetID(const SR_Nametag* self, LCHAR** id)
195{
196  SR_NametagImpl* impl = (SR_NametagImpl*) self;
197
198  *id = impl->id;
199  return ESR_SUCCESS;
200}
201
202ESR_ReturnCode SR_Nametag_GetValue(const SR_Nametag* self, const char** pvalue, size_t* plen)
203{
204  SR_NametagImpl* impl = (SR_NametagImpl*) self;
205
206  *pvalue = (const char*)impl->value;
207  if(!impl->value)
208      return ESR_NO_MATCH_ERROR;
209  *plen = impl->value_len;
210  return ESR_SUCCESS;
211}
212
213ESR_ReturnCode SR_Nametag_SetID(SR_Nametag* self, const LCHAR* id)
214{
215  SR_NametagImpl* impl = (SR_NametagImpl*) self;
216  ESR_ReturnCode rc;
217
218  FREE(impl->id);
219  impl->id = (LCHAR*) MALLOC(sizeof(LCHAR) * (LSTRLEN(id) + 1), MTAG);
220  if (impl->id == NULL)
221  {
222    rc = ESR_OUT_OF_MEMORY;
223    PLogError(ESR_rc2str(rc));
224    goto CLEANUP;
225  }
226  LSTRCPY(impl->id, id);
227
228  return ESR_SUCCESS;
229CLEANUP:
230  return rc;
231}
232
233ESR_ReturnCode SR_Nametag_Clone(const SR_Nametag* self, SR_Nametag** result)
234{
235  SR_NametagImpl* impl = (SR_NametagImpl*) self;
236  ESR_ReturnCode rc;
237
238  CHKLOG(rc, SR_NametagCreateFromValue(impl->id, impl->value, LSTRLEN(impl->value)+1, result));
239  return ESR_SUCCESS;
240CLEANUP:
241  return rc;
242}
243