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
StringUtil.h
00001 /** 00002 * ACKme WiConnect Host Library is licensed under the BSD licence: 00003 * 00004 * Copyright (c)2014 ACKme Networks. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without modification, 00008 * are permitted provided that the following conditions are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright notice, 00011 * this list of conditions and the following disclaimer. 00012 * 2. Redistributions in binary form must reproduce the above copyright notice, 00013 * this list of conditions and the following disclaimer in the documentation 00014 * and/or other materials provided with the distribution. 00015 * 3. The name of the author may not be used to endorse or promote products 00016 * derived from this software without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED 00019 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00020 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00021 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00022 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00023 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00026 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00027 * OF SUCH DAMAGE. 00028 */ 00029 #pragma once 00030 00031 00032 #include <string.h> 00033 #include <ctype.h> 00034 #include <stdint.h> 00035 #include <limits.h> 00036 00037 00038 #ifdef WICONNECT_USE_STRTOLL 00039 // Necessary to get strtoll in C99 mode. 00040 // http://sourceware.org/ml/newlib/2012/msg00425.html 00041 extern long long strtoll(const char *__n, char **__end_PTR, int __base); 00042 #endif 00043 00044 00045 class StringUtil 00046 { 00047 00048 public: 00049 /*************************************************************************************************/ 00050 // Helper to find an occurrence of a delimiter string, 00051 // insert '\0' in its place and return string after 00052 // the delimiter e.g. 00053 // if char s[] = "foo://bar"; 00054 // - strchop(s, "://") returns "bar" 00055 // - s becomes "foo" 00056 static char *chop(char *haystack, const char *needle) 00057 { 00058 if (!haystack) 00059 { 00060 return NULL; 00061 } 00062 char *end = strstr(haystack, needle); 00063 if (end) 00064 { 00065 *end = '\0'; 00066 return end + strlen(needle); 00067 } 00068 return NULL; 00069 } 00070 00071 /*************************************************************************************************/ 00072 // Check if string is non-null and non-empty. 00073 static bool empty(const char *s) 00074 { 00075 return !(s && *s); 00076 } 00077 00078 /*************************************************************************************************/ 00079 static bool isSpace(const char *s) 00080 { 00081 while(*s != 0) 00082 { 00083 if(!isspace((uint8_t)*s++)) 00084 return false; 00085 } 00086 return true; 00087 } 00088 00089 /*************************************************************************************************/ 00090 // Convert null-terminated string to lower case. 00091 // ASCII charset only. 00092 static void toLower(char *s) 00093 { 00094 for (; *s; ++s) 00095 { 00096 *s = tolower((int) * s); 00097 } 00098 } 00099 00100 /*************************************************************************************************/ 00101 // Combination of strip left + right. 00102 static char *strip(char *s, const char *chars) 00103 { 00104 return rightStrip(leftStrip(s, chars), chars); 00105 } 00106 00107 /*************************************************************************************************/ 00108 // Strip string from the left. 00109 // Returns pointer into the input string. 00110 static char *leftStrip(char *s, const char *chars) 00111 { 00112 return s + strspn(s, chars); 00113 } 00114 00115 /*************************************************************************************************/ 00116 // Strip string from the right. 00117 // Modified in place. 00118 static char *rightStrip(char *s, const char *chars) 00119 { 00120 char *end = s + strlen(s) - 1; 00121 while (end > s && strstr(chars, end)) 00122 { 00123 *end-- = '\0'; 00124 } 00125 return s; 00126 } 00127 00128 /*************************************************************************************************/ 00129 // Parse decimal integer and check if it's in bounds [min, max]. 00130 static bool parseInt(const char *s, intmax_t *result, intmax_t min, intmax_t max) 00131 { 00132 return parseBase(s, result, min, max, 10); 00133 } 00134 00135 // Parse hexadecimal integer and check if it's in bounds [min, max]. 00136 static bool parseHex(const char *s, intmax_t *result, intmax_t min, intmax_t max) 00137 { 00138 return parseBase(s, result, min, max, 16); 00139 } 00140 00141 /*************************************************************************************************/ 00142 static bool parseBase(const char *s, intmax_t *result, intmax_t min, intmax_t max, int base) 00143 { 00144 if (!s) 00145 { 00146 return false; 00147 } 00148 char *end; 00149 #ifdef WICONNECT_USE_STRTOLL 00150 intmax_t value = strtoll(s, &end, base); 00151 #else 00152 intmax_t value = strtol(s, &end, base); 00153 #endif 00154 if (*end || value < min || value > max) 00155 { 00156 return false; 00157 } 00158 *result = value; 00159 return true; 00160 } 00161 00162 /*************************************************************************************************/ 00163 // Parse an long long integer. 00164 static bool parseBool(const char *onoff, bool *var) 00165 { 00166 const char* const on_vals[] = 00167 { 00168 "1", 00169 "on", 00170 "true", 00171 "yes", 00172 }; 00173 00174 for(uint8_t i = 0; i < ARRAY_COUNT(on_vals); ++i) 00175 { 00176 if(strcasecmp(on_vals[i], onoff) == 0) 00177 { 00178 *var = true; 00179 return true; 00180 } 00181 } 00182 00183 const char* const off_vals[] = 00184 { 00185 "0", 00186 "false", 00187 "no", 00188 "off", 00189 NULL 00190 }; 00191 for(uint8_t i = 0; i < ARRAY_COUNT(off_vals); ++i) 00192 { 00193 if(strcasecmp(off_vals[i], onoff) == 0) 00194 { 00195 *var = false; 00196 return true; 00197 } 00198 } 00199 00200 return false; 00201 } 00202 00203 /*************************************************************************************************/ 00204 // convert binary data to hex string 00205 static void binToHex(char *dst, int max_dst, const void *data, int data_len) 00206 { 00207 char *end = dst + max_dst - 1; 00208 for (int i = 0; i < data_len; ++i) 00209 { 00210 if (dst < end) 00211 { 00212 dst += sprintf(dst, "%2.2x", ((uint8_t *)data)[i]); 00213 } 00214 } 00215 } 00216 00217 00218 /*************************************************************************************************/ 00219 // Parse binary data into hex string 00220 // the input buffer MUST be len*2 long 00221 // as the parsing is destructive and done in-place 00222 static void binToHex(void *h, int len) 00223 { 00224 char *dst = (char*)h; 00225 char *src= (char*)h+len; 00226 00227 memmove(src, dst, len); 00228 00229 while(len--) 00230 { 00231 sprintf(dst, "%2.2X", (unsigned int)(*src & 0xff)); 00232 dst += 2; 00233 ++src; 00234 } 00235 } 00236 00237 00238 /*************************************************************************************************/ 00239 // Parses hex representation of binary data destructively. 00240 // Returns number of bytes parsed or -1 on error. 00241 static int hexToBin(char *s) 00242 { 00243 int len, i, j; 00244 len = strlen(s); 00245 if (len % 2) 00246 { 00247 return -1; 00248 } 00249 for (i = j = 0; i < len; i += 2, j++) 00250 { 00251 const int num = hexToInt(&s[i]); 00252 if(num == -1) 00253 return -1; 00254 s[j] = (char)num; 00255 } 00256 return j; 00257 } 00258 00259 /*************************************************************************************************/ 00260 // hex string to integer, returns -1 on error 00261 static int hexToInt(const char *hex_str) 00262 { 00263 int hi = hexToNibble(*hex_str); 00264 int lo = hexToNibble(*(hex_str+1)); 00265 if (hi == -1 || lo == -1) 00266 { 00267 return -1; 00268 } 00269 return (hi << 4) | lo; 00270 } 00271 00272 /*************************************************************************************************/ 00273 static int hexToNibble(char c) 00274 { 00275 if (c >= '0' && c <= '9') 00276 { 00277 return c - '0'; 00278 } 00279 if (c >= 'a' && c <= 'f') 00280 { 00281 return 10 + (c - 'a'); 00282 } 00283 if (c >= 'A' && c <= 'F') 00284 { 00285 return 10 + (c - 'A'); 00286 } 00287 return -1; 00288 } 00289 00290 /*************************************************************************************************/ 00291 static const char* uint32ToStr(char* intStrBuffer, int integer) 00292 { 00293 sprintf(intStrBuffer, "%u", integer); 00294 return intStrBuffer; 00295 } 00296 00297 /*************************************************************************************************/ 00298 static const char* hexToStr(char* intStrBuffer, uint32_t hexInteger) 00299 { 00300 sprintf(intStrBuffer, "%X", hexInteger); 00301 return intStrBuffer; 00302 } 00303 00304 /*************************************************************************************************/ 00305 static bool strToUint32(const char *str, uint32_t *uint32Ptr) 00306 { 00307 intmax_t r; 00308 bool result = (str[0] == '0' && str[1] == 'x') ? StringUtil::parseHex(&str[2], &r, 0, UINT_MAX): StringUtil::parseInt(str, &r, 0, UINT_MAX); 00309 *uint32Ptr = (uint32_t)r; 00310 return result; 00311 } 00312 00313 00314 /*************************************************************************************************/ 00315 static bool strToUint16(const char *str, uint16_t *uint16Ptr) 00316 { 00317 intmax_t r; 00318 bool result = StringUtil::parseInt(str, &r, 0, USHRT_MAX); 00319 *uint16Ptr = (uint16_t)r; 00320 return result; 00321 } 00322 00323 /*************************************************************************************************/ 00324 static bool strToUint8(const char *str, uint8_t *uint8Ptr) 00325 { 00326 intmax_t r; 00327 bool result = StringUtil::parseInt(str, &r, 0, UCHAR_MAX); 00328 *uint8Ptr = (uint8_t)r; 00329 return result; 00330 } 00331 00332 /*************************************************************************************************/ 00333 static bool strToInt32(const char *str, int32_t *int32Ptr) 00334 { 00335 intmax_t r; 00336 bool result = StringUtil::parseInt(str, &r, INT_MIN, INT_MAX); 00337 *int32Ptr = (int32_t)r; 00338 return result; 00339 } 00340 00341 /*************************************************************************************************/ 00342 // uint32 hex string to uint32 00343 static bool strHexToUint32(const char *strHex, uint32_t *uint32Ptr) 00344 { 00345 intmax_t r; 00346 bool result = StringUtil::parseHex(strHex, &r, 0, UINT_MAX); 00347 *uint32Ptr = (uint32_t)r; 00348 return result; 00349 } 00350 00351 /*************************************************************************************************/ 00352 static char *strtok_r(char *str, const char *delim, char **nextp) 00353 { 00354 char *ret; 00355 00356 if (str == NULL) 00357 { 00358 str = *nextp; 00359 } 00360 00361 str += strspn(str, delim); 00362 00363 if (*str == '\0') 00364 { 00365 return NULL; 00366 } 00367 00368 ret = str; 00369 00370 str += strcspn(str, delim); 00371 00372 if (*str) 00373 { 00374 *str++ = '\0'; 00375 } 00376 00377 *nextp = str; 00378 00379 return ret; 00380 } 00381 00382 /*************************************************************************************************/ 00383 static int strncasecmp(const char *s1, const char *s2, int n) 00384 { 00385 if (n == 0) 00386 return 0; 00387 00388 while (n-- != 0 && tolower(*s1) == tolower(*s2)) 00389 { 00390 if (n == 0 || *s1 == '\0' || *s2 == '\0') 00391 break; 00392 s1++; 00393 s2++; 00394 } 00395 00396 return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); 00397 } 00398 00399 /*************************************************************************************************/ 00400 static int strcasecmp(const char *s1, const char *s2) 00401 { 00402 register const unsigned char *p1 = (const unsigned char *) s1; 00403 register const unsigned char *p2 = (const unsigned char *) s2; 00404 unsigned char c1, c2; 00405 00406 if (p1 == p2) 00407 return 0; 00408 00409 do 00410 { 00411 c1 = tolower (*p1); 00412 c2 = tolower (*p2); 00413 00414 if (c1 == '\0') 00415 break; 00416 00417 ++p1; 00418 ++p2; 00419 } 00420 while (c1 == c2); 00421 00422 if (UCHAR_MAX <= INT_MAX) 00423 return c1 - c2; 00424 else 00425 /* On machines where 'char' and 'int' are types of the same size, the 00426 difference of two 'unsigned char' values - including the sign bit - 00427 doesn't fit in an 'int'. */ 00428 return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); 00429 } 00430 };
Generated on Tue Jul 12 2022 17:35:58 by 1.7.2