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 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