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@22:2d7ef60a9f2a, 2014-08-26 (annotated)
- Committer:
- dan_ackme
- Date:
- Tue Aug 26 16:53:06 2014 -0700
- Revision:
- 22:2d7ef60a9f2a
- Parent:
- 21:17bb3eddcbae
- Child:
- 24:e27e23297f02
- Child:
- 26:8067e3d463d3
fixed build error
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dan_ackme | 21:17bb3eddcbae | 1 | /** |
dan_ackme | 21:17bb3eddcbae | 2 | * ACKme WiConnect Host Library is licensed under the BSD licence: |
dan_ackme | 21:17bb3eddcbae | 3 | * |
dan_ackme | 21:17bb3eddcbae | 4 | * Copyright (c)2014 ACKme Networks. |
dan_ackme | 21:17bb3eddcbae | 5 | * All rights reserved. |
dan_ackme | 21:17bb3eddcbae | 6 | * |
dan_ackme | 21:17bb3eddcbae | 7 | * Redistribution and use in source and binary forms, with or without modification, |
dan_ackme | 21:17bb3eddcbae | 8 | * are permitted provided that the following conditions are met: |
dan_ackme | 21:17bb3eddcbae | 9 | * |
dan_ackme | 21:17bb3eddcbae | 10 | * 1. Redistributions of source code must retain the above copyright notice, |
dan_ackme | 21:17bb3eddcbae | 11 | * this list of conditions and the following disclaimer. |
dan_ackme | 21:17bb3eddcbae | 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
dan_ackme | 21:17bb3eddcbae | 13 | * this list of conditions and the following disclaimer in the documentation |
dan_ackme | 21:17bb3eddcbae | 14 | * and/or other materials provided with the distribution. |
dan_ackme | 21:17bb3eddcbae | 15 | * 3. The name of the author may not be used to endorse or promote products |
dan_ackme | 21:17bb3eddcbae | 16 | * derived from this software without specific prior written permission. |
dan_ackme | 21:17bb3eddcbae | 17 | * |
dan_ackme | 21:17bb3eddcbae | 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED |
dan_ackme | 21:17bb3eddcbae | 19 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
dan_ackme | 21:17bb3eddcbae | 20 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
dan_ackme | 21:17bb3eddcbae | 21 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
dan_ackme | 21:17bb3eddcbae | 22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
dan_ackme | 21:17bb3eddcbae | 23 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
dan_ackme | 21:17bb3eddcbae | 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
dan_ackme | 21:17bb3eddcbae | 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
dan_ackme | 21:17bb3eddcbae | 26 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
dan_ackme | 21:17bb3eddcbae | 27 | * OF SUCH DAMAGE. |
dan_ackme | 0:ea85c4bb5e1f | 28 | */ |
dan_ackme | 0:ea85c4bb5e1f | 29 | #pragma once |
dan_ackme | 0:ea85c4bb5e1f | 30 | |
dan_ackme | 0:ea85c4bb5e1f | 31 | |
dan_ackme | 0:ea85c4bb5e1f | 32 | #include <string.h> |
dan_ackme | 0:ea85c4bb5e1f | 33 | #include <ctype.h> |
dan_ackme | 0:ea85c4bb5e1f | 34 | #include <stdint.h> |
dan_ackme | 0:ea85c4bb5e1f | 35 | #include <limits.h> |
dan_ackme | 0:ea85c4bb5e1f | 36 | |
dan_ackme | 0:ea85c4bb5e1f | 37 | |
dan_ackme | 0:ea85c4bb5e1f | 38 | #ifdef WICONNECT_USE_STRTOLL |
dan_ackme | 0:ea85c4bb5e1f | 39 | // Necessary to get strtoll in C99 mode. |
dan_ackme | 0:ea85c4bb5e1f | 40 | // http://sourceware.org/ml/newlib/2012/msg00425.html |
dan_ackme | 0:ea85c4bb5e1f | 41 | extern long long strtoll(const char *__n, char **__end_PTR, int __base); |
dan_ackme | 0:ea85c4bb5e1f | 42 | #endif |
dan_ackme | 0:ea85c4bb5e1f | 43 | |
dan_ackme | 0:ea85c4bb5e1f | 44 | |
dan_ackme | 0:ea85c4bb5e1f | 45 | class StringUtil |
dan_ackme | 0:ea85c4bb5e1f | 46 | { |
dan_ackme | 0:ea85c4bb5e1f | 47 | |
dan_ackme | 0:ea85c4bb5e1f | 48 | public: |
dan_ackme | 0:ea85c4bb5e1f | 49 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 50 | // Helper to find an occurrence of a delimiter string, |
dan_ackme | 0:ea85c4bb5e1f | 51 | // insert '\0' in its place and return string after |
dan_ackme | 0:ea85c4bb5e1f | 52 | // the delimiter e.g. |
dan_ackme | 0:ea85c4bb5e1f | 53 | // if char s[] = "foo://bar"; |
dan_ackme | 0:ea85c4bb5e1f | 54 | // - strchop(s, "://") returns "bar" |
dan_ackme | 0:ea85c4bb5e1f | 55 | // - s becomes "foo" |
dan_ackme | 0:ea85c4bb5e1f | 56 | static char *chop(char *haystack, const char *needle) |
dan_ackme | 0:ea85c4bb5e1f | 57 | { |
dan_ackme | 0:ea85c4bb5e1f | 58 | if (!haystack) |
dan_ackme | 0:ea85c4bb5e1f | 59 | { |
dan_ackme | 0:ea85c4bb5e1f | 60 | return NULL; |
dan_ackme | 0:ea85c4bb5e1f | 61 | } |
dan_ackme | 0:ea85c4bb5e1f | 62 | char *end = strstr(haystack, needle); |
dan_ackme | 0:ea85c4bb5e1f | 63 | if (end) |
dan_ackme | 0:ea85c4bb5e1f | 64 | { |
dan_ackme | 0:ea85c4bb5e1f | 65 | *end = '\0'; |
dan_ackme | 0:ea85c4bb5e1f | 66 | return end + strlen(needle); |
dan_ackme | 0:ea85c4bb5e1f | 67 | } |
dan_ackme | 0:ea85c4bb5e1f | 68 | return NULL; |
dan_ackme | 0:ea85c4bb5e1f | 69 | } |
dan_ackme | 0:ea85c4bb5e1f | 70 | |
dan_ackme | 0:ea85c4bb5e1f | 71 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 72 | // Check if string is non-null and non-empty. |
dan_ackme | 0:ea85c4bb5e1f | 73 | static bool empty(const char *s) |
dan_ackme | 0:ea85c4bb5e1f | 74 | { |
dan_ackme | 0:ea85c4bb5e1f | 75 | return !(s && *s); |
dan_ackme | 0:ea85c4bb5e1f | 76 | } |
dan_ackme | 0:ea85c4bb5e1f | 77 | |
dan_ackme | 0:ea85c4bb5e1f | 78 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 79 | static bool isSpace(const char *s) |
dan_ackme | 0:ea85c4bb5e1f | 80 | { |
dan_ackme | 0:ea85c4bb5e1f | 81 | while(*s != 0) |
dan_ackme | 0:ea85c4bb5e1f | 82 | { |
dan_ackme | 0:ea85c4bb5e1f | 83 | if(!isspace((uint8_t)*s++)) |
dan_ackme | 0:ea85c4bb5e1f | 84 | return false; |
dan_ackme | 0:ea85c4bb5e1f | 85 | } |
dan_ackme | 0:ea85c4bb5e1f | 86 | return true; |
dan_ackme | 0:ea85c4bb5e1f | 87 | } |
dan_ackme | 0:ea85c4bb5e1f | 88 | |
dan_ackme | 0:ea85c4bb5e1f | 89 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 90 | // Convert null-terminated string to lower case. |
dan_ackme | 0:ea85c4bb5e1f | 91 | // ASCII charset only. |
dan_ackme | 0:ea85c4bb5e1f | 92 | static void toLower(char *s) |
dan_ackme | 0:ea85c4bb5e1f | 93 | { |
dan_ackme | 0:ea85c4bb5e1f | 94 | for (; *s; ++s) |
dan_ackme | 0:ea85c4bb5e1f | 95 | { |
dan_ackme | 0:ea85c4bb5e1f | 96 | *s = tolower((int) * s); |
dan_ackme | 0:ea85c4bb5e1f | 97 | } |
dan_ackme | 0:ea85c4bb5e1f | 98 | } |
dan_ackme | 0:ea85c4bb5e1f | 99 | |
dan_ackme | 0:ea85c4bb5e1f | 100 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 101 | // Combination of strip left + right. |
dan_ackme | 0:ea85c4bb5e1f | 102 | static char *strip(char *s, const char *chars) |
dan_ackme | 0:ea85c4bb5e1f | 103 | { |
dan_ackme | 0:ea85c4bb5e1f | 104 | return rightStrip(leftStrip(s, chars), chars); |
dan_ackme | 0:ea85c4bb5e1f | 105 | } |
dan_ackme | 0:ea85c4bb5e1f | 106 | |
dan_ackme | 0:ea85c4bb5e1f | 107 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 108 | // Strip string from the left. |
dan_ackme | 0:ea85c4bb5e1f | 109 | // Returns pointer into the input string. |
dan_ackme | 0:ea85c4bb5e1f | 110 | static char *leftStrip(char *s, const char *chars) |
dan_ackme | 0:ea85c4bb5e1f | 111 | { |
dan_ackme | 0:ea85c4bb5e1f | 112 | return s + strspn(s, chars); |
dan_ackme | 0:ea85c4bb5e1f | 113 | } |
dan_ackme | 0:ea85c4bb5e1f | 114 | |
dan_ackme | 0:ea85c4bb5e1f | 115 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 116 | // Strip string from the right. |
dan_ackme | 0:ea85c4bb5e1f | 117 | // Modified in place. |
dan_ackme | 0:ea85c4bb5e1f | 118 | static char *rightStrip(char *s, const char *chars) |
dan_ackme | 0:ea85c4bb5e1f | 119 | { |
dan_ackme | 0:ea85c4bb5e1f | 120 | char *end = s + strlen(s) - 1; |
dan_ackme | 0:ea85c4bb5e1f | 121 | while (end > s && strstr(chars, end)) |
dan_ackme | 0:ea85c4bb5e1f | 122 | { |
dan_ackme | 0:ea85c4bb5e1f | 123 | *end-- = '\0'; |
dan_ackme | 0:ea85c4bb5e1f | 124 | } |
dan_ackme | 0:ea85c4bb5e1f | 125 | return s; |
dan_ackme | 0:ea85c4bb5e1f | 126 | } |
dan_ackme | 0:ea85c4bb5e1f | 127 | |
dan_ackme | 0:ea85c4bb5e1f | 128 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 129 | // Parse decimal integer and check if it's in bounds [min, max]. |
dan_ackme | 0:ea85c4bb5e1f | 130 | static bool parseInt(const char *s, intmax_t *result, intmax_t min, intmax_t max) |
dan_ackme | 0:ea85c4bb5e1f | 131 | { |
dan_ackme | 0:ea85c4bb5e1f | 132 | return parseBase(s, result, min, max, 10); |
dan_ackme | 0:ea85c4bb5e1f | 133 | } |
dan_ackme | 0:ea85c4bb5e1f | 134 | |
dan_ackme | 0:ea85c4bb5e1f | 135 | // Parse hexadecimal integer and check if it's in bounds [min, max]. |
dan_ackme | 0:ea85c4bb5e1f | 136 | static bool parseHex(const char *s, intmax_t *result, intmax_t min, intmax_t max) |
dan_ackme | 0:ea85c4bb5e1f | 137 | { |
dan_ackme | 0:ea85c4bb5e1f | 138 | return parseBase(s, result, min, max, 16); |
dan_ackme | 0:ea85c4bb5e1f | 139 | } |
dan_ackme | 0:ea85c4bb5e1f | 140 | |
dan_ackme | 0:ea85c4bb5e1f | 141 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 142 | static bool parseBase(const char *s, intmax_t *result, intmax_t min, intmax_t max, int base) |
dan_ackme | 0:ea85c4bb5e1f | 143 | { |
dan_ackme | 0:ea85c4bb5e1f | 144 | if (!s) |
dan_ackme | 0:ea85c4bb5e1f | 145 | { |
dan_ackme | 0:ea85c4bb5e1f | 146 | return false; |
dan_ackme | 0:ea85c4bb5e1f | 147 | } |
dan_ackme | 0:ea85c4bb5e1f | 148 | char *end; |
dan_ackme | 0:ea85c4bb5e1f | 149 | #ifdef WICONNECT_USE_STRTOLL |
dan_ackme | 0:ea85c4bb5e1f | 150 | intmax_t value = strtoll(s, &end, base); |
dan_ackme | 0:ea85c4bb5e1f | 151 | #else |
dan_ackme | 0:ea85c4bb5e1f | 152 | intmax_t value = strtol(s, &end, base); |
dan_ackme | 0:ea85c4bb5e1f | 153 | #endif |
dan_ackme | 0:ea85c4bb5e1f | 154 | if (*end || value < min || value > max) |
dan_ackme | 0:ea85c4bb5e1f | 155 | { |
dan_ackme | 0:ea85c4bb5e1f | 156 | return false; |
dan_ackme | 0:ea85c4bb5e1f | 157 | } |
dan_ackme | 0:ea85c4bb5e1f | 158 | *result = value; |
dan_ackme | 0:ea85c4bb5e1f | 159 | return true; |
dan_ackme | 0:ea85c4bb5e1f | 160 | } |
dan_ackme | 0:ea85c4bb5e1f | 161 | |
dan_ackme | 0:ea85c4bb5e1f | 162 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 163 | // Parse an long long integer. |
dan_ackme | 0:ea85c4bb5e1f | 164 | static bool parseBool(const char *onoff, bool *var) |
dan_ackme | 0:ea85c4bb5e1f | 165 | { |
dan_ackme | 0:ea85c4bb5e1f | 166 | const char* const on_vals[] = |
dan_ackme | 0:ea85c4bb5e1f | 167 | { |
dan_ackme | 0:ea85c4bb5e1f | 168 | "1", |
dan_ackme | 0:ea85c4bb5e1f | 169 | "on", |
dan_ackme | 0:ea85c4bb5e1f | 170 | "true", |
dan_ackme | 0:ea85c4bb5e1f | 171 | "yes", |
dan_ackme | 0:ea85c4bb5e1f | 172 | }; |
dan_ackme | 0:ea85c4bb5e1f | 173 | |
dan_ackme | 0:ea85c4bb5e1f | 174 | for(uint8_t i = 0; i < ARRAY_COUNT(on_vals); ++i) |
dan_ackme | 0:ea85c4bb5e1f | 175 | { |
dan_ackme | 0:ea85c4bb5e1f | 176 | if(strcasecmp(on_vals[i], onoff) == 0) |
dan_ackme | 0:ea85c4bb5e1f | 177 | { |
dan_ackme | 0:ea85c4bb5e1f | 178 | *var = true; |
dan_ackme | 0:ea85c4bb5e1f | 179 | return true; |
dan_ackme | 0:ea85c4bb5e1f | 180 | } |
dan_ackme | 0:ea85c4bb5e1f | 181 | } |
dan_ackme | 0:ea85c4bb5e1f | 182 | |
dan_ackme | 0:ea85c4bb5e1f | 183 | const char* const off_vals[] = |
dan_ackme | 0:ea85c4bb5e1f | 184 | { |
dan_ackme | 0:ea85c4bb5e1f | 185 | "0", |
dan_ackme | 0:ea85c4bb5e1f | 186 | "false", |
dan_ackme | 0:ea85c4bb5e1f | 187 | "no", |
dan_ackme | 0:ea85c4bb5e1f | 188 | "off", |
dan_ackme | 0:ea85c4bb5e1f | 189 | NULL |
dan_ackme | 0:ea85c4bb5e1f | 190 | }; |
dan_ackme | 0:ea85c4bb5e1f | 191 | for(uint8_t i = 0; i < ARRAY_COUNT(off_vals); ++i) |
dan_ackme | 0:ea85c4bb5e1f | 192 | { |
dan_ackme | 0:ea85c4bb5e1f | 193 | if(strcasecmp(off_vals[i], onoff) == 0) |
dan_ackme | 0:ea85c4bb5e1f | 194 | { |
dan_ackme | 0:ea85c4bb5e1f | 195 | *var = false; |
dan_ackme | 0:ea85c4bb5e1f | 196 | return true; |
dan_ackme | 0:ea85c4bb5e1f | 197 | } |
dan_ackme | 0:ea85c4bb5e1f | 198 | } |
dan_ackme | 0:ea85c4bb5e1f | 199 | |
dan_ackme | 0:ea85c4bb5e1f | 200 | return false; |
dan_ackme | 0:ea85c4bb5e1f | 201 | } |
dan_ackme | 0:ea85c4bb5e1f | 202 | |
dan_ackme | 0:ea85c4bb5e1f | 203 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 204 | // convert binary data to hex string |
dan_ackme | 0:ea85c4bb5e1f | 205 | static void binToHex(char *dst, int max_dst, const void *data, int data_len) |
dan_ackme | 0:ea85c4bb5e1f | 206 | { |
dan_ackme | 0:ea85c4bb5e1f | 207 | char *end = dst + max_dst - 1; |
dan_ackme | 0:ea85c4bb5e1f | 208 | for (int i = 0; i < data_len; ++i) |
dan_ackme | 0:ea85c4bb5e1f | 209 | { |
dan_ackme | 0:ea85c4bb5e1f | 210 | if (dst < end) |
dan_ackme | 0:ea85c4bb5e1f | 211 | { |
dan_ackme | 0:ea85c4bb5e1f | 212 | dst += sprintf(dst, "%2.2x", ((uint8_t *)data)[i]); |
dan_ackme | 0:ea85c4bb5e1f | 213 | } |
dan_ackme | 0:ea85c4bb5e1f | 214 | } |
dan_ackme | 0:ea85c4bb5e1f | 215 | } |
dan_ackme | 0:ea85c4bb5e1f | 216 | |
dan_ackme | 0:ea85c4bb5e1f | 217 | |
dan_ackme | 0:ea85c4bb5e1f | 218 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 219 | // Parse binary data into hex string |
dan_ackme | 0:ea85c4bb5e1f | 220 | // the input buffer MUST be len*2 long |
dan_ackme | 0:ea85c4bb5e1f | 221 | // as the parsing is destructive and done in-place |
dan_ackme | 0:ea85c4bb5e1f | 222 | static void binToHex(void *h, int len) |
dan_ackme | 0:ea85c4bb5e1f | 223 | { |
dan_ackme | 0:ea85c4bb5e1f | 224 | char *dst = (char*)h; |
dan_ackme | 0:ea85c4bb5e1f | 225 | char *src= (char*)h+len; |
dan_ackme | 0:ea85c4bb5e1f | 226 | |
dan_ackme | 0:ea85c4bb5e1f | 227 | memmove(src, dst, len); |
dan_ackme | 0:ea85c4bb5e1f | 228 | |
dan_ackme | 0:ea85c4bb5e1f | 229 | while(len--) |
dan_ackme | 0:ea85c4bb5e1f | 230 | { |
dan_ackme | 0:ea85c4bb5e1f | 231 | sprintf(dst, "%2.2X", (unsigned int)(*src & 0xff)); |
dan_ackme | 0:ea85c4bb5e1f | 232 | dst += 2; |
dan_ackme | 0:ea85c4bb5e1f | 233 | ++src; |
dan_ackme | 0:ea85c4bb5e1f | 234 | } |
dan_ackme | 0:ea85c4bb5e1f | 235 | } |
dan_ackme | 0:ea85c4bb5e1f | 236 | |
dan_ackme | 0:ea85c4bb5e1f | 237 | |
dan_ackme | 0:ea85c4bb5e1f | 238 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 239 | // Parses hex representation of binary data destructively. |
dan_ackme | 0:ea85c4bb5e1f | 240 | // Returns number of bytes parsed or -1 on error. |
dan_ackme | 0:ea85c4bb5e1f | 241 | static int hexToBin(char *s) |
dan_ackme | 0:ea85c4bb5e1f | 242 | { |
dan_ackme | 0:ea85c4bb5e1f | 243 | int len, i, j; |
dan_ackme | 0:ea85c4bb5e1f | 244 | len = strlen(s); |
dan_ackme | 0:ea85c4bb5e1f | 245 | if (len % 2) |
dan_ackme | 0:ea85c4bb5e1f | 246 | { |
dan_ackme | 0:ea85c4bb5e1f | 247 | return -1; |
dan_ackme | 0:ea85c4bb5e1f | 248 | } |
dan_ackme | 0:ea85c4bb5e1f | 249 | for (i = j = 0; i < len; i += 2, j++) |
dan_ackme | 0:ea85c4bb5e1f | 250 | { |
dan_ackme | 0:ea85c4bb5e1f | 251 | const int num = hexToInt(&s[i]); |
dan_ackme | 0:ea85c4bb5e1f | 252 | if(num == -1) |
dan_ackme | 0:ea85c4bb5e1f | 253 | return -1; |
dan_ackme | 0:ea85c4bb5e1f | 254 | s[j] = (char)num; |
dan_ackme | 0:ea85c4bb5e1f | 255 | } |
dan_ackme | 0:ea85c4bb5e1f | 256 | return j; |
dan_ackme | 0:ea85c4bb5e1f | 257 | } |
dan_ackme | 0:ea85c4bb5e1f | 258 | |
dan_ackme | 0:ea85c4bb5e1f | 259 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 260 | // hex string to integer, returns -1 on error |
dan_ackme | 0:ea85c4bb5e1f | 261 | static int hexToInt(const char *hex_str) |
dan_ackme | 0:ea85c4bb5e1f | 262 | { |
dan_ackme | 0:ea85c4bb5e1f | 263 | int hi = hexToNibble(*hex_str); |
dan_ackme | 0:ea85c4bb5e1f | 264 | int lo = hexToNibble(*(hex_str+1)); |
dan_ackme | 0:ea85c4bb5e1f | 265 | if (hi == -1 || lo == -1) |
dan_ackme | 0:ea85c4bb5e1f | 266 | { |
dan_ackme | 0:ea85c4bb5e1f | 267 | return -1; |
dan_ackme | 0:ea85c4bb5e1f | 268 | } |
dan_ackme | 0:ea85c4bb5e1f | 269 | return (hi << 4) | lo; |
dan_ackme | 0:ea85c4bb5e1f | 270 | } |
dan_ackme | 0:ea85c4bb5e1f | 271 | |
dan_ackme | 0:ea85c4bb5e1f | 272 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 273 | static int hexToNibble(char c) |
dan_ackme | 0:ea85c4bb5e1f | 274 | { |
dan_ackme | 0:ea85c4bb5e1f | 275 | if (c >= '0' && c <= '9') |
dan_ackme | 0:ea85c4bb5e1f | 276 | { |
dan_ackme | 0:ea85c4bb5e1f | 277 | return c - '0'; |
dan_ackme | 0:ea85c4bb5e1f | 278 | } |
dan_ackme | 0:ea85c4bb5e1f | 279 | if (c >= 'a' && c <= 'f') |
dan_ackme | 0:ea85c4bb5e1f | 280 | { |
dan_ackme | 0:ea85c4bb5e1f | 281 | return 10 + (c - 'a'); |
dan_ackme | 0:ea85c4bb5e1f | 282 | } |
dan_ackme | 0:ea85c4bb5e1f | 283 | if (c >= 'A' && c <= 'F') |
dan_ackme | 0:ea85c4bb5e1f | 284 | { |
dan_ackme | 0:ea85c4bb5e1f | 285 | return 10 + (c - 'A'); |
dan_ackme | 0:ea85c4bb5e1f | 286 | } |
dan_ackme | 0:ea85c4bb5e1f | 287 | return -1; |
dan_ackme | 0:ea85c4bb5e1f | 288 | } |
dan_ackme | 0:ea85c4bb5e1f | 289 | |
dan_ackme | 0:ea85c4bb5e1f | 290 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 291 | static const char* uint32ToStr(char* intStrBuffer, int integer) |
dan_ackme | 0:ea85c4bb5e1f | 292 | { |
dan_ackme | 0:ea85c4bb5e1f | 293 | sprintf(intStrBuffer, "%u", integer); |
dan_ackme | 0:ea85c4bb5e1f | 294 | return intStrBuffer; |
dan_ackme | 0:ea85c4bb5e1f | 295 | } |
dan_ackme | 0:ea85c4bb5e1f | 296 | |
dan_ackme | 0:ea85c4bb5e1f | 297 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 298 | static bool strToUint32(const char *str, uint32_t *uint32Ptr) |
dan_ackme | 0:ea85c4bb5e1f | 299 | { |
dan_ackme | 0:ea85c4bb5e1f | 300 | intmax_t r; |
dan_ackme | 22:2d7ef60a9f2a | 301 | bool result = StringUtil::parseInt(str, &r, 0, UINT_MAX); |
dan_ackme | 0:ea85c4bb5e1f | 302 | *uint32Ptr = (uint32_t)r; |
dan_ackme | 0:ea85c4bb5e1f | 303 | return result; |
dan_ackme | 0:ea85c4bb5e1f | 304 | } |
dan_ackme | 0:ea85c4bb5e1f | 305 | |
dan_ackme | 0:ea85c4bb5e1f | 306 | /*************************************************************************************************/ |
dan_ackme | 21:17bb3eddcbae | 307 | static bool strToUint16(const char *str, uint16_t *uint16Ptr) |
dan_ackme | 21:17bb3eddcbae | 308 | { |
dan_ackme | 21:17bb3eddcbae | 309 | intmax_t r; |
dan_ackme | 22:2d7ef60a9f2a | 310 | bool result = StringUtil::parseInt(str, &r, 0, USHRT_MAX); |
dan_ackme | 21:17bb3eddcbae | 311 | *uint16Ptr = (uint16_t)r; |
dan_ackme | 21:17bb3eddcbae | 312 | return result; |
dan_ackme | 21:17bb3eddcbae | 313 | } |
dan_ackme | 21:17bb3eddcbae | 314 | |
dan_ackme | 21:17bb3eddcbae | 315 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 316 | static bool strToInt32(const char *str, int32_t *int32Ptr) |
dan_ackme | 0:ea85c4bb5e1f | 317 | { |
dan_ackme | 0:ea85c4bb5e1f | 318 | intmax_t r; |
dan_ackme | 22:2d7ef60a9f2a | 319 | bool result = StringUtil::parseInt(str, &r, INT_MIN, INT_MAX); |
dan_ackme | 0:ea85c4bb5e1f | 320 | *int32Ptr = (int32_t)r; |
dan_ackme | 0:ea85c4bb5e1f | 321 | return result; |
dan_ackme | 0:ea85c4bb5e1f | 322 | } |
dan_ackme | 0:ea85c4bb5e1f | 323 | |
dan_ackme | 0:ea85c4bb5e1f | 324 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 325 | // uint32 hex string to uint32 |
dan_ackme | 0:ea85c4bb5e1f | 326 | static bool strHexToUint32(const char *strHex, uint32_t *uint32Ptr) |
dan_ackme | 0:ea85c4bb5e1f | 327 | { |
dan_ackme | 0:ea85c4bb5e1f | 328 | intmax_t r; |
dan_ackme | 22:2d7ef60a9f2a | 329 | bool result = StringUtil::parseHex(strHex, &r, 0, UINT_MAX); |
dan_ackme | 0:ea85c4bb5e1f | 330 | *uint32Ptr = (uint32_t)r; |
dan_ackme | 0:ea85c4bb5e1f | 331 | return result; |
dan_ackme | 0:ea85c4bb5e1f | 332 | } |
dan_ackme | 0:ea85c4bb5e1f | 333 | |
dan_ackme | 0:ea85c4bb5e1f | 334 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 335 | static char *strtok_r(char *str, const char *delim, char **nextp) |
dan_ackme | 0:ea85c4bb5e1f | 336 | { |
dan_ackme | 0:ea85c4bb5e1f | 337 | char *ret; |
dan_ackme | 0:ea85c4bb5e1f | 338 | |
dan_ackme | 0:ea85c4bb5e1f | 339 | if (str == NULL) |
dan_ackme | 0:ea85c4bb5e1f | 340 | { |
dan_ackme | 0:ea85c4bb5e1f | 341 | str = *nextp; |
dan_ackme | 0:ea85c4bb5e1f | 342 | } |
dan_ackme | 0:ea85c4bb5e1f | 343 | |
dan_ackme | 0:ea85c4bb5e1f | 344 | str += strspn(str, delim); |
dan_ackme | 0:ea85c4bb5e1f | 345 | |
dan_ackme | 0:ea85c4bb5e1f | 346 | if (*str == '\0') |
dan_ackme | 0:ea85c4bb5e1f | 347 | { |
dan_ackme | 0:ea85c4bb5e1f | 348 | return NULL; |
dan_ackme | 0:ea85c4bb5e1f | 349 | } |
dan_ackme | 0:ea85c4bb5e1f | 350 | |
dan_ackme | 0:ea85c4bb5e1f | 351 | ret = str; |
dan_ackme | 0:ea85c4bb5e1f | 352 | |
dan_ackme | 0:ea85c4bb5e1f | 353 | str += strcspn(str, delim); |
dan_ackme | 0:ea85c4bb5e1f | 354 | |
dan_ackme | 0:ea85c4bb5e1f | 355 | if (*str) |
dan_ackme | 0:ea85c4bb5e1f | 356 | { |
dan_ackme | 0:ea85c4bb5e1f | 357 | *str++ = '\0'; |
dan_ackme | 0:ea85c4bb5e1f | 358 | } |
dan_ackme | 0:ea85c4bb5e1f | 359 | |
dan_ackme | 0:ea85c4bb5e1f | 360 | *nextp = str; |
dan_ackme | 0:ea85c4bb5e1f | 361 | |
dan_ackme | 0:ea85c4bb5e1f | 362 | return ret; |
dan_ackme | 0:ea85c4bb5e1f | 363 | } |
dan_ackme | 0:ea85c4bb5e1f | 364 | |
dan_ackme | 0:ea85c4bb5e1f | 365 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 366 | static int strncasecmp(const char *s1, const char *s2, int n) |
dan_ackme | 0:ea85c4bb5e1f | 367 | { |
dan_ackme | 0:ea85c4bb5e1f | 368 | if (n == 0) |
dan_ackme | 0:ea85c4bb5e1f | 369 | return 0; |
dan_ackme | 0:ea85c4bb5e1f | 370 | |
dan_ackme | 0:ea85c4bb5e1f | 371 | while (n-- != 0 && tolower(*s1) == tolower(*s2)) |
dan_ackme | 0:ea85c4bb5e1f | 372 | { |
dan_ackme | 0:ea85c4bb5e1f | 373 | if (n == 0 || *s1 == '\0' || *s2 == '\0') |
dan_ackme | 0:ea85c4bb5e1f | 374 | break; |
dan_ackme | 0:ea85c4bb5e1f | 375 | s1++; |
dan_ackme | 0:ea85c4bb5e1f | 376 | s2++; |
dan_ackme | 0:ea85c4bb5e1f | 377 | } |
dan_ackme | 0:ea85c4bb5e1f | 378 | |
dan_ackme | 0:ea85c4bb5e1f | 379 | return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); |
dan_ackme | 0:ea85c4bb5e1f | 380 | } |
dan_ackme | 0:ea85c4bb5e1f | 381 | |
dan_ackme | 0:ea85c4bb5e1f | 382 | /*************************************************************************************************/ |
dan_ackme | 0:ea85c4bb5e1f | 383 | static int strcasecmp(const char *s1, const char *s2) |
dan_ackme | 0:ea85c4bb5e1f | 384 | { |
dan_ackme | 0:ea85c4bb5e1f | 385 | register const unsigned char *p1 = (const unsigned char *) s1; |
dan_ackme | 0:ea85c4bb5e1f | 386 | register const unsigned char *p2 = (const unsigned char *) s2; |
dan_ackme | 0:ea85c4bb5e1f | 387 | unsigned char c1, c2; |
dan_ackme | 0:ea85c4bb5e1f | 388 | |
dan_ackme | 0:ea85c4bb5e1f | 389 | if (p1 == p2) |
dan_ackme | 0:ea85c4bb5e1f | 390 | return 0; |
dan_ackme | 0:ea85c4bb5e1f | 391 | |
dan_ackme | 0:ea85c4bb5e1f | 392 | do |
dan_ackme | 0:ea85c4bb5e1f | 393 | { |
dan_ackme | 0:ea85c4bb5e1f | 394 | c1 = tolower (*p1); |
dan_ackme | 0:ea85c4bb5e1f | 395 | c2 = tolower (*p2); |
dan_ackme | 0:ea85c4bb5e1f | 396 | |
dan_ackme | 0:ea85c4bb5e1f | 397 | if (c1 == '\0') |
dan_ackme | 0:ea85c4bb5e1f | 398 | break; |
dan_ackme | 0:ea85c4bb5e1f | 399 | |
dan_ackme | 0:ea85c4bb5e1f | 400 | ++p1; |
dan_ackme | 0:ea85c4bb5e1f | 401 | ++p2; |
dan_ackme | 0:ea85c4bb5e1f | 402 | } |
dan_ackme | 0:ea85c4bb5e1f | 403 | while (c1 == c2); |
dan_ackme | 0:ea85c4bb5e1f | 404 | |
dan_ackme | 0:ea85c4bb5e1f | 405 | if (UCHAR_MAX <= INT_MAX) |
dan_ackme | 0:ea85c4bb5e1f | 406 | return c1 - c2; |
dan_ackme | 0:ea85c4bb5e1f | 407 | else |
dan_ackme | 0:ea85c4bb5e1f | 408 | /* On machines where 'char' and 'int' are types of the same size, the |
dan_ackme | 0:ea85c4bb5e1f | 409 | difference of two 'unsigned char' values - including the sign bit - |
dan_ackme | 0:ea85c4bb5e1f | 410 | doesn't fit in an 'int'. */ |
dan_ackme | 0:ea85c4bb5e1f | 411 | return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); |
dan_ackme | 0:ea85c4bb5e1f | 412 | } |
dan_ackme | 0:ea85c4bb5e1f | 413 | }; |