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