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