Host library for controlling a WiConnect enabled Wi-Fi module.
Dependents: wiconnect-ota_example wiconnect-web_setup_example wiconnect-test-console wiconnect-tcp_server_example ... more
Diff: StringUtil.h
- Revision:
- 0:ea85c4bb5e1f
- Child:
- 1:6ec9998427ad
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/StringUtil.h Mon Aug 11 09:58:24 2014 +0000 @@ -0,0 +1,387 @@ +/* + * Copyright 2014, ACKme Networks + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of ACKme Networks. + */ + +#pragma once + + +#include <string.h> +#include <ctype.h> +#include <stdint.h> +#include <limits.h> + + +#ifdef WICONNECT_USE_STRTOLL +// Necessary to get strtoll in C99 mode. +// http://sourceware.org/ml/newlib/2012/msg00425.html +extern long long strtoll(const char *__n, char **__end_PTR, int __base); +#endif + + +class StringUtil +{ + +public: + /*************************************************************************************************/ + // Helper to find an occurrence of a delimiter string, + // insert '\0' in its place and return string after + // the delimiter e.g. + // if char s[] = "foo://bar"; + // - strchop(s, "://") returns "bar" + // - s becomes "foo" + static char *chop(char *haystack, const char *needle) + { + if (!haystack) + { + return NULL; + } + char *end = strstr(haystack, needle); + if (end) + { + *end = '\0'; + return end + strlen(needle); + } + return NULL; + } + + /*************************************************************************************************/ + // Check if string is non-null and non-empty. + static bool empty(const char *s) + { + return !(s && *s); + } + + /*************************************************************************************************/ + static bool isSpace(const char *s) + { + while(*s != 0) + { + if(!isspace((uint8_t)*s++)) + return false; + } + return true; + } + + /*************************************************************************************************/ + // Convert null-terminated string to lower case. + // ASCII charset only. + static void toLower(char *s) + { + for (; *s; ++s) + { + *s = tolower((int) * s); + } + } + + /*************************************************************************************************/ + // Combination of strip left + right. + static char *strip(char *s, const char *chars) + { + return rightStrip(leftStrip(s, chars), chars); + } + + /*************************************************************************************************/ + // Strip string from the left. + // Returns pointer into the input string. + static char *leftStrip(char *s, const char *chars) + { + return s + strspn(s, chars); + } + + /*************************************************************************************************/ + // Strip string from the right. + // Modified in place. + static char *rightStrip(char *s, const char *chars) + { + char *end = s + strlen(s) - 1; + while (end > s && strstr(chars, end)) + { + *end-- = '\0'; + } + return s; + } + + /*************************************************************************************************/ + // Parse decimal integer and check if it's in bounds [min, max]. + static bool parseInt(const char *s, intmax_t *result, intmax_t min, intmax_t max) + { + return parseBase(s, result, min, max, 10); + } + + // Parse hexadecimal integer and check if it's in bounds [min, max]. + static bool parseHex(const char *s, intmax_t *result, intmax_t min, intmax_t max) + { + return parseBase(s, result, min, max, 16); + } + + /*************************************************************************************************/ + static bool parseBase(const char *s, intmax_t *result, intmax_t min, intmax_t max, int base) + { + if (!s) + { + return false; + } + char *end; +#ifdef WICONNECT_USE_STRTOLL + intmax_t value = strtoll(s, &end, base); +#else + intmax_t value = strtol(s, &end, base); +#endif + if (*end || value < min || value > max) + { + return false; + } + *result = value; + return true; + } + + /*************************************************************************************************/ + // Parse an long long integer. + static bool parseBool(const char *onoff, bool *var) + { + const char* const on_vals[] = + { + "1", + "on", + "true", + "yes", + }; + + for(uint8_t i = 0; i < ARRAY_COUNT(on_vals); ++i) + { + if(strcasecmp(on_vals[i], onoff) == 0) + { + *var = true; + return true; + } + } + + const char* const off_vals[] = + { + "0", + "false", + "no", + "off", + NULL + }; + for(uint8_t i = 0; i < ARRAY_COUNT(off_vals); ++i) + { + if(strcasecmp(off_vals[i], onoff) == 0) + { + *var = false; + return true; + } + } + + return false; + } + + /*************************************************************************************************/ + // convert binary data to hex string + static void binToHex(char *dst, int max_dst, const void *data, int data_len) + { + char *end = dst + max_dst - 1; + for (int i = 0; i < data_len; ++i) + { + if (dst < end) + { + dst += sprintf(dst, "%2.2x", ((uint8_t *)data)[i]); + } + } + } + + + /*************************************************************************************************/ + // Parse binary data into hex string + // the input buffer MUST be len*2 long + // as the parsing is destructive and done in-place + static void binToHex(void *h, int len) + { + char *dst = (char*)h; + char *src= (char*)h+len; + + memmove(src, dst, len); + + while(len--) + { + sprintf(dst, "%2.2X", (unsigned int)(*src & 0xff)); + dst += 2; + ++src; + } + } + + + /*************************************************************************************************/ + // Parses hex representation of binary data destructively. + // Returns number of bytes parsed or -1 on error. + static int hexToBin(char *s) + { + int len, i, j; + len = strlen(s); + if (len % 2) + { + return -1; + } + for (i = j = 0; i < len; i += 2, j++) + { + const int num = hexToInt(&s[i]); + if(num == -1) + return -1; + s[j] = (char)num; + } + return j; + } + + /*************************************************************************************************/ + // hex string to integer, returns -1 on error + static int hexToInt(const char *hex_str) + { + int hi = hexToNibble(*hex_str); + int lo = hexToNibble(*(hex_str+1)); + if (hi == -1 || lo == -1) + { + return -1; + } + return (hi << 4) | lo; + } + + /*************************************************************************************************/ + static int hexToNibble(char c) + { + if (c >= '0' && c <= '9') + { + return c - '0'; + } + if (c >= 'a' && c <= 'f') + { + return 10 + (c - 'a'); + } + if (c >= 'A' && c <= 'F') + { + return 10 + (c - 'A'); + } + return -1; + } + + /*************************************************************************************************/ + static const char* uint32ToStr(char* intStrBuffer, int integer) + { + sprintf(intStrBuffer, "%u", integer); + return intStrBuffer; + } + + /*************************************************************************************************/ + static bool strToUint32(const char *str, uint32_t *uint32Ptr) + { + intmax_t r; + bool result = StringUtil::parseInt(str, &r, 0, UINT_MAX); + *uint32Ptr = (uint32_t)r; + return result; + } + + /*************************************************************************************************/ + static bool strToInt32(const char *str, int32_t *int32Ptr) + { + intmax_t r; + bool result = StringUtil::parseInt(str, &r, INT_MIN, INT_MAX); + *int32Ptr = (int32_t)r; + return result; + } + + /*************************************************************************************************/ + // uint32 hex string to uint32 + static bool strHexToUint32(const char *strHex, uint32_t *uint32Ptr) + { + intmax_t r; + bool result = StringUtil::parseHex(strHex, &r, 0, UINT_MAX); + *uint32Ptr = (uint32_t)r; + return result; + } + + /*************************************************************************************************/ + static char *strtok_r(char *str, const char *delim, char **nextp) + { + char *ret; + + if (str == NULL) + { + str = *nextp; + } + + str += strspn(str, delim); + + if (*str == '\0') + { + return NULL; + } + + ret = str; + + str += strcspn(str, delim); + + if (*str) + { + *str++ = '\0'; + } + + *nextp = str; + + return ret; + } + + /*************************************************************************************************/ + static int strncasecmp(const char *s1, const char *s2, int n) + { + if (n == 0) + return 0; + + while (n-- != 0 && tolower(*s1) == tolower(*s2)) + { + if (n == 0 || *s1 == '\0' || *s2 == '\0') + break; + s1++; + s2++; + } + + return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); + } + + /*************************************************************************************************/ + static int strcasecmp(const char *s1, const char *s2) + { + register const unsigned char *p1 = (const unsigned char *) s1; + register const unsigned char *p2 = (const unsigned char *) s2; + unsigned char c1, c2; + + if (p1 == p2) + return 0; + + do + { + c1 = tolower (*p1); + c2 = tolower (*p2); + + if (c1 == '\0') + break; + + ++p1; + ++p2; + } + while (c1 == c2); + + if (UCHAR_MAX <= INT_MAX) + return c1 - c2; + else + /* On machines where 'char' and 'int' are types of the same size, the + difference of two 'unsigned char' values - including the sign bit - + doesn't fit in an 'int'. */ + return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); + } +}; +