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