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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers StringUtil.h Source File

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 };