Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 /**
     17  ************************************************************************
     18  * @file         M4DPAK_CharStar.c
     19  * @ingroup
     20   * @brief        definition of the Char Star set of functions.
     21  * @note         This file defines the Char Star set of functions.
     22  *
     23  ************************************************************************
     24 */
     25 
     26 
     27 #include "M4OSA_CharStar.h"
     28 #include "M4OSA_Memory.h"
     29 #include "M4OSA_Debug.h"
     30 
     31 /* WARNING: Specific Android */
     32 #include <stdio.h>
     33 #include <stdlib.h>
     34 #include <stdarg.h>
     35 #include <string.h>
     36 #include <errno.h>
     37 
     38 
     39 /**
     40  ************************************************************************
     41  * @brief      This function mimics the functionality of the libc's strncpy().
     42  * @note       It copies exactly len2Copy characters from pStrIn to pStrOut,
     43  *             truncating  pStrIn or adding null characters to pStrOut if
     44  *             necessary.
     45  *             - If len2Copy is less than or equal to the length of pStrIn,
     46  *               a null character is appended automatically to the copied
     47  *               string.
     48  *             - If len2Copy is greater than the length of pStrIn, pStrOut is
     49  *               padded with null characters up to length len2Copy.
     50  *             - pStrOut and pStrIn MUST NOT OVERLAP (this is NOT CHECKED).
     51  * @param      pStrOut: (OUT) Destination character string.
     52  * @param      pStrIn: (IN) Source character string.
     53  * @param      len2Copy: (IN) Maximum number of characters from pStrIn to copy.
     54  * @return     M4NO_ERROR: there is no error.
     55  * @return     M4ERR_PARAMETER: pStrIn or pStrOut is M4OSA_NULL.
     56   ************************************************************************
     57 */
     58 M4OSA_ERR M4OSA_chrNCopy(M4OSA_Char* pStrOut, M4OSA_Char   *pStrIn, M4OSA_UInt32 len2Copy)
     59 {
     60     M4OSA_TRACE1_3("M4OSA_chrNCopy\t(M4OSA_Char* %x,M4OSA_Char* %x,M4OSA_UInt32 %ld)",
     61         pStrOut,pStrIn,len2Copy);
     62     M4OSA_DEBUG_IF2((M4OSA_NULL == pStrOut),M4ERR_PARAMETER,
     63                             "M4OSA_chrNCopy:\tpStrOut is M4OSA_NULL");
     64     M4OSA_DEBUG_IF2((M4OSA_NULL == pStrIn),M4ERR_PARAMETER,
     65                             "M4OSA_chrNCopy:\tpStrIn is M4OSA_NULL");
     66 
     67     strncpy((char *)pStrOut, (const char *)pStrIn, (size_t)len2Copy);
     68     if(len2Copy <= (M4OSA_UInt32)strlen((const char *)pStrIn))
     69     {
     70         pStrOut[len2Copy] = '\0';
     71     }
     72 
     73     return M4NO_ERROR;
     74 }
     75 
     76 /**
     77  ************************************************************************
     78   * @brief      This function returns the boolean comparison of pStrIn1 and pStrIn2.
     79  * @note       The value returned in result is M4OSA_TRUE if the string
     80  *             pointed to by pStrIn1 is strictly identical to the string pointed
     81  *             to by pStrIn2, and M4OSA_FALSE otherwise.
     82  * @param      pStrIn1: (IN) First character string.
     83  * @param      pStrIn2: (IN) Second character string.
     84  * @param      cmpResult: (OUT) Comparison result.
     85  * @return     M4NO_ERROR: there is no error.
     86  * @return     M4ERR_PARAMETER: pStrIn1 pStrIn2 or cmpResult is M4OSA_NULL.
     87   ************************************************************************
     88 */
     89 M4OSA_ERR M4OSA_chrAreIdentical(M4OSA_Char* pStrIn1, M4OSA_Char* pStrIn2,
     90                                                             M4OSA_Bool* pResult)
     91 {
     92     M4OSA_UInt32 i32,len32;
     93     M4OSA_TRACE1_3("M4OSA_chrAreIdentical\t(M4OSA_Char* %x,M4OSA_Char* %x,"
     94         "M4OSA_Int32* %x)",pStrIn1,pStrIn2,pResult);
     95     M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn1, M4ERR_PARAMETER,
     96                                "M4OSA_chrAreIdentical:\tpStrIn1 is M4OSA_NULL");
     97     M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn2, M4ERR_PARAMETER,
     98                                "M4OSA_chrAreIdentical:\tpStrIn2 is M4OSA_NULL");
     99     M4OSA_DEBUG_IF2(M4OSA_NULL == pResult, M4ERR_PARAMETER,
    100                                "M4OSA_chrAreIdentical:\tpResult is M4OSA_NULL");
    101 
    102     len32 = (M4OSA_UInt32)strlen((const char *)pStrIn1);
    103     if(len32 != (M4OSA_UInt32)strlen((const char *)pStrIn2))
    104     {
    105         *pResult = M4OSA_FALSE;
    106         return M4NO_ERROR;
    107     }
    108 
    109     for(i32=0;i32<len32;i32++)
    110     {
    111         if(pStrIn1[i32] != pStrIn2[i32])
    112         {
    113             *pResult = M4OSA_FALSE;
    114             return M4NO_ERROR;
    115         }
    116     }
    117 
    118     *pResult = M4OSA_TRUE;
    119 
    120     return M4NO_ERROR;
    121 }
    122 
    123 
    124 /**
    125  ************************************************************************
    126  * @brief      This function gets a M4OSA_UInt32 from string.
    127  * @note       This function converts the first set of non-whitespace
    128  *             characters of pStrIn to a M4OSA_UInt32 value pVal, assuming a
    129  *             representation in base provided by the parameter base. pStrOut is
    130  *             set to the first character of the string following the last
    131  *             character of the number that has been converted.
    132  *             - in case of a failure during the conversion, pStrOut is not
    133  *               updated, and pVal is set to null.
    134  *             - in case of negative number, pStrOut is not updated, and pVal is
    135  *               set to null.
    136  *             - in case of numerical overflow, pVal is set to M4OSA_UINT32_MAX.
    137  *             - if pStrOut is not to be used, it can be set to M4OSA_NULL.
    138  * @param      pStrIn: (IN) Character string.
    139  * @param      pVal: (OUT) read value.
    140  * @param      pStrOut: (OUT) Output character string.
    141  * @param      base: (IN) Base of the character string representation.
    142  * @return     M4NO_ERROR: there is no error.
    143  * @return     M4ERR_PARAMETER: pStrIn or pVal is M4OSA_NULL.
    144  * @return     M4ERR_CHR_CONV_FAILED: conversion failure.
    145  * @return     M4WAR_CHR_NUM_RANGE: the character string represents a number
    146  *             greater than M4OSA_UINT32_MAX.
    147  * @return     M4WAR_CHR_NEGATIVE: the character string represents a negative
    148  *             number.
    149  ************************************************************************
    150 */
    151 M4OSA_ERR M4OSA_chrGetUInt32(M4OSA_Char*    pStrIn,
    152                              M4OSA_UInt32*    pVal,
    153                              M4OSA_Char**    pStrOut,
    154                              M4OSA_chrNumBase base)
    155 {
    156     M4OSA_UInt32 ul;
    157     char*        pTemp;
    158 
    159     M4OSA_TRACE1_4("M4OSA_chrGetUInt32\t(M4OSA_Char* %x, M4OSA_UInt32* %x"
    160         "M4OSA_Char** %x,M4OSA_chrNumBase %d)",pStrIn,pVal,pStrOut,base);
    161     M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn, M4ERR_PARAMETER,
    162                                    "M4OSA_chrGetUInt32:\tpStrIn is M4OSA_NULL");
    163     M4OSA_DEBUG_IF2(M4OSA_NULL == pVal, M4ERR_PARAMETER,
    164                                      "M4OSA_chrGetUInt32:\tpVal is M4OSA_NULL");
    165 
    166     errno = 0;
    167     switch(base)
    168     {
    169     case M4OSA_kchrDec:
    170         ul = strtoul((const char *)pStrIn, &pTemp, 10);
    171         break;
    172     case M4OSA_kchrHexa:
    173         ul = strtoul((const char *)pStrIn, &pTemp,16);
    174         break;
    175     case M4OSA_kchrOct:
    176         ul = strtoul((const char *)pStrIn, &pTemp,8);
    177         break;
    178     default:
    179         return M4ERR_PARAMETER;
    180     }
    181 
    182     /* has conversion failed ? */
    183     if((M4OSA_Char*)pTemp == pStrIn)
    184     {
    185         *pVal = 0;
    186         return M4ERR_CHR_CONV_FAILED;
    187     }
    188 
    189     /* was the number negative ? */
    190     if(*(pStrIn+strspn((const char *)pStrIn," \t")) == '-')
    191     {
    192         *pVal = 0;
    193         return M4WAR_CHR_NEGATIVE;
    194     }
    195 
    196     /* has an overflow occured ? */
    197     if(errno == ERANGE)
    198     {
    199         *pVal = M4OSA_UINT32_MAX;
    200         if(M4OSA_NULL != pStrOut)
    201         {
    202             *pStrOut = (M4OSA_Char*)pTemp;
    203         }
    204         return M4WAR_CHR_NUM_RANGE;
    205     }
    206 
    207     /* nominal case */
    208     *pVal = (M4OSA_UInt32)ul;
    209     if(M4OSA_NULL != pStrOut)
    210     {
    211         *pStrOut = (M4OSA_Char*)pTemp;
    212     }
    213 
    214     return M4NO_ERROR;
    215 }
    216 
    217 /**
    218  ************************************************************************
    219  * @brief      This function gets a M4OSA_UInt16 from string.
    220  * @note       This function converts the first set of non-whitespace
    221  *             characters of pStrIn to a M4OSA_UInt16 value pVal, assuming a
    222  *             representation in base provided by the parameter base. pStrOut is
    223  *             set to the first character of the string following the last
    224  *             character of the number that has been converted.
    225  *             - in case of a failure during the conversion, pStrOut is not
    226  *               updated, and pVal is set to null.
    227  *             - in case of negative number, pStrOut is not updated, and pVal is
    228  *               set to null.
    229  *             - in case of numerical overflow, pVal is set to M4OSA_UINT16_MAX.
    230  *             - if pStrOut is not to be used, it can be set to M4OSA_NULL.
    231  * @param      pStrIn: (IN) Character string.
    232  * @param      pVal: (OUT) read value.
    233  * @param      pStrOut: (OUT) Output character string.
    234  * @param      base: (IN) Base of the character string representation.
    235  * @return     M4NO_ERROR: there is no error.
    236  * @return     M4ERR_PARAMETER: pStrIn or pVal is M4OSA_NULL.
    237  * @return     M4ERR_CHR_CONV_FAILED: conversion failure.
    238  * @return     M4WAR_CHR_NUM_RANGE: the character string represents a number
    239  *             greater than M4OSA_UINT16_MAX.
    240  * @return     M4WAR_CHR_NEGATIVE: the character string represents a negative
    241  *             number.
    242  ************************************************************************
    243 */
    244 M4OSA_ERR M4OSA_chrGetUInt16 (M4OSA_Char* pStrIn, M4OSA_UInt16 *pVal,
    245                               M4OSA_Char** pStrOut, M4OSA_chrNumBase base)
    246 {
    247     M4OSA_UInt32 ul;
    248     char*        pTemp;
    249 
    250     M4OSA_TRACE1_4("M4OSA_chrGetUInt16\t(M4OSA_Char* %x, M4OSA_UInt16* %x"
    251         "M4OSA_Char** %x,M4OSA_chrNumBase %d)",pStrIn,pVal,pStrOut,base);
    252     M4OSA_DEBUG_IF2(M4OSA_NULL == pStrIn,M4ERR_PARAMETER,
    253                                    "M4OSA_chrGetUInt16:\tpStrIn is M4OSA_NULL");
    254     M4OSA_DEBUG_IF2(M4OSA_NULL == pVal, M4ERR_PARAMETER,
    255                                      "M4OSA_chrGetUInt16:\tpVal is M4OSA_NULL");
    256 
    257     switch(base)
    258     {
    259     case M4OSA_kchrDec:
    260         ul = strtoul((const char *)pStrIn, &pTemp,10);
    261         break;
    262     case M4OSA_kchrHexa:
    263         ul = strtoul((const char *)pStrIn, &pTemp,16);
    264         break;
    265     case M4OSA_kchrOct:
    266         ul = strtoul((const char *)pStrIn, &pTemp,8);
    267         break;
    268     default:
    269         return M4ERR_PARAMETER;
    270     }
    271 
    272     /* has conversion failed ? */
    273     if((M4OSA_Char*)pTemp == pStrIn)
    274     {
    275         *pVal = 0;
    276         return M4ERR_CHR_CONV_FAILED;
    277     }
    278 
    279     /* was the number negative ? */
    280     if(*(pStrIn+strspn((const char *)pStrIn," \t")) == '-')
    281     {
    282         *pVal = 0;
    283         return M4WAR_CHR_NEGATIVE;
    284     }
    285 
    286     /* has an overflow occured ? */
    287     if(ul>M4OSA_UINT16_MAX)
    288     {
    289         *pVal = M4OSA_UINT16_MAX;
    290         if(M4OSA_NULL != pStrOut)
    291         {
    292             *pStrOut = (M4OSA_Char*)pTemp;
    293         }
    294         return M4WAR_CHR_NUM_RANGE;
    295     }
    296 
    297     /* nominal case */
    298     *pVal = (M4OSA_UInt16)ul;
    299     if(M4OSA_NULL != pStrOut)
    300     {
    301         *pStrOut = (M4OSA_Char*)pTemp;
    302     }
    303     return M4NO_ERROR;
    304 }
    305 
    306 M4OSA_ERR M4OSA_chrSPrintf(M4OSA_Char  *pStrOut, M4OSA_UInt32 strOutMaxLen,
    307                            M4OSA_Char   *format, ...)
    308 {
    309     va_list       marker;
    310     M4OSA_Char   *pTemp;
    311     M4OSA_Char   *percentPointer;
    312     M4OSA_Char   *newFormat;
    313     M4OSA_Int32  newFormatLength=0;
    314     M4OSA_UInt32  count_ll = 0;
    315     M4OSA_UInt32  count_tm = 0;
    316     M4OSA_UInt32  count_aa = 0;
    317     M4OSA_UInt32  count;
    318     M4OSA_UInt32  nbChar;
    319     M4OSA_Int32     err;
    320     M4OSA_Char flagChar[]             = "'-+ #0";
    321     M4OSA_Char widthOrPrecisionChar[] = "*0123456789";
    322     M4OSA_Char otherPrefixChar[]      = "hlL";
    323     M4OSA_Char conversionChar[]       = "diouxXnfeEgGcCsSp%";
    324 
    325     M4OSA_TRACE1_3("M4OSA_chrSPrintf\t(M4OSA_Char* %x, M4OSA_UInt32 %ld"
    326         "M4OSA_Char* %x)",pStrOut,strOutMaxLen,format);
    327     M4OSA_DEBUG_IF2(M4OSA_NULL == pStrOut, M4ERR_PARAMETER,
    328                                     "M4OSA_chrSPrintf:\tpStrOut is M4OSA_NULL");
    329     M4OSA_DEBUG_IF2(M4OSA_NULL == format, M4ERR_PARAMETER,
    330                                      "M4OSA_chrSPrintf:\tformat is M4OSA_NULL");
    331 
    332     va_start(marker,format);
    333 
    334     /* count the number of %[flags][width][.precision]ll[conversion] */
    335     pTemp = format;
    336     while(*pTemp)
    337     {
    338         percentPointer = (M4OSA_Char *)strchr((const char *)pTemp,'%'); /* get the next percent character */
    339         if(!percentPointer)
    340             break;                            /* "This is the End", (c) J. Morrisson */
    341         pTemp = percentPointer+1;           /* span it */
    342         if(!*pTemp)
    343             break;                            /* "This is the End", (c) J. Morrisson */
    344         pTemp += strspn((const char *)pTemp,(const char *)flagChar);    /* span the optional flags */
    345         if(!*pTemp)
    346             break;                            /* "This is the End", (c) J. Morrisson */
    347         pTemp += strspn((const char *)pTemp,(const char *)widthOrPrecisionChar); /* span the optional width */
    348         if(!*pTemp)
    349             break;                            /* "This is the End", (c) J. Morrisson */
    350         if(*pTemp=='.')
    351         {
    352             pTemp++;
    353             pTemp += strspn((const char *)pTemp, (const char *)widthOrPrecisionChar); /* span the optional precision */
    354         }
    355         if(!*pTemp)
    356             break;                            /* "This is the End", (c) J. Morrisson */
    357         if(strlen((const char *)pTemp)>=2)
    358         {
    359             if(!strncmp((const char *)pTemp,"ll",2))
    360             {
    361                 count_ll++;                 /* I got ONE */
    362                 pTemp +=2;                  /* span the "ll" prefix */
    363             }
    364             else if(!strncmp((const char *)pTemp,"tm",2))
    365             {
    366                 count_tm++;
    367                 pTemp +=2;
    368             }
    369             else if(!strncmp((const char *)pTemp,"aa",2))
    370             {
    371                 count_aa++;
    372                 pTemp +=2;
    373             }
    374         }
    375         pTemp += strspn((const char *)pTemp, (const char *)otherPrefixChar); /* span the other optional prefix */
    376         if(!*pTemp)
    377             break;                        /* "This is the End", (c) J. Morrisson */
    378         pTemp += strspn((const char *)pTemp, (const char *)conversionChar);
    379         if(!*pTemp)
    380             break;                        /* "This is the End", (c) J. Morrisson */
    381     }
    382 
    383     count = count_ll + count_tm + count_aa;
    384 
    385     if(!count)
    386     {
    387         err= vsnprintf((char *)pStrOut, (size_t)strOutMaxLen + 1, (const char *)format, marker);
    388         va_end(marker);
    389         if ((err<0) || ((M4OSA_UInt32)err>strOutMaxLen))
    390         {
    391             pStrOut[strOutMaxLen] = '\0';
    392             return M4ERR_CHR_STR_OVERFLOW;
    393         }
    394         else
    395         {
    396             return M4NO_ERROR;
    397         }
    398     }
    399 
    400 
    401     newFormatLength = strlen((const char *)format) + 1;
    402 
    403     newFormatLength -= (count_ll+count_tm+count_aa);
    404 
    405     newFormat =(M4OSA_Char*)M4OSA_32bitAlignedMalloc(newFormatLength,
    406         M4OSA_CHARSTAR,(M4OSA_Char*)"M4OSA_chrPrintf: newFormat");
    407     if(M4OSA_NULL == newFormat)
    408         return M4ERR_ALLOC;
    409     newFormat[newFormatLength-1] = '\0';
    410     pTemp = newFormat;
    411 
    412     /* copy format to newFormat, replacing %[flags][width][.precision]ll[conversion]
    413      * by %[flags][width][.precision]I64[conversion] */
    414     while(*format)
    415     {
    416         nbChar = strcspn((const char *)format, "%");
    417         if(nbChar)
    418         {
    419             strncpy((char *)pTemp, (const char *)format, nbChar);      /* copy characters before the % character */
    420             format +=nbChar;
    421             pTemp   +=nbChar;
    422         }
    423         if(!*format) break;
    424         *pTemp++ = *format++;                 /* copy the % character */
    425         nbChar = strspn((const char *)format, (const char *)flagChar);
    426         if(nbChar)
    427         {
    428             strncpy((char *)pTemp, (const char *)format, nbChar);      /* copy the flag characters */
    429             format +=nbChar;
    430             pTemp   +=nbChar;
    431         }
    432         if(!*format) break;
    433         nbChar = strspn((const char *)format, (const char *)widthOrPrecisionChar);
    434         if(nbChar)
    435         {
    436             strncpy((char *)pTemp, (const char *)format, nbChar);      /* copy the width characters */
    437             format +=nbChar;
    438             pTemp   +=nbChar;
    439         }
    440         if(!*format) break;
    441         if(*format=='.')
    442         {
    443             *pTemp++ = *format++;              /* copy the dot character */
    444             if(!format) break;
    445             nbChar = strspn((const char *)format, (const char *)widthOrPrecisionChar);
    446             if(nbChar)
    447             {
    448                 strncpy((char *)pTemp, (const char *)format, nbChar);      /* copy the width characters */
    449                 format +=nbChar;
    450                 pTemp   +=nbChar;
    451             }
    452             if(!format) break;
    453         }
    454         if(strlen((const char *)format)>=2)
    455         {
    456             if(!strncmp((const char *)format, "ll", 2))
    457             {
    458                 *pTemp++ = 'l'; /* %l */
    459                 format +=2;                         /* span the "ll" prefix */
    460             }
    461             else if(!strncmp((const char *)format, "tm", 2))
    462             {
    463                 *pTemp++ = 'l'; /* %l */
    464                 format +=2;                         /* span the "tm" prefix */
    465             }
    466             else if(!strncmp((const char *)format, "aa", 2))
    467             {
    468                 *pTemp++ = 'l';
    469                 format +=2;                         /* span the "aa" prefix */
    470             }
    471         }
    472         nbChar = strspn((const char *)format, (const char *)otherPrefixChar);
    473         if(nbChar)
    474         {
    475             strncpy((char *)pTemp, (const char *)format, nbChar);      /* copy the other Prefix */
    476             format +=nbChar;
    477             pTemp   +=nbChar;
    478         }
    479         if(!*format) break;
    480         nbChar = strspn((const char *)format, (const char *)conversionChar);
    481         if(nbChar)
    482         {
    483             strncpy((char *)pTemp, (const char *)format, nbChar);
    484             format += nbChar;
    485             pTemp   += nbChar;
    486         }
    487         if(!*format) break;
    488     }
    489 
    490     /* Zero terminate the format string. */
    491     (*pTemp) = '\0';
    492 
    493     err = vsnprintf((char *)pStrOut, (size_t)strOutMaxLen + 1, (const char *)newFormat, marker);
    494     va_end(marker);
    495     free(newFormat);
    496     if ((err<0) || ((M4OSA_UInt32)err>strOutMaxLen))
    497     {
    498         pStrOut[strOutMaxLen] = '\0';
    499         return M4ERR_CHR_STR_OVERFLOW;
    500     }
    501     else
    502     {
    503         return M4NO_ERROR;
    504     }
    505 }
    506 
    507