ACKme Logo WiConnect Host Library- API Reference Guide
 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
StringUtil.h
1 
29 #pragma once
30 
31 
32 #include <string.h>
33 #include <ctype.h>
34 #include <stdint.h>
35 #include <limits.h>
36 
37 
38 #ifdef WICONNECT_USE_STRTOLL
39 // Necessary to get strtoll in C99 mode.
40 // http://sourceware.org/ml/newlib/2012/msg00425.html
41 extern long long strtoll(const char *__n, char **__end_PTR, int __base);
42 #endif
43 
44 
46 {
47 
48 public:
49  /*************************************************************************************************/
50  // Helper to find an occurrence of a delimiter string,
51  // insert '\0' in its place and return string after
52  // the delimiter e.g.
53  // if char s[] = "foo://bar";
54  // - strchop(s, "://") returns "bar"
55  // - s becomes "foo"
56  static char *chop(char *haystack, const char *needle)
57  {
58  if (!haystack)
59  {
60  return NULL;
61  }
62  char *end = strstr(haystack, needle);
63  if (end)
64  {
65  *end = '\0';
66  return end + strlen(needle);
67  }
68  return NULL;
69  }
70 
71  /*************************************************************************************************/
72  // Check if string is non-null and non-empty.
73  static bool empty(const char *s)
74  {
75  return !(s && *s);
76  }
77 
78  /*************************************************************************************************/
79  static bool isSpace(const char *s)
80  {
81  while(*s != 0)
82  {
83  if(!isspace((uint8_t)*s++))
84  return false;
85  }
86  return true;
87  }
88 
89  /*************************************************************************************************/
90  // Convert null-terminated string to lower case.
91  // ASCII charset only.
92  static void toLower(char *s)
93  {
94  for (; *s; ++s)
95  {
96  *s = tolower((int) * s);
97  }
98  }
99 
100  /*************************************************************************************************/
101  // Combination of strip left + right.
102  static char *strip(char *s, const char *chars)
103  {
104  return rightStrip(leftStrip(s, chars), chars);
105  }
106 
107  /*************************************************************************************************/
108  // Strip string from the left.
109  // Returns pointer into the input string.
110  static char *leftStrip(char *s, const char *chars)
111  {
112  return s + strspn(s, chars);
113  }
114 
115  /*************************************************************************************************/
116  // Strip string from the right.
117  // Modified in place.
118  static char *rightStrip(char *s, const char *chars)
119  {
120  char *end = s + strlen(s) - 1;
121  while (end > s && strstr(chars, end))
122  {
123  *end-- = '\0';
124  }
125  return s;
126  }
127 
128  /*************************************************************************************************/
129  // Parse decimal integer and check if it's in bounds [min, max].
130  static bool parseInt(const char *s, intmax_t *result, intmax_t min, intmax_t max)
131  {
132  return parseBase(s, result, min, max, 10);
133  }
134 
135  // Parse hexadecimal integer and check if it's in bounds [min, max].
136  static bool parseHex(const char *s, intmax_t *result, intmax_t min, intmax_t max)
137  {
138  return parseBase(s, result, min, max, 16);
139  }
140 
141  /*************************************************************************************************/
142  static bool parseBase(const char *s, intmax_t *result, intmax_t min, intmax_t max, int base)
143  {
144  if (!s)
145  {
146  return false;
147  }
148  char *end;
149 #ifdef WICONNECT_USE_STRTOLL
150  intmax_t value = strtoll(s, &end, base);
151 #else
152  intmax_t value = strtol(s, &end, base);
153 #endif
154  if (*end || value < min || value > max)
155  {
156  return false;
157  }
158  *result = value;
159  return true;
160  }
161 
162  /*************************************************************************************************/
163  // Parse an long long integer.
164  static bool parseBool(const char *onoff, bool *var)
165  {
166  const char* const on_vals[] =
167  {
168  "1",
169  "on",
170  "true",
171  "yes",
172  };
173 
174  for(uint8_t i = 0; i < ARRAY_COUNT(on_vals); ++i)
175  {
176  if(strcasecmp(on_vals[i], onoff) == 0)
177  {
178  *var = true;
179  return true;
180  }
181  }
182 
183  const char* const off_vals[] =
184  {
185  "0",
186  "false",
187  "no",
188  "off",
189  NULL
190  };
191  for(uint8_t i = 0; i < ARRAY_COUNT(off_vals); ++i)
192  {
193  if(strcasecmp(off_vals[i], onoff) == 0)
194  {
195  *var = false;
196  return true;
197  }
198  }
199 
200  return false;
201  }
202 
203  /*************************************************************************************************/
204  // convert binary data to hex string
205  static void binToHex(char *dst, int max_dst, const void *data, int data_len)
206  {
207  char *end = dst + max_dst - 1;
208  for (int i = 0; i < data_len; ++i)
209  {
210  if (dst < end)
211  {
212  dst += sprintf(dst, "%2.2x", ((uint8_t *)data)[i]);
213  }
214  }
215  }
216 
217 
218  /*************************************************************************************************/
219  // Parse binary data into hex string
220  // the input buffer MUST be len*2 long
221  // as the parsing is destructive and done in-place
222  static void binToHex(void *h, int len)
223  {
224  char *dst = (char*)h;
225  char *src= (char*)h+len;
226 
227  memmove(src, dst, len);
228 
229  while(len--)
230  {
231  sprintf(dst, "%2.2X", (unsigned int)(*src & 0xff));
232  dst += 2;
233  ++src;
234  }
235  }
236 
237 
238  /*************************************************************************************************/
239  // Parses hex representation of binary data destructively.
240  // Returns number of bytes parsed or -1 on error.
241  static int hexToBin(char *s)
242  {
243  int len, i, j;
244  len = strlen(s);
245  if (len % 2)
246  {
247  return -1;
248  }
249  for (i = j = 0; i < len; i += 2, j++)
250  {
251  const int num = hexToInt(&s[i]);
252  if(num == -1)
253  return -1;
254  s[j] = (char)num;
255  }
256  return j;
257  }
258 
259  /*************************************************************************************************/
260  // hex string to integer, returns -1 on error
261  static int hexToInt(const char *hex_str)
262  {
263  int hi = hexToNibble(*hex_str);
264  int lo = hexToNibble(*(hex_str+1));
265  if (hi == -1 || lo == -1)
266  {
267  return -1;
268  }
269  return (hi << 4) | lo;
270  }
271 
272  /*************************************************************************************************/
273  static int hexToNibble(char c)
274  {
275  if (c >= '0' && c <= '9')
276  {
277  return c - '0';
278  }
279  if (c >= 'a' && c <= 'f')
280  {
281  return 10 + (c - 'a');
282  }
283  if (c >= 'A' && c <= 'F')
284  {
285  return 10 + (c - 'A');
286  }
287  return -1;
288  }
289 
290  /*************************************************************************************************/
291  static const char* uint32ToStr(char* intStrBuffer, int integer)
292  {
293  sprintf(intStrBuffer, "%u", integer);
294  return intStrBuffer;
295  }
296 
297  /*************************************************************************************************/
298  static bool strToUint32(const char *str, uint32_t *uint32Ptr)
299  {
300  intmax_t r;
301  bool result = (str[0] == '0' && str[1] == 'x') ? StringUtil::parseHex(&str[2], &r, 0, UINT_MAX): StringUtil::parseInt(str, &r, 0, UINT_MAX);
302  *uint32Ptr = (uint32_t)r;
303  return result;
304  }
305 
306  /*************************************************************************************************/
307  static bool strToUint16(const char *str, uint16_t *uint16Ptr)
308  {
309  intmax_t r;
310  bool result = StringUtil::parseInt(str, &r, 0, USHRT_MAX);
311  *uint16Ptr = (uint16_t)r;
312  return result;
313  }
314 
315  /*************************************************************************************************/
316  static bool strToInt32(const char *str, int32_t *int32Ptr)
317  {
318  intmax_t r;
319  bool result = StringUtil::parseInt(str, &r, INT_MIN, INT_MAX);
320  *int32Ptr = (int32_t)r;
321  return result;
322  }
323 
324  /*************************************************************************************************/
325  // uint32 hex string to uint32
326  static bool strHexToUint32(const char *strHex, uint32_t *uint32Ptr)
327  {
328  intmax_t r;
329  bool result = StringUtil::parseHex(strHex, &r, 0, UINT_MAX);
330  *uint32Ptr = (uint32_t)r;
331  return result;
332  }
333 
334  /*************************************************************************************************/
335  static char *strtok_r(char *str, const char *delim, char **nextp)
336  {
337  char *ret;
338 
339  if (str == NULL)
340  {
341  str = *nextp;
342  }
343 
344  str += strspn(str, delim);
345 
346  if (*str == '\0')
347  {
348  return NULL;
349  }
350 
351  ret = str;
352 
353  str += strcspn(str, delim);
354 
355  if (*str)
356  {
357  *str++ = '\0';
358  }
359 
360  *nextp = str;
361 
362  return ret;
363  }
364 
365  /*************************************************************************************************/
366  static int strncasecmp(const char *s1, const char *s2, int n)
367  {
368  if (n == 0)
369  return 0;
370 
371  while (n-- != 0 && tolower(*s1) == tolower(*s2))
372  {
373  if (n == 0 || *s1 == '\0' || *s2 == '\0')
374  break;
375  s1++;
376  s2++;
377  }
378 
379  return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
380  }
381 
382  /*************************************************************************************************/
383  static int strcasecmp(const char *s1, const char *s2)
384  {
385  register const unsigned char *p1 = (const unsigned char *) s1;
386  register const unsigned char *p2 = (const unsigned char *) s2;
387  unsigned char c1, c2;
388 
389  if (p1 == p2)
390  return 0;
391 
392  do
393  {
394  c1 = tolower (*p1);
395  c2 = tolower (*p2);
396 
397  if (c1 == '\0')
398  break;
399 
400  ++p1;
401  ++p2;
402  }
403  while (c1 == c2);
404 
405  if (UCHAR_MAX <= INT_MAX)
406  return c1 - c2;
407  else
408  /* On machines where 'char' and 'int' are types of the same size, the
409  difference of two 'unsigned char' values - including the sign bit -
410  doesn't fit in an 'int'. */
411  return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
412  }
413 };
#define ARRAY_COUNT(x)
Return number of elements in static array x.