• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
M4OSA_chrNCopy(M4OSA_Char * pStrOut,M4OSA_Char * pStrIn,M4OSA_UInt32 len2Copy)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 */
M4OSA_chrAreIdentical(M4OSA_Char * pStrIn1,M4OSA_Char * pStrIn2,M4OSA_Bool * pResult)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 */
M4OSA_chrGetUInt32(M4OSA_Char * pStrIn,M4OSA_UInt32 * pVal,M4OSA_Char ** pStrOut,M4OSA_chrNumBase base)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 */
M4OSA_chrGetUInt16(M4OSA_Char * pStrIn,M4OSA_UInt16 * pVal,M4OSA_Char ** pStrOut,M4OSA_chrNumBase base)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 
M4OSA_chrSPrintf(M4OSA_Char * pStrOut,M4OSA_UInt32 strOutMaxLen,M4OSA_Char * format,...)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