Home | History | Annotate | Download | only in src
      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