1 /*---------------------------------------------------------------------------*
2 * LCHAR.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 "LCHAR.h"
21 #include "plog.h"
22 #include "pmemory.h"
23
24 #define MTAG NULL
25
lstrtrim(LCHAR * text)26 ESR_ReturnCode lstrtrim(LCHAR* text)
27 {
28 size_t beginning, ending, len;
29
30 len = LSTRLEN(text);
31
32 /* locating first non-whitespace character from beginning */
33 for (beginning = 0; beginning < len && LISSPACE(text[beginning]); ++beginning);
34 /* locating first non-whitespace character from end */
35 for (ending = len - 1; ending > beginning && LISSPACE(text[ending]); --ending);
36
37 if (beginning > 0 && beginning <= ending)
38 LMEMMOVE(text, text + beginning, ending - beginning + 1);
39 text[ending-beginning+1] = '\0';
40 return ESR_SUCCESS;
41 }
42
lstrinsert(const LCHAR * source,LCHAR * target,size_t offset,size_t * len)43 ESR_ReturnCode lstrinsert(const LCHAR* source, LCHAR* target, size_t offset, size_t* len)
44 {
45 ESR_ReturnCode rc;
46
47 if (source == NULL || target == NULL || len == NULL)
48 {
49 rc = ESR_INVALID_ARGUMENT;
50 PLogError(ESR_rc2str(rc));
51 goto CLEANUP;
52 }
53 if (LSTRLEN(source) + LSTRLEN(target) + 1 > *len)
54 {
55 *len = LSTRLEN(source) + LSTRLEN(target) + 1;
56 rc = ESR_BUFFER_OVERFLOW;
57 PLOG_DBG_TRACE((ESR_rc2str(rc)));
58 goto CLEANUP;
59 }
60 memmove(target + offset + LSTRLEN(source), target + offset, LSTRLEN(target + offset) + 1);
61 LSTRNCPY(target + offset, source, LSTRLEN(source));
62 return ESR_SUCCESS;
63 CLEANUP:
64 return rc;
65 }
66
lstrreplace(LCHAR * text,const LCHAR source,const LCHAR target)67 ESR_ReturnCode lstrreplace(LCHAR* text, const LCHAR source, const LCHAR target)
68 {
69 LCHAR* index;
70
71 while (ESR_TRUE)
72 {
73 index = LSTRCHR(text, source);
74 if (index == NULL)
75 break;
76 *index = target;
77 }
78 return ESR_SUCCESS;
79 }
80
lstrtoi(const LCHAR * text,int * result,int base)81 ESR_ReturnCode lstrtoi(const LCHAR* text, int* result, int base)
82 {
83 LCHAR* endPtr;
84
85 if (result == NULL)
86 return ESR_INVALID_ARGUMENT;
87 *result = LSTRTOL(text, &endPtr, base);
88 if (endPtr == text || (!LISSPACE(*endPtr) && *endPtr != L('\0')))
89 return ESR_INVALID_ARGUMENT;
90 return ESR_SUCCESS;
91 }
92
lstrtoui(const LCHAR * text,unsigned int * result,int base)93 ESR_ReturnCode lstrtoui(const LCHAR* text, unsigned int* result, int base)
94 {
95 LCHAR* endPtr;
96
97 if (result == NULL)
98 return ESR_INVALID_ARGUMENT;
99 *result = LSTRTOUL(text, &endPtr, base);
100 if (endPtr == text || (!LISSPACE(*endPtr) && *endPtr != L('\0')))
101 return ESR_INVALID_ARGUMENT;
102 return ESR_SUCCESS;
103 }
104
lstrtof(const LCHAR * text,float * result)105 ESR_ReturnCode lstrtof(const LCHAR* text, float* result)
106 {
107 LCHAR* endPtr;
108
109 if (result == NULL)
110 return ESR_INVALID_ARGUMENT;
111 *result = (float) LSTRTOD(text, &endPtr);
112 if (endPtr == text || (!LISSPACE(*endPtr) && *endPtr != L('\0')))
113 return ESR_INVALID_ARGUMENT;
114 return ESR_SUCCESS;
115 }
116
lstrtob(const LCHAR * text,ESR_BOOL * result)117 ESR_ReturnCode lstrtob(const LCHAR* text, ESR_BOOL* result)
118 {
119 ESR_ReturnCode rc = ESR_SUCCESS;
120 int compare;
121 unsigned int temp;
122
123 if (result == NULL)
124 return ESR_INVALID_ARGUMENT;
125 CHKLOG(rc, lstrcasecmp(text, L("true"), &compare));
126 if (compare == 0)
127 {
128 *result = ESR_TRUE;
129 return ESR_SUCCESS;
130 }
131 CHKLOG(rc, lstrcasecmp(text, L("yes"), &compare));
132 if (compare == 0)
133 {
134 *result = ESR_TRUE;
135 return ESR_SUCCESS;
136 }
137 CHKLOG(rc, lstrcasecmp(text, L("false"), &compare));
138 if (compare == 0)
139 {
140 *result = ESR_FALSE;
141 return ESR_SUCCESS;
142 }
143 CHKLOG(rc, lstrcasecmp(text, L("no"), &compare));
144 if (compare == 0)
145 {
146 *result = ESR_FALSE;
147 return ESR_SUCCESS;
148 }
149
150 /* Check for boolean expressed as an integer value */
151 CHK(rc, lstrtoui(text, &temp, 10));
152 *result = (temp != 0);
153 return ESR_SUCCESS;
154 CLEANUP:
155 return rc;
156 }
157
LCHARGetInt(LCHAR * text,int * value,LCHAR ** finalPosition)158 ESR_ReturnCode LCHARGetInt( LCHAR* text, int* value, LCHAR** finalPosition)
159 {
160 LCHAR *beg, *end;
161 LCHAR temp;
162 ESR_ReturnCode rc;
163
164 /* Skip whitespace */
165 for (beg = text; *beg != L('\0') && LISSPACE(*beg); ++beg);
166 if (beg == NULL)
167 return ESR_INVALID_ARGUMENT; /* invalid command syntax */
168 /* Find next whitespace */
169 for (end = beg; *end != L('\0') && !LISSPACE(*end); ++end);
170 if (end == NULL)
171 return ESR_INVALID_ARGUMENT; /* invalid command syntax */
172
173 temp = *end;
174 *end = L('\0');
175 rc = lstrtoi(beg, value, 10);
176 if (rc != ESR_SUCCESS)
177 {
178 *end = temp;
179 PLogError(ESR_rc2str(rc));
180 goto CLEANUP;
181 }
182 *end = temp;
183 if (finalPosition != NULL)
184 *finalPosition = end;
185 return ESR_SUCCESS;
186 CLEANUP:
187 return rc;
188 }
189
lstrlwr(LCHAR * string)190 ESR_ReturnCode lstrlwr(LCHAR* string)
191 {
192 if (string)
193 {
194 while (*string)
195 {
196 if (LISALPHA(*string))
197 *string = (LCHAR) LTOLOWER(*string);
198 ++string;
199 }
200 }
201 else
202 return ESR_INVALID_ARGUMENT;
203
204 return ESR_SUCCESS;
205 }
206
lstrupr(LCHAR * string)207 ESR_ReturnCode lstrupr(LCHAR* string)
208 {
209 if (string)
210 {
211 while (*string)
212 {
213 if (LISALPHA(*string))
214 *string = (LCHAR) LTOUPPER(*string);
215 ++string;
216 }
217 }
218 else
219 return ESR_INVALID_ARGUMENT;
220
221 return ESR_SUCCESS;
222 }
223
224 /* strcasecmp is not POSIX.4 API */
lstrcasecmp(const LCHAR * string1,const LCHAR * string2,int * result)225 ESR_ReturnCode lstrcasecmp(const LCHAR *string1, const LCHAR *string2, int *result)
226 {
227
228 if (!string1 || !string2)
229 return ESR_INVALID_ARGUMENT;
230
231 while (LTOUPPER(*string1) == LTOUPPER(*string2++))
232 {
233 if (!*string1++)
234 {
235 *result = 0;
236 return ESR_SUCCESS;
237 }
238 }
239
240 *result = LTOUPPER(*string1) - LTOUPPER(*--string2);
241 return ESR_SUCCESS;
242 }
243
244 /**
245 * This code is from MS SDK: C:\PROGRAM FILES\MICROSOFT SDK\src\crt\xtoa.c
246 * Buffer overflow checking is left up to the caller.
247 *
248 * @param value Number to be converted
249 * @param string String result
250 * @param radix Base of value; must be in the range 2 - 36
251 */
pxtoa(unsigned long val,LCHAR * buf,unsigned radix,int is_neg)252 static void pxtoa(unsigned long val, LCHAR *buf, unsigned radix, int is_neg)
253 {
254 LCHAR *p; /* pointer to traverse string */
255 LCHAR *firstdig; /* pointer to first digit */
256 LCHAR temp; /* temp char */
257 unsigned digval; /* value of digit */
258
259 p = buf;
260
261 if (is_neg)
262 {
263 /* negative, so output '-' and negate */
264 *p++ = '-';
265 val = (unsigned long)(-(long)val);
266 }
267
268 firstdig = p; /* save pointer to first digit */
269
270 do
271 {
272 digval = (unsigned)(val % radix);
273 val /= radix; /* get next digit */
274
275 /* convert to ascii and store */
276 if (digval > 9)
277 *p++ = (LCHAR)(digval - 10 + 'a'); /* a letter */
278 else
279 *p++ = (LCHAR)(digval + '0'); /* a digit */
280 }
281 while (val > 0);
282
283 /* We now have the digit of the number in the buffer, but in reverse
284 order. Thus we reverse them now. */
285
286 *p-- = '\0'; /* terminate string; p points to last digit */
287
288 do
289 {
290 temp = *p;
291 *p = *firstdig;
292 *firstdig = temp; /* swap *p and *firstdig */
293 --p;
294 ++firstdig; /* advance to next two digits */
295 }
296 while (firstdig < p); /* repeat until halfway */
297 }
298
299 /*
300 * Convert an integer to a string.
301 */
litostr(int value,LCHAR * string,size_t * len,int radix)302 ESR_ReturnCode litostr(int value, LCHAR *string, size_t *len, int radix)
303 {
304 size_t size;
305 /* pxtoa() is guaranteed not to overflow past 33 characters */
306 LCHAR buffer[33];
307
308 if (!string)
309 return ESR_INVALID_ARGUMENT;
310
311 if (radix == 10 && value < 0)
312 pxtoa((unsigned long) value, buffer, radix, 1);
313 else
314 pxtoa((unsigned long) value, buffer, radix, 0);
315
316 size = LSTRLEN(buffer);
317
318 if (size >= *len) /* + null-terminated character */
319 {
320 *len = size;
321 return ESR_BUFFER_OVERFLOW;
322 }
323 else
324 LSTRCPY(string, buffer);
325
326 return ESR_SUCCESS;
327 }
328
329
330 /* Convert an unsigned long integer to a string. */
lultostr(unsigned long value,LCHAR * string,size_t * len,int radix)331 ESR_ReturnCode lultostr(unsigned long value, LCHAR *string, size_t *len, int radix)
332 {
333 size_t size;
334 LCHAR buffer[33];
335
336 if (!string)
337 return ESR_INVALID_ARGUMENT;
338
339 pxtoa(value, buffer, radix, 0);
340
341 size = LSTRLEN(buffer);
342
343 if (size >= *len) /* + null-terminated character */
344 {
345 *len = size;
346 return ESR_BUFFER_OVERFLOW;
347 }
348 else
349 {
350 *len = size;
351 LSTRCPY(string, buffer);
352 }
353
354 return ESR_SUCCESS;
355 }
356