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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 */ 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. */ 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