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