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
lstrtosize_t(const LCHAR * text,size_t * result,int base)105 ESR_ReturnCode lstrtosize_t(const LCHAR* text, size_t* result, int base)
106 {
107 LCHAR* endPtr;
108
109 if (result == NULL)
110 return ESR_INVALID_ARGUMENT;
111 *result = (size_t) LSTRTOUL(text, &endPtr, base);
112 if (endPtr == text || (!LISSPACE(*endPtr) && *endPtr != L('\0')))
113 return ESR_INVALID_ARGUMENT;
114 return ESR_SUCCESS;
115 }
116
lstrtof(const LCHAR * text,float * result)117 ESR_ReturnCode lstrtof(const LCHAR* text, float* result)
118 {
119 LCHAR* endPtr;
120
121 if (result == NULL)
122 return ESR_INVALID_ARGUMENT;
123 *result = (float) LSTRTOD(text, &endPtr);
124 if (endPtr == text || (!LISSPACE(*endPtr) && *endPtr != L('\0')))
125 return ESR_INVALID_ARGUMENT;
126 return ESR_SUCCESS;
127 }
128
lstrtob(const LCHAR * text,ESR_BOOL * result)129 ESR_ReturnCode lstrtob(const LCHAR* text, ESR_BOOL* result)
130 {
131 ESR_ReturnCode rc = ESR_SUCCESS;
132 int compare;
133 unsigned int temp;
134
135 if (result == NULL)
136 return ESR_INVALID_ARGUMENT;
137 CHKLOG(rc, lstrcasecmp(text, L("true"), &compare));
138 if (compare == 0)
139 {
140 *result = ESR_TRUE;
141 return ESR_SUCCESS;
142 }
143 CHKLOG(rc, lstrcasecmp(text, L("yes"), &compare));
144 if (compare == 0)
145 {
146 *result = ESR_TRUE;
147 return ESR_SUCCESS;
148 }
149 CHKLOG(rc, lstrcasecmp(text, L("false"), &compare));
150 if (compare == 0)
151 {
152 *result = ESR_FALSE;
153 return ESR_SUCCESS;
154 }
155 CHKLOG(rc, lstrcasecmp(text, L("no"), &compare));
156 if (compare == 0)
157 {
158 *result = ESR_FALSE;
159 return ESR_SUCCESS;
160 }
161
162 /* Check for boolean expressed as an integer value */
163 CHK(rc, lstrtoui(text, &temp, 10));
164 *result = (temp != 0);
165 return ESR_SUCCESS;
166 CLEANUP:
167 return rc;
168 }
169
LCHARGetInt(LCHAR * text,int * value,LCHAR ** finalPosition)170 ESR_ReturnCode LCHARGetInt( LCHAR* text, int* value, LCHAR** finalPosition)
171 {
172 LCHAR *beg, *end;
173 LCHAR temp;
174 ESR_ReturnCode rc;
175
176 /* Skip whitespace */
177 for (beg = text; *beg != L('\0') && LISSPACE(*beg); ++beg);
178 if (beg == NULL)
179 return ESR_INVALID_ARGUMENT; /* invalid command syntax */
180 /* Find next whitespace */
181 for (end = beg; *end != L('\0') && !LISSPACE(*end); ++end);
182 if (end == NULL)
183 return ESR_INVALID_ARGUMENT; /* invalid command syntax */
184
185 temp = *end;
186 *end = L('\0');
187 rc = lstrtoi(beg, value, 10);
188 if (rc != ESR_SUCCESS)
189 {
190 *end = temp;
191 PLogError(ESR_rc2str(rc));
192 goto CLEANUP;
193 }
194 *end = temp;
195 if (finalPosition != NULL)
196 *finalPosition = end;
197 return ESR_SUCCESS;
198 CLEANUP:
199 return rc;
200 }
201
lstrlwr(LCHAR * string)202 ESR_ReturnCode lstrlwr(LCHAR* string)
203 {
204 if (string)
205 {
206 while (*string)
207 {
208 if (LISALPHA(*string))
209 *string = (LCHAR) LTOLOWER(*string);
210 ++string;
211 }
212 }
213 else
214 return ESR_INVALID_ARGUMENT;
215
216 return ESR_SUCCESS;
217 }
218
lstrupr(LCHAR * string)219 ESR_ReturnCode lstrupr(LCHAR* string)
220 {
221 if (string)
222 {
223 while (*string)
224 {
225 if (LISALPHA(*string))
226 *string = (LCHAR) LTOUPPER(*string);
227 ++string;
228 }
229 }
230 else
231 return ESR_INVALID_ARGUMENT;
232
233 return ESR_SUCCESS;
234 }
235
236 /* strcasecmp is not POSIX.4 API */
lstrcasecmp(const LCHAR * string1,const LCHAR * string2,int * result)237 ESR_ReturnCode lstrcasecmp(const LCHAR *string1, const LCHAR *string2, int *result)
238 {
239
240 if (!string1 || !string2)
241 return ESR_INVALID_ARGUMENT;
242
243 while (LTOUPPER(*string1) == LTOUPPER(*string2++))
244 {
245 if (!*string1++)
246 {
247 *result = 0;
248 return ESR_SUCCESS;
249 }
250 }
251
252 *result = LTOUPPER(*string1) - LTOUPPER(*--string2);
253 return ESR_SUCCESS;
254 }
255
256 /**
257 * This code is from MS SDK: C:\PROGRAM FILES\MICROSOFT SDK\src\crt\xtoa.c
258 * Buffer overflow checking is left up to the caller.
259 *
260 * @param value Number to be converted
261 * @param string String result
262 * @param radix Base of value; must be in the range 2 - 36
263 */
pxtoa(unsigned long val,LCHAR * buf,unsigned radix,int is_neg)264 static void pxtoa(unsigned long val, LCHAR *buf, unsigned radix, int is_neg)
265 {
266 LCHAR *p; /* pointer to traverse string */
267 LCHAR *firstdig; /* pointer to first digit */
268 LCHAR temp; /* temp char */
269 unsigned digval; /* value of digit */
270
271 p = buf;
272
273 if (is_neg)
274 {
275 /* negative, so output '-' and negate */
276 *p++ = '-';
277 val = (unsigned long)(-(long)val);
278 }
279
280 firstdig = p; /* save pointer to first digit */
281
282 do
283 {
284 digval = (unsigned)(val % radix);
285 val /= radix; /* get next digit */
286
287 /* convert to ascii and store */
288 if (digval > 9)
289 *p++ = (LCHAR)(digval - 10 + 'a'); /* a letter */
290 else
291 *p++ = (LCHAR)(digval + '0'); /* a digit */
292 }
293 while (val > 0);
294
295 /* We now have the digit of the number in the buffer, but in reverse
296 order. Thus we reverse them now. */
297
298 *p-- = '\0'; /* terminate string; p points to last digit */
299
300 do
301 {
302 temp = *p;
303 *p = *firstdig;
304 *firstdig = temp; /* swap *p and *firstdig */
305 --p;
306 ++firstdig; /* advance to next two digits */
307 }
308 while (firstdig < p); /* repeat until halfway */
309 }
310
311 /*
312 * Convert an integer to a string.
313 */
litostr(int value,LCHAR * string,size_t * len,int radix)314 ESR_ReturnCode litostr(int value, LCHAR *string, size_t *len, int radix)
315 {
316 size_t size;
317 /* pxtoa() is guaranteed not to overflow past 33 characters */
318 LCHAR buffer[33];
319
320 if (!string)
321 return ESR_INVALID_ARGUMENT;
322
323 if (radix == 10 && value < 0)
324 pxtoa((unsigned long) value, buffer, radix, 1);
325 else
326 pxtoa((unsigned long) value, buffer, radix, 0);
327
328 size = LSTRLEN(buffer);
329
330 if (size >= *len) /* + null-terminated character */
331 {
332 *len = size;
333 return ESR_BUFFER_OVERFLOW;
334 }
335 else
336 LSTRCPY(string, buffer);
337
338 return ESR_SUCCESS;
339 }
340
341
342 /* Convert an unsigned long integer to a string. */
lultostr(unsigned long value,LCHAR * string,size_t * len,int radix)343 ESR_ReturnCode lultostr(unsigned long value, LCHAR *string, size_t *len, int radix)
344 {
345 size_t size;
346 LCHAR buffer[33];
347
348 if (!string)
349 return ESR_INVALID_ARGUMENT;
350
351 pxtoa(value, buffer, radix, 0);
352
353 size = LSTRLEN(buffer);
354
355 if (size >= *len) /* + null-terminated character */
356 {
357 *len = size;
358 return ESR_BUFFER_OVERFLOW;
359 }
360 else
361 {
362 *len = size;
363 LSTRCPY(string, buffer);
364 }
365
366 return ESR_SUCCESS;
367 }
368