| /*---------------------------------------------------------------------------* |
| * LCHAR.c * |
| * * |
| * Copyright 2007, 2008 Nuance Communciations, Inc. * |
| * * |
| * Licensed under the Apache License, Version 2.0 (the 'License'); * |
| * you may not use this file except in compliance with the License. * |
| * * |
| * You may obtain a copy of the License at * |
| * http://www.apache.org/licenses/LICENSE-2.0 * |
| * * |
| * Unless required by applicable law or agreed to in writing, software * |
| * distributed under the License is distributed on an 'AS IS' BASIS, * |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * |
| * See the License for the specific language governing permissions and * |
| * limitations under the License. * |
| * * |
| *---------------------------------------------------------------------------*/ |
| |
| #include "LCHAR.h" |
| #include "plog.h" |
| #include "pmemory.h" |
| |
| #define MTAG NULL |
| |
| ESR_ReturnCode lstrtrim(LCHAR* text) |
| { |
| size_t beginning, ending, len; |
| |
| len = LSTRLEN(text); |
| |
| /* locating first non-whitespace character from beginning */ |
| for (beginning = 0; beginning < len && LISSPACE(text[beginning]); ++beginning); |
| /* locating first non-whitespace character from end */ |
| for (ending = len - 1; ending > beginning && LISSPACE(text[ending]); --ending); |
| |
| if (beginning > 0 && beginning <= ending) |
| LMEMMOVE(text, text + beginning, ending - beginning + 1); |
| text[ending-beginning+1] = '\0'; |
| return ESR_SUCCESS; |
| } |
| |
| ESR_ReturnCode lstrinsert(const LCHAR* source, LCHAR* target, size_t offset, size_t* len) |
| { |
| ESR_ReturnCode rc; |
| |
| if (source == NULL || target == NULL || len == NULL) |
| { |
| rc = ESR_INVALID_ARGUMENT; |
| PLogError(ESR_rc2str(rc)); |
| goto CLEANUP; |
| } |
| if (LSTRLEN(source) + LSTRLEN(target) + 1 > *len) |
| { |
| *len = LSTRLEN(source) + LSTRLEN(target) + 1; |
| rc = ESR_BUFFER_OVERFLOW; |
| PLOG_DBG_TRACE((ESR_rc2str(rc))); |
| goto CLEANUP; |
| } |
| memmove(target + offset + LSTRLEN(source), target + offset, LSTRLEN(target + offset) + 1); |
| LSTRNCPY(target + offset, source, LSTRLEN(source)); |
| return ESR_SUCCESS; |
| CLEANUP: |
| return rc; |
| } |
| |
| ESR_ReturnCode lstrreplace(LCHAR* text, const LCHAR source, const LCHAR target) |
| { |
| LCHAR* index; |
| |
| while (ESR_TRUE) |
| { |
| index = LSTRCHR(text, source); |
| if (index == NULL) |
| break; |
| *index = target; |
| } |
| return ESR_SUCCESS; |
| } |
| |
| ESR_ReturnCode lstrtoi(const LCHAR* text, int* result, int base) |
| { |
| LCHAR* endPtr; |
| |
| if (result == NULL) |
| return ESR_INVALID_ARGUMENT; |
| *result = LSTRTOL(text, &endPtr, base); |
| if (endPtr == text || (!LISSPACE(*endPtr) && *endPtr != L('\0'))) |
| return ESR_INVALID_ARGUMENT; |
| return ESR_SUCCESS; |
| } |
| |
| ESR_ReturnCode lstrtoui(const LCHAR* text, unsigned int* result, int base) |
| { |
| LCHAR* endPtr; |
| |
| if (result == NULL) |
| return ESR_INVALID_ARGUMENT; |
| *result = LSTRTOUL(text, &endPtr, base); |
| if (endPtr == text || (!LISSPACE(*endPtr) && *endPtr != L('\0'))) |
| return ESR_INVALID_ARGUMENT; |
| return ESR_SUCCESS; |
| } |
| |
| ESR_ReturnCode lstrtof(const LCHAR* text, float* result) |
| { |
| LCHAR* endPtr; |
| |
| if (result == NULL) |
| return ESR_INVALID_ARGUMENT; |
| *result = (float) LSTRTOD(text, &endPtr); |
| if (endPtr == text || (!LISSPACE(*endPtr) && *endPtr != L('\0'))) |
| return ESR_INVALID_ARGUMENT; |
| return ESR_SUCCESS; |
| } |
| |
| ESR_ReturnCode lstrtob(const LCHAR* text, ESR_BOOL* result) |
| { |
| ESR_ReturnCode rc = ESR_SUCCESS; |
| int compare; |
| unsigned int temp; |
| |
| if (result == NULL) |
| return ESR_INVALID_ARGUMENT; |
| CHKLOG(rc, lstrcasecmp(text, L("true"), &compare)); |
| if (compare == 0) |
| { |
| *result = ESR_TRUE; |
| return ESR_SUCCESS; |
| } |
| CHKLOG(rc, lstrcasecmp(text, L("yes"), &compare)); |
| if (compare == 0) |
| { |
| *result = ESR_TRUE; |
| return ESR_SUCCESS; |
| } |
| CHKLOG(rc, lstrcasecmp(text, L("false"), &compare)); |
| if (compare == 0) |
| { |
| *result = ESR_FALSE; |
| return ESR_SUCCESS; |
| } |
| CHKLOG(rc, lstrcasecmp(text, L("no"), &compare)); |
| if (compare == 0) |
| { |
| *result = ESR_FALSE; |
| return ESR_SUCCESS; |
| } |
| |
| /* Check for boolean expressed as an integer value */ |
| CHK(rc, lstrtoui(text, &temp, 10)); |
| *result = (temp != 0); |
| return ESR_SUCCESS; |
| CLEANUP: |
| return rc; |
| } |
| |
| ESR_ReturnCode LCHARGetInt( LCHAR* text, int* value, LCHAR** finalPosition) |
| { |
| LCHAR *beg, *end; |
| LCHAR temp; |
| ESR_ReturnCode rc; |
| |
| /* Skip whitespace */ |
| for (beg = text; *beg != L('\0') && LISSPACE(*beg); ++beg); |
| if (beg == NULL) |
| return ESR_INVALID_ARGUMENT; /* invalid command syntax */ |
| /* Find next whitespace */ |
| for (end = beg; *end != L('\0') && !LISSPACE(*end); ++end); |
| if (end == NULL) |
| return ESR_INVALID_ARGUMENT; /* invalid command syntax */ |
| |
| temp = *end; |
| *end = L('\0'); |
| rc = lstrtoi(beg, value, 10); |
| if (rc != ESR_SUCCESS) |
| { |
| *end = temp; |
| PLogError(ESR_rc2str(rc)); |
| goto CLEANUP; |
| } |
| *end = temp; |
| if (finalPosition != NULL) |
| *finalPosition = end; |
| return ESR_SUCCESS; |
| CLEANUP: |
| return rc; |
| } |
| |
| ESR_ReturnCode lstrlwr(LCHAR* string) |
| { |
| if (string) |
| { |
| while (*string) |
| { |
| if (LISALPHA(*string)) |
| *string = (LCHAR) LTOLOWER(*string); |
| ++string; |
| } |
| } |
| else |
| return ESR_INVALID_ARGUMENT; |
| |
| return ESR_SUCCESS; |
| } |
| |
| ESR_ReturnCode lstrupr(LCHAR* string) |
| { |
| if (string) |
| { |
| while (*string) |
| { |
| if (LISALPHA(*string)) |
| *string = (LCHAR) LTOUPPER(*string); |
| ++string; |
| } |
| } |
| else |
| return ESR_INVALID_ARGUMENT; |
| |
| return ESR_SUCCESS; |
| } |
| |
| /* strcasecmp is not POSIX.4 API */ |
| ESR_ReturnCode lstrcasecmp(const LCHAR *string1, const LCHAR *string2, int *result) |
| { |
| |
| if (!string1 || !string2) |
| return ESR_INVALID_ARGUMENT; |
| |
| while (LTOUPPER(*string1) == LTOUPPER(*string2++)) |
| { |
| if (!*string1++) |
| { |
| *result = 0; |
| return ESR_SUCCESS; |
| } |
| } |
| |
| *result = LTOUPPER(*string1) - LTOUPPER(*--string2); |
| return ESR_SUCCESS; |
| } |
| |
| /** |
| * This code is from MS SDK: C:\PROGRAM FILES\MICROSOFT SDK\src\crt\xtoa.c |
| * Buffer overflow checking is left up to the caller. |
| * |
| * @param value Number to be converted |
| * @param string String result |
| * @param radix Base of value; must be in the range 2 - 36 |
| */ |
| static void pxtoa(unsigned long val, LCHAR *buf, unsigned radix, int is_neg) |
| { |
| LCHAR *p; /* pointer to traverse string */ |
| LCHAR *firstdig; /* pointer to first digit */ |
| LCHAR temp; /* temp char */ |
| unsigned digval; /* value of digit */ |
| |
| p = buf; |
| |
| if (is_neg) |
| { |
| /* negative, so output '-' and negate */ |
| *p++ = '-'; |
| val = (unsigned long)(-(long)val); |
| } |
| |
| firstdig = p; /* save pointer to first digit */ |
| |
| do |
| { |
| digval = (unsigned)(val % radix); |
| val /= radix; /* get next digit */ |
| |
| /* convert to ascii and store */ |
| if (digval > 9) |
| *p++ = (LCHAR)(digval - 10 + 'a'); /* a letter */ |
| else |
| *p++ = (LCHAR)(digval + '0'); /* a digit */ |
| } |
| while (val > 0); |
| |
| /* We now have the digit of the number in the buffer, but in reverse |
| order. Thus we reverse them now. */ |
| |
| *p-- = '\0'; /* terminate string; p points to last digit */ |
| |
| do |
| { |
| temp = *p; |
| *p = *firstdig; |
| *firstdig = temp; /* swap *p and *firstdig */ |
| --p; |
| ++firstdig; /* advance to next two digits */ |
| } |
| while (firstdig < p); /* repeat until halfway */ |
| } |
| |
| /* |
| * Convert an integer to a string. |
| */ |
| ESR_ReturnCode litostr(int value, LCHAR *string, size_t *len, int radix) |
| { |
| size_t size; |
| /* pxtoa() is guaranteed not to overflow past 33 characters */ |
| LCHAR buffer[33]; |
| |
| if (!string) |
| return ESR_INVALID_ARGUMENT; |
| |
| if (radix == 10 && value < 0) |
| pxtoa((unsigned long) value, buffer, radix, 1); |
| else |
| pxtoa((unsigned long) value, buffer, radix, 0); |
| |
| size = LSTRLEN(buffer); |
| |
| if (size >= *len) /* + null-terminated character */ |
| { |
| *len = size; |
| return ESR_BUFFER_OVERFLOW; |
| } |
| else |
| LSTRCPY(string, buffer); |
| |
| return ESR_SUCCESS; |
| } |
| |
| |
| /* Convert an unsigned long integer to a string. */ |
| ESR_ReturnCode lultostr(unsigned long value, LCHAR *string, size_t *len, int radix) |
| { |
| size_t size; |
| LCHAR buffer[33]; |
| |
| if (!string) |
| return ESR_INVALID_ARGUMENT; |
| |
| pxtoa(value, buffer, radix, 0); |
| |
| size = LSTRLEN(buffer); |
| |
| if (size >= *len) /* + null-terminated character */ |
| { |
| *len = size; |
| return ESR_BUFFER_OVERFLOW; |
| } |
| else |
| { |
| *len = size; |
| LSTRCPY(string, buffer); |
| } |
| |
| return ESR_SUCCESS; |
| } |