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
api/StringUtil.h
- Committer:
- dan_ackme
- Date:
- 2014-11-26
- Revision:
- 34:2616445d0823
- Parent:
- 29:b6af04b77a56
File content as of revision 34:2616445d0823:
/** * ACKme WiConnect Host Library is licensed under the BSD licence: * * Copyright (c)2014 ACKme Networks. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ #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 const char* hexToStr(char* intStrBuffer, uint32_t hexInteger) { sprintf(intStrBuffer, "%X", hexInteger); return intStrBuffer; } /*************************************************************************************************/ static bool strToUint32(const char *str, uint32_t *uint32Ptr) { intmax_t r; bool result = (str[0] == '0' && str[1] == 'x') ? StringUtil::parseHex(&str[2], &r, 0, UINT_MAX): StringUtil::parseInt(str, &r, 0, UINT_MAX); *uint32Ptr = (uint32_t)r; return result; } /*************************************************************************************************/ static bool strToUint16(const char *str, uint16_t *uint16Ptr) { intmax_t r; bool result = StringUtil::parseInt(str, &r, 0, USHRT_MAX); *uint16Ptr = (uint16_t)r; return result; } /*************************************************************************************************/ static bool strToUint8(const char *str, uint8_t *uint8Ptr) { intmax_t r; bool result = StringUtil::parseInt(str, &r, 0, UCHAR_MAX); *uint8Ptr = (uint8_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); } };