/*---------------------------------------------------------------------------*
* 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;
}