/** ****************************************************************************** * @file StringUtils.c * @author William Xu * @version V1.0.0 * @date 05-May-2014 * @brief This file contains function for manipulating strings.. ****************************************************************************** * * The MIT License * Copyright (c) 2014 MXCHIP Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is furnished * to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************** */ #include "StringUtils.h" #include "debug.h" #include #include #ifndef MIN extern int MIN (/*@sef@*/ int x, /*@sef@*/ int y); /* LINT : This tells lint that the parameter must be side-effect free. i.e. evaluation does not change any values (since it is being evaulated more than once */ #define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* ifndef MIN */ #ifndef MAX extern int MAX (/*@sef@*/ int x, /*@sef@*/ int y); /* LINT : This tells lint that the parameter must be side-effect free. i.e. evaluation does not change any values (since it is being evaulated more than once */ #define MAX(x,y) ((x) > (y) ? (x) : (y)) #endif /* ifndef MAX */ #define IS_AF(c) ((c >= 'A') && (c <= 'F')) #define IS_af(c) ((c >= 'a') && (c <= 'f')) #define IS_09(c) ((c >= '0') && (c <= '9')) #define ISVALIDHEX(c) IS_AF(c) || IS_af(c) || IS_09(c) #define ISVALIDDEC(c) IS_09(c) #define CONVERTDEC(c) (c - '0') #define CONVERTHEX_alpha(c) (IS_AF(c) ? (c - 'A'+10) : (c - 'a'+10)) #define CONVERTHEX(c) (IS_09(c) ? (c - '0') : CONVERTHEX_alpha(c)) //=========================================================================================================================== // formatMACAddr // // Add ":" to every two character //=========================================================================================================================== void formatMACAddr(char *destAddr, char *srcAddr) { sprintf((char *)destAddr, "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",\ toupper(*(char *)srcAddr),toupper(*((char *)(srcAddr)+1)),\ toupper(*((char *)(srcAddr)+2)),toupper(*((char *)(srcAddr)+3)),\ toupper(*((char *)(srcAddr)+4)),toupper(*((char *)(srcAddr)+5)),\ toupper(*((char *)(srcAddr)+6)),toupper(*((char *)(srcAddr)+7)),\ toupper(*((char *)(srcAddr)+8)),toupper(*((char *)(srcAddr)+9)),\ toupper(*((char *)(srcAddr)+10)),toupper(*((char *)(srcAddr)+11))); } //=========================================================================================================================== // __strdup // // Alloc a new memory and store the input content //=========================================================================================================================== char *__strdup(const char *src) { int len; char *dst; if (src == NULL) return NULL; if (src[0] == 0) return NULL; len = strlen(src) + 1; dst = (char*)malloc(len); if (dst) memcpy(dst, src, len); return dst; } char *__strdup_trans_dot(char *src) { char *dst, *dstTemp; char *srcTemp = src; uint32_t newLen = strlen(src)+1; while(*srcTemp!= 0) { if (*srcTemp == '.') newLen++; srcTemp++; } dst = malloc(newLen); dstTemp = dst; srcTemp = src; while(*srcTemp!= 0) { if (*srcTemp == '.') { *dstTemp++ = '/'; *dstTemp++ = '.'; srcTemp++; } else { *dstTemp++ = *srcTemp++; } } *dstTemp = 0x0; return dst; } /*** *strnlen - return the length of a null-terminated string * *Purpose: * Finds the length in bytes of the given string, not including * the final null character. Only the first maxsize characters * are inspected: if the null character is not found, maxsize is * returned. * *Entry: * const char * str - string whose length is to be computed * size_t maxsize * *Exit: * Length of the string "str", exclusive of the final null byte, or * maxsize if the null character is not found. * *Exceptions: * *******************************************************************************/ #if defined (__CC_ARM) size_t strnlen(const char *str, size_t maxsize) { size_t n; /* Note that we do not check if s == NULL, because we do not * return errno_t... */ for (n = 0; n < maxsize && *str; n++, str++) ; return n; } #endif void Int2Str(uint8_t* str, int32_t intnum) { uint32_t i, Div = 1000000000, j = 0, Status = 0; for (i = 0; i < 10; i++) { str[j++] = (intnum / Div) + 48; intnum = intnum % Div; Div /= 10; if ((str[j-1] == '0') & (Status == 0)) { j = 0; } else { Status++; } } } uint32_t Str2Int(uint8_t *inputstr, int32_t *intnum) { uint32_t i = 0, res = 0; uint32_t val = 0; if (inputstr[0] == '0' && (inputstr[1] == 'x' || inputstr[1] == 'X')) { if (inputstr[2] == '\0') { return 0; } for (i = 2; i < 11; i++) { if (inputstr[i] == '\0') { *intnum = val; /* return 1; */ res = 1; break; } if (ISVALIDHEX(inputstr[i])) { val = (val << 4) + CONVERTHEX(inputstr[i]); } else { /* Return 0, Invalid input */ res = 0; break; } } /* Over 8 digit hex --invalid */ if (i >= 11) { res = 0; } } else /* max 10-digit decimal input */ { for (i = 0;i < 11;i++) { if (inputstr[i] == '\0') { *intnum = val; /* return 1 */ res = 1; break; } else if ((inputstr[i] == 'k' || inputstr[i] == 'K') && (i > 0)) { val = val << 10; *intnum = val; res = 1; break; } else if ((inputstr[i] == 'm' || inputstr[i] == 'M') && (i > 0)) { val = val << 20; *intnum = val; res = 1; break; } else if (ISVALIDDEC(inputstr[i])) { val = val * 10 + CONVERTDEC(inputstr[i]); } else { /* return 0, Invalid input */ res = 0; break; } } /* Over 10 digit decimal --invalid */ if (i >= 11) { res = 0; } } return res; } unsigned int str2hex(unsigned char *ibuf, unsigned char *obuf, unsigned int olen) { unsigned int i; /* loop iteration variable */ unsigned int j = 0; /* current character */ unsigned int by = 0; /* byte value for conversion */ unsigned char ch; /* current character */ unsigned int len = strlen((char *)ibuf); /* process the list of characaters */ for (i = 0; i < len; i++) { if (i == (2 * olen)) { // truncated it. return j + 1; } ch = ibuf[i]; /* do the conversion */ if (ch >= '0' && ch <= '9') by = (by << 4) + ch - '0'; else if (ch >= 'A' && ch <= 'F') by = (by << 4) + ch - 'A' + 10; else if (ch >= 'a' && ch <= 'f') by = (by << 4) + ch - 'a' + 10; else { /* error if not hexadecimal */ return 0; } /* store a byte for each pair of hexadecimal digits */ if (i & 1) { j = ((i + 1) / 2) - 1; obuf[j] = by & 0xff; } } return j + 1; } //=========================================================================================================================== // TextToHardwareAddress // // Parses hardware address text (e.g. AA:BB:CC:00:11:22:33:44 for Fibre Channel) into an n-byte array. // Segments can be separated by a colon ':', dash '-', or a space ' '. Segments do not need zero padding // (e.g. "0:1:2:3:4:5:6:7" is equivalent to "00:01:02:03:04:05:06:07"). //=========================================================================================================================== OSStatus TextToHardwareAddress( const void *inText, size_t inTextSize, size_t inAddrSize, void *outAddr ) { OSStatus err; const char * src; const char * end; int i; int x; char c; uint8_t * dst; if( inTextSize == kSizeCString ) inTextSize = strlen( (const char *) inText ); src = (const char *) inText; end = src + inTextSize; dst = (uint8_t *) outAddr; while( inAddrSize-- > 0 ) { x = 0; i = 0; while( ( i < 2 ) && ( src < end ) ) { c = *src++; if( isdigit_safe( c ) ) { x = ( x * 16 ) + ( c - '0' ); ++i; } else if( isxdigit_safe( c ) ) { x = ( x * 16 ) + 10 + ( tolower_safe( c ) - 'a' ); ++i; } else if( ( i != 0 ) || ( ( c != ':' ) && ( c != '-' ) && ( c != ' ' ) ) ) break; } if( i == 0 ) { err = kMalformedErr; goto exit; } require_action( (( x >= 0x00 ) && ( x <= 0xFF )), exit, err = kRangeErr ); if( dst ) *dst++ = (uint8_t) x; } err = kNoErr; exit: return err; } char* DataToHexString( const uint8_t *inBuf, size_t inBufLen ) { char* buf_str = NULL; char* buf_ptr; require_quiet(inBuf, error); require_quiet(inBufLen > 0, error); buf_str = (char*) malloc (2*inBufLen + 1); require(buf_str, error); buf_ptr = buf_str; uint32_t i; for (i = 0; i < inBufLen; i++) buf_ptr += sprintf(buf_ptr, "%02X", inBuf[i]); *buf_ptr = '\0'; return buf_str; error: if ( buf_str ) free( buf_str ); return NULL; } char* DataToHexStringWithSpaces( const uint8_t *inBuf, size_t inBufLen ) { char* buf_str = NULL; char* buf_ptr = NULL; require_quiet(inBuf, error); require_quiet(inBufLen > 0, error); buf_str = (char*) malloc (3*inBufLen + 1); require(buf_str, error); buf_ptr = buf_str; uint32_t i; for (i = 0; i < inBufLen; i++) buf_ptr += sprintf(buf_ptr, "%02X ", inBuf[i]); *buf_ptr = '\0'; return buf_str; error: if ( buf_str ) free( buf_str ); return NULL; } char* DataToHexStringWithColons( const uint8_t *inBuf, size_t inBufLen ) { char* buf_str = NULL; char* buf_ptr = NULL; require_quiet(inBuf, error); require_quiet(inBufLen > 0, error); buf_str = (char*) malloc (3*inBufLen + 1); require(buf_str, error); buf_ptr = buf_str; uint32_t i; for (i = 0; i < inBufLen; i++) { if ( i == inBufLen - 1 ) buf_ptr += sprintf(buf_ptr, "%02X", inBuf[i]); else buf_ptr += sprintf(buf_ptr, "%02X:", inBuf[i]); } *buf_ptr = '\0'; return buf_str; error: if ( buf_str ) free( buf_str ); return NULL; } char* DataToCString( const uint8_t *inBuf, size_t inBufLen ) { char* cString = NULL; require_quiet(inBuf, error); require_quiet(inBufLen > 0, error); cString = (char*) malloc( inBufLen + 1 ); require(cString, error); memcpy( cString, inBuf, inBufLen ); *(cString + inBufLen ) = '\0'; return cString; error: if ( cString ) free( cString ); return NULL; } //=========================================================================================================================== // strnicmp // // Like the ANSI C strncmp routine, but performs a case-insensitive compare. //=========================================================================================================================== int strnicmp( const char *inS1, const char *inS2, size_t inMax ) { const char * end; int c1; int c2; end = inS1 + inMax; while( inS1 < end ) { c1 = tolower( *( (const unsigned char *) inS1 ) ); c2 = tolower( *( (const unsigned char *) inS2 ) ); if( c1 < c2 ) return( -1 ); if( c1 > c2 ) return( 1 ); if( c1 == '\0' ) break; ++inS1; ++inS2; } return( 0 ); } //=========================================================================================================================== // strnicmpx // // Like the ANSI C strncmp routine, but case-insensitive and requires all characters in s1 match all characters in s2. //=========================================================================================================================== int strnicmpx( const void *inS1, size_t inN, const char *inS2 ) { const unsigned char * s1; const unsigned char * s2; int c1; int c2; s1 = (const unsigned char *) inS1; s2 = (const unsigned char *) inS2; while( inN-- > 0 ) { c1 = tolower( *s1 ); c2 = tolower( *s2 ); if( c1 < c2 ) return( -1 ); if( c1 > c2 ) return( 1 ); if( c2 == 0 ) return( 0 ); ++s1; ++s2; } if( *s2 != 0 ) return( -1 ); return( 0 ); } //=========================================================================================================================== // VSNScanF - va_list version of SNScanF. //=========================================================================================================================== int VSNScanF( const void *inString, size_t inSize, const char *inFormat, va_list inArgs ) { int matched; const unsigned char * src; const unsigned char * end; const unsigned char * fmt; const unsigned char * old; const unsigned char * setStart; const unsigned char * setEnd; const unsigned char * set; int notSet; int suppress; int alt; int storePtr; int fieldWidth; int sizeModifier; unsigned char * s; int * i; int base; int negative; unsigned char c; int64_t x; int v; void * p; const unsigned char ** ptrArg; size_t * sizeArg; size_t len; if( inSize == kSizeCString ) inSize = strlen( (const char *) inString ); src = (const unsigned char *) inString; end = src + inSize; fmt = (const unsigned char *) inFormat; matched = 0; for( ;; ) { // Skip whitespace. 1 or more whitespace in the format matches 0 or more whitepsace in the string. if( isspace( *fmt ) ) { ++fmt; while( isspace( *fmt ) ) ++fmt; while( ( src < end ) && isspace( *src ) ) ++src; } if( *fmt == '\0' ) break; // If it's not a conversion, it must match exactly. Otherwise, move onto conversion handling. if( *fmt != '%' ) { if( src >= end ) break; if( *fmt++ != *src++ ) break; continue; } ++fmt; // Flags suppress = 0; alt = 0; storePtr = 0; for( ;; ) { c = *fmt; if( c == '*' ) suppress = 1; else if( c == '#' ) alt += 1; else if( c == '&' ) storePtr = 1; else break; ++fmt; } // Field width. If none, use INT_MAX to simplify no-width vs width cases. if( isdigit( *fmt ) ) { fieldWidth = 0; do { fieldWidth = ( fieldWidth * 10 ) + ( *fmt++ - '0' ); } while( isdigit( *fmt ) ); } else if( *fmt == '.' ) { ++fmt; fieldWidth = va_arg( inArgs, int ); if( fieldWidth < 0 ) goto exit; } else { fieldWidth = INT_MAX; } // Size modifier. Note: converts double-char (e.g. hh) into unique char (e.g. H) for easier processing. c = *fmt; switch( c ) { case 'h': if( *( ++fmt ) == 'h' ) { sizeModifier = 'H'; ++fmt; } // hh for char * / unsigned char * else sizeModifier = 'h'; // h for short * / unsigned short * break; case 'l': if( *( ++fmt ) == 'l' ) { sizeModifier = 'L'; ++fmt; } // ll for long long * / unsigned long long * else sizeModifier = 'l'; // l for long * / unsigned long * break; case 'j': // j for intmax_t * / uintmax_t * case 'z': // z for size_t * case 't': // t for ptrdiff_t * sizeModifier = c; ++fmt; break; default: sizeModifier = 0; break; } if( *fmt == '\0' ) break; // Conversions switch( *fmt++ ) { case 'd': // %d: Signed decimal integer. base = 10; break; case 'u': // %u: Unsigned decimal integer. base = 10; break; case 'p': // %x/%X/%p: Hexidecimal integer. if( sizeModifier == 0 ) sizeModifier = 'p'; case 'x': case 'X': base = 16; break; case 'o': // %o: Octal integer. base = 8; break; case 'i': // %i: Integer using an optional prefix to determine the base (e.g. 10, 0xA, 012, 0b1010 for decimal 10). base = 0; break; case 'b': // %b: Binary integer. base = 2; break; case 'c': // %c: 1 or more characters. if( sizeModifier != 0 ) goto exit; if( storePtr ) { len = (size_t)( end - src ); if( len > (size_t) fieldWidth ) { len = (size_t) fieldWidth; } if( suppress ) { src += len; continue; } ptrArg = va_arg( inArgs, const unsigned char ** ); if( ptrArg ) *ptrArg = src; sizeArg = va_arg( inArgs, size_t * ); if( sizeArg ) *sizeArg = len; src += len; } else { if( fieldWidth == INT_MAX ) fieldWidth = 1; if( ( end - src ) < fieldWidth ) goto exit; if( suppress ) { src += fieldWidth; continue; } s = va_arg( inArgs, unsigned char * ); if( !s ) goto exit; while( fieldWidth-- > 0 ) *s++ = *src++; } ++matched; continue; case 's': // %s: string of non-whitespace characters with a null terminator. if( sizeModifier != 0 ) goto exit; // Skip leading white space first since fieldWidth does not include leading whitespace. while( ( src < end ) && isspace( *src ) ) ++src; if( !alt && ( ( src >= end ) || ( *src == '\0' ) ) ) goto exit; // Copy the string until a null terminator, whitespace, or the max fieldWidth is hit. if( suppress ) { while( ( src < end ) && ( *src != '\0' ) && !isspace( *src ) && ( fieldWidth-- > 0 ) ) ++src; } else if( storePtr ) { old = src; while( ( src < end ) && ( *src != '\0' ) && !isspace( *src ) && ( fieldWidth-- > 0 ) ) ++src; ptrArg = va_arg( inArgs, const unsigned char ** ); if( ptrArg ) *ptrArg = old; sizeArg = va_arg( inArgs, size_t * ); if( sizeArg ) *sizeArg = (size_t)( src - old ); ++matched; } else { s = va_arg( inArgs, unsigned char * ); if( !s ) goto exit; while( ( src < end ) && ( *src != '\0' ) && !isspace( *src ) && ( fieldWidth-- > 0 ) ) *s++ = *src++; *s = '\0'; ++matched; } continue; case '[': // %[: Match a scanset (set between brackets or the compliment set if it starts with ^). if( sizeModifier != 0 ) goto exit; notSet = ( *fmt == '^' ); // A scanlist starting with ^ matches all characters not in the scanlist. if( notSet ) ++fmt; setStart = fmt; if( *fmt == ']' ) ++fmt; // A scanlist (after a potential ^) starting with ] includes ] in the set. // Find the end of the scanlist. while( ( *fmt != '\0' ) && ( *fmt != ']' ) ) ++fmt; if( *fmt == '\0' ) goto exit; setEnd = fmt++; // Parse until a mismatch, null terminator, or the max fieldWidth is hit. old = src; if( notSet ) { while( ( src < end ) && ( *src != '\0' ) && ( fieldWidth-- > 0 ) ) { c = *src; for( set = setStart; ( set < setEnd ) && ( *set != c ); ++set ) {} if( set < setEnd ) break; ++src; } } else { while( ( src < end ) && ( *src != '\0' ) && ( fieldWidth-- > 0 ) ) { c = *src; for( set = setStart; ( set < setEnd ) && ( *set != c ); ++set ) {} if( set >= setEnd ) break; ++src; } } if( ( old == src ) && !alt ) goto exit; if( !suppress ) { if( storePtr ) { ptrArg = va_arg( inArgs, const unsigned char ** ); if( ptrArg ) *ptrArg = old; sizeArg = va_arg( inArgs, size_t * ); if( sizeArg ) *sizeArg = (size_t)( src - old ); } else { s = va_arg( inArgs, unsigned char * ); if( !s ) goto exit; while( old < src ) *s++ = *old++; *s = '\0'; } ++matched; } continue; case '%': // %%: Match a literal % character. if( sizeModifier != 0 ) goto exit; if( fieldWidth != INT_MAX ) goto exit; if( suppress ) goto exit; if( src >= end ) goto exit; if( *src++ != '%' ) goto exit; continue; case 'n': // %n: Return the number of characters read so far. if( sizeModifier != 0 ) goto exit; if( fieldWidth != INT_MAX ) goto exit; if( suppress ) goto exit; i = va_arg( inArgs, int * ); if( !i ) goto exit; *i = (int)( src - ( (const unsigned char *) inString ) ); continue; default: // Unknown conversion. goto exit; } // Number conversion. Skip leading white space since number conversions ignore leading white space. while( ( src < end ) && isspace( *src ) ) ++src; // Handle +/- prefix for negative/positive (even for unsigned numbers). negative = 0; if( ( ( end - src ) > 1 ) && ( fieldWidth > 0 ) ) { if( src[ 0 ] == '-' ) { negative = 1; ++src; --fieldWidth; } else if( src[ 0 ] == '+' ) { ++src; --fieldWidth; } } // Detect the base for base 0 and skip valid prefixes. old = src; if( base == 0 ) { if( ( ( end - src ) > 2 ) && ( fieldWidth >= 2 ) && ( src[ 0 ] == '0' ) && ( tolower( src[ 1 ] ) == 'x' ) && isxdigit( src[ 2 ] ) ) { base = 16; src += 2; fieldWidth -= 2; } else if( ( ( end - src ) > 2 ) && ( fieldWidth >= 2 ) && ( src[ 0 ] == '0' ) && ( tolower( src[ 1 ] ) == 'b' ) && ( ( src[ 2 ] == '0' ) || ( src[ 2 ] == '1' ) ) ) { base = 2; src += 2; fieldWidth -= 2; } else if( ( ( end - src ) > 1 ) && ( fieldWidth >= 1 ) && ( src[ 0 ] == '0' ) && ( src[ 1 ] >= '0' ) && ( src[ 1 ] <= '7' ) ) { base = 8; src += 1; fieldWidth -= 1; } else { base = 10; } } else if( ( base == 16 ) && ( ( end - src ) >= 2 ) && ( fieldWidth >= 2 ) && ( src[ 0 ] == '0' ) && ( tolower( src[ 1 ] ) == 'x' ) ) { src += 2; fieldWidth -= 2; } else if( ( base == 2 ) && ( ( end - src ) >= 2 ) && ( fieldWidth >= 2 ) && ( src[ 0 ] == '0' ) && ( tolower( src[ 1 ] ) == 'b' ) ) { src += 2; fieldWidth -= 2; } // Convert the string to a number. x = 0; while( ( src < end ) && ( fieldWidth-- > 0 ) ) { c = *src; if( isdigit( c ) ) v = c - '0'; else if( isxdigit( c ) ) v = 10 + ( tolower( c ) - 'a' ); else break; if( v >= base ) break; x = ( x * base ) + v; ++src; } if( src == old ) goto exit; if( suppress ) continue; if( negative ) x = -x; // Store the result. p = va_arg( inArgs, void * ); if( !p ) goto exit; switch( sizeModifier ) { case 0: *( (int *) p ) = (int) x; break; case 'l': *( (long *) p ) = (long) x; break; case 'H': *( (char *) p ) = (char) x; break; case 'h': *( (short *) p ) = (short) x; break; case 'L': *( (int64_t *) p ) = x; break; case 'j': *( (intmax_t *) p ) = (intmax_t) x; break; case 'z': *( (size_t *) p ) = (size_t) x; break; case 't': *( (ptrdiff_t *) p ) = (ptrdiff_t) x; break; case 'p': *( (void **) p ) = (void *)( (uintptr_t) x ); break; default: // Unknown size modifier. goto exit; } ++matched; } exit: return( matched ); } //=========================================================================================================================== // strnicmp_suffix // // Like strnicmp routine, but only returns 0 if the entire suffix matches. //=========================================================================================================================== int strnicmp_suffix( const void *inStr, size_t inMaxLen, const char *inSuffix ) { const char * stringPtr; size_t stringLen; size_t suffixLen; stringPtr = (const char *) inStr; stringLen = strnlen( stringPtr, inMaxLen ); suffixLen = strlen( inSuffix ); if( suffixLen <= stringLen ) { return( strnicmpx( stringPtr + ( stringLen - suffixLen ), suffixLen, inSuffix ) ); } return( -1 ); } //=========================================================================================================================== // strnstr_suffix // // Like the ANSI C strstr routine, but performs a case-insensitive compare. //=========================================================================================================================== char * strnstr_suffix( const char *inStr, size_t inMaxLen, const char *inSuffix) { size_t stringLen; size_t suffixLen; char * instr_tmp; char * inSuffix_tmp; size_t i; char * ret; suffixLen = strlen( inSuffix ); stringLen = strnlen( inStr, inMaxLen ); instr_tmp = calloc(stringLen+1, 1); inSuffix_tmp = calloc(suffixLen+1, 1); for(i=0; i ( 0x7fffffff >> 4 ) ) && ( is_unsigned == 0 ) ) || ( *value_out > ( 0xffffffff >> 4 ) ) ) { break; } *value_out = ( *value_out << 4 ) + nibble; } else { if ( ( ( *value_out > ( 0x7fffffff / 10 ) ) && ( is_unsigned == 0 ) ) || ( *value_out > ( 0xffffffff / 10 ) ) ) { break; } *value_out = ( *value_out * 10 ) + nibble; } string++; characters_processed++; } return characters_processed; } /*! ****************************************************************************** * Convert a decimal or hexidecimal string to an integer. * * @param[in] str The string containing the value. * * @return The value represented by the string. */ uint32_t generic_string_to_unsigned( const char* str ) { uint32_t val = 0; uint8_t is_hex = 0; if ( strncmp( str, "0x", 2 ) == 0 ) { is_hex = 1; str += 2; } string_to_unsigned( str, (uint8_t)strlen(str), &val, is_hex ); return val; } /** * Converts a decimal/hexidecimal string (with optional sign) to a signed long int * Better than strtol or atol or atoi because the return value indicates if an error occurred * * @param string[in] : The string buffer to be converted * @param str_length[in] : The maximum number of characters to process in the string buffer * @param value_out[out] : The unsigned in that will receive value of the the decimal string * @param is_hex[in] : 0 = Decimal string, 1 = Hexidecimal string * * @return the number of characters successfully converted (including sign). i.e. 0 = error * */ uint8_t string_to_signed( const char* string, uint8_t str_length, int32_t* value_out, uint8_t is_hex ) { uint8_t characters_processed = 0; uint8_t retval; char first_char; if ( string == NULL ) { return 0; } first_char = *string; if ( ( first_char == '-' ) || ( *string == '+' ) ) { characters_processed++; string++; str_length--; } retval = string_to_generic( string, str_length, (uint32_t*)value_out, 0, is_hex ); if ( retval == 0 ) { return 0; } if ( first_char == '-' ) { *value_out = -(*value_out); } return (uint8_t) ( characters_processed + retval ); } /** * Converts a decimal/hexidecimal string to an unsigned long int * Better than strtol or atol or atoi because the return value indicates if an error occurred * * @param string[in] : The string buffer to be converted * @param str_length[in] : The maximum number of characters to process in the string buffer * @param value_out[out] : The unsigned in that will receive value of the the decimal string * @param is_hex[in] : 0 = Decimal string, 1 = Hexidecimal string * * @return the number of characters successfully converted. i.e. 0 = error * */ uint8_t string_to_unsigned( const char* string, uint8_t str_length, uint32_t* value_out, uint8_t is_hex ) { return string_to_generic( string, str_length, value_out, 1, is_hex ); } /** * Converts a unsigned long int to a decimal string * * @param value[in] : The unsigned long to be converted * @param output[out] : The buffer which will receive the decimal string * @param min_length[in] : the minimum number of characters to output (zero padding will apply if required). * @param max_length[in] : the maximum number of characters to output (up to 10 ). There must be space for terminating NULL. * * @note: A terminating NULL is added. Wnsure that there is space in the buffer for this. * * @return the number of characters returned (excluding terminating null) * */ uint8_t unsigned_to_decimal_string( uint32_t value, char* output, uint8_t min_length, uint8_t max_length ) { uint8_t digits_left; char buffer[ 10 ] = "0000000000"; max_length = (uint8_t) MIN( max_length, sizeof( buffer ) ); digits_left = max_length; while ( ( value != 0 ) && ( digits_left != 0 ) ) { --digits_left; buffer[ digits_left ] = (char) (( value % 10 ) + '0'); value = value / 10; } digits_left = (uint8_t) MIN( ( max_length - min_length ), digits_left ); memcpy( output, &buffer[ digits_left ], (size_t)( max_length - digits_left ) ); /* Add terminating null */ output[( max_length - digits_left )] = '\x00'; return (uint8_t) ( max_length - digits_left ); } /** * Converts a signed long int to a decimal string * * @param value[in] : The signed long to be converted * @param output[out] : The buffer which will receive the decimal string * @param min_length[in] : the minimum number of characters to output (zero padding will apply if required) * @param max_length[in] : the maximum number of characters to output (up to 10 ). There must be space for terminating NULL. * * @note: A terminating NULL is added. Wnsure that there is space in the buffer for this. * * @return the number of characters returned. * */ uint8_t signed_to_decimal_string( int32_t value, char* output, uint8_t min_length, uint8_t max_length ) { uint8_t retval = 0; if ( ( value < 0 ) && ( max_length > 0 ) ) { *output = '-'; output++; max_length--; value = -value; retval++; } retval = (uint8_t) ( retval + unsigned_to_decimal_string( (uint32_t)value, output, min_length, max_length ) ); return retval; } /** * Converts a unsigned long int to a hexidecimal string * * @param value[in] : The unsigned long to be converted * @param output[out] : The buffer which will receive the hexidecimal string * @param min_length[in] : the minimum number of characters to output (zero padding will apply if required) * @param max_length[in] : the maximum number of characters to output (up to 8 ) There must be space for terminating NULL. * * @note: A terminating NULL is added. Wnsure that there is space in the buffer for this. * @note: No leading '0x' is added. * * @return the number of characters returned. * */ uint8_t unsigned_to_hex_string( uint32_t value, char* output, uint8_t min_length, uint8_t max_length ) { uint8_t digits_left; char buffer[ 8 ] = "00000000"; max_length = (uint8_t) MIN( max_length, sizeof( buffer ) ); digits_left = max_length; while ( ( value != 0 ) && ( digits_left != 0 ) ) { --digits_left; buffer[ digits_left ] = nibble_to_hexchar( value & 0x0000000F ); value = value >> 4; } digits_left = (uint8_t) MIN( ( max_length - min_length ), digits_left ); memcpy( output, &buffer[ digits_left ], (size_t)( max_length - digits_left ) ); /* Add terminating null */ output[( max_length - digits_left )] = '\x00'; return (uint8_t) ( max_length - digits_left ); } int is_digit_str( const char* str ) { int res = 0; int i = 0; if ( str != NULL ) { i = (int)strlen(str); res = 1; while ( i > 0 ) { if ( !IS_09(*str) ) { res = 0; break; } str++; i--; } } return res; } uint8_t match_string_with_wildcard_pattern( const char* string, uint32_t length, const char* pattern ) { uint32_t current_string_length = length; uint32_t temp_string_length = 0; char* current_string = (char*)string; char* current_pattern = (char*)pattern; char* temp_string = NULL; char* temp_pattern = NULL; /* Iterate through string and pattern until '*' is found */ while ( ( current_string_length != 0 ) && ( *current_pattern != '*' ) ) { /* Current pattern is not equal current string and current pattern isn't a wildcard character */ if ( ( *current_pattern != *current_string ) && ( *current_pattern != '?' ) ) { return 0; } current_pattern++; current_string++; current_string_length--; } /* '*' is detected in pattern. Consume string until matching pattern is found */ while ( current_string_length != 0 ) { switch ( *current_pattern ) { case '*': if ( *(++current_pattern) == '\0' ) { /* Last character in the pattern is '*'. Return successful */ return 1; } /* Store temp variables for starting another matching iteration when non-matching character is found. */ temp_pattern = current_pattern; temp_string_length = current_string_length - 1; temp_string = current_string + 1; break; case '?': current_pattern++; current_string++; current_string_length--; break; default: if ( *current_pattern == *current_string ) { current_pattern++; current_string++; current_string_length--; } else { current_pattern = temp_pattern; current_string = temp_string++; current_string_length = temp_string_length--; } break; } } while ( *current_pattern == '*' ) { current_pattern++; } return ( *current_pattern == '\0' ); } /* ****************************************************************************** * Length limited version of strstr. Ported from bcmutils.c * * @param arg The string to be searched. * @param arg The length of the string to be searched. * @param arg The string to be found. * @param arg The length of the string to be found. * * @return pointer to the found string if search successful, otherwise NULL */ char* strnstr(const char *s, uint16_t s_len, const char *substr, uint16_t substr_len) { for (; s_len >= substr_len; s++, s_len--) { if (strncmp(s, substr, substr_len) == 0) { return (char*)s; } } return NULL; }