M4OSA_CharStar.c revision aa382f3637a68361989d5b70e3184bddcc472d3d
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 newFormatLength -= (count_ll+count_tm+count_aa); 405 406 newFormat =(M4OSA_Char*)M4OSA_32bitAlignedMalloc(newFormatLength, 407 M4OSA_CHARSTAR,(M4OSA_Char*)"M4OSA_chrPrintf: newFormat"); 408 if(M4OSA_NULL == newFormat) 409 return M4ERR_ALLOC; 410 newFormat[newFormatLength-1] = '\0'; 411 pTemp = newFormat; 412 413 /* copy format to newFormat, replacing %[flags][width][.precision]ll[conversion] 414 * by %[flags][width][.precision]I64[conversion] */ 415 while(*format) 416 { 417 nbChar = strcspn((const char *)format, "%"); 418 if(nbChar) 419 { 420 strncpy((char *)pTemp, (const char *)format, nbChar); /* copy characters before the % character */ 421 format +=nbChar; 422 pTemp +=nbChar; 423 } 424 if(!*format) break; 425 *pTemp++ = *format++; /* copy the % character */ 426 nbChar = strspn((const char *)format, (const char *)flagChar); 427 if(nbChar) 428 { 429 strncpy((char *)pTemp, (const char *)format, nbChar); /* copy the flag characters */ 430 format +=nbChar; 431 pTemp +=nbChar; 432 } 433 if(!*format) break; 434 nbChar = strspn((const char *)format, (const char *)widthOrPrecisionChar); 435 if(nbChar) 436 { 437 strncpy((char *)pTemp, (const char *)format, nbChar); /* copy the width characters */ 438 format +=nbChar; 439 pTemp +=nbChar; 440 } 441 if(!*format) break; 442 if(*format=='.') 443 { 444 *pTemp++ = *format++; /* copy the dot character */ 445 if(!format) break; 446 nbChar = strspn((const char *)format, (const char *)widthOrPrecisionChar); 447 if(nbChar) 448 { 449 strncpy((char *)pTemp, (const char *)format, nbChar); /* copy the width characters */ 450 format +=nbChar; 451 pTemp +=nbChar; 452 } 453 if(!format) break; 454 } 455 if(strlen((const char *)format)>=2) 456 { 457 if(!strncmp((const char *)format, "ll", 2)) 458 { 459 *pTemp++ = 'l'; /* %l */ 460 format +=2; /* span the "ll" prefix */ 461 } 462 else if(!strncmp((const char *)format, "tm", 2)) 463 { 464 *pTemp++ = 'l'; /* %l */ 465 format +=2; /* span the "tm" prefix */ 466 } 467 else if(!strncmp((const char *)format, "aa", 2)) 468 { 469 *pTemp++ = 'l'; 470 format +=2; /* span the "aa" prefix */ 471 } 472 } 473 nbChar = strspn((const char *)format, (const char *)otherPrefixChar); 474 if(nbChar) 475 { 476 strncpy((char *)pTemp, (const char *)format, nbChar); /* copy the other Prefix */ 477 format +=nbChar; 478 pTemp +=nbChar; 479 } 480 if(!*format) break; 481 nbChar = strspn((const char *)format, (const char *)conversionChar); 482 if(nbChar) 483 { 484 strncpy((char *)pTemp, (const char *)format, nbChar); 485 format += nbChar; 486 pTemp += nbChar; 487 } 488 if(!*format) break; 489 } 490 491 /* Zero terminate the format string. */ 492 (*pTemp) = '\0'; 493 494 err = vsnprintf((char *)pStrOut, (size_t)strOutMaxLen + 1, (const char *)newFormat, marker); 495 va_end(marker); 496 free(newFormat); 497 if ((err<0) || ((M4OSA_UInt32)err>strOutMaxLen)) 498 { 499 pStrOut[strOutMaxLen] = '\0'; 500 return M4ERR_CHR_STR_OVERFLOW; 501 } 502 else 503 { 504 return M4NO_ERROR; 505 } 506} 507 508