• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "iwconv.h"
2 #include <math.h>
3 #include <string.h>
4 #include <assert.h>
5 #include <ctype.h>
6 #include <errno.h>
7 #include <stdio.h>
8 
9 // mapping of ASCII characters to hex values
10 static const uint8_t ascii2hex[] = {
11   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
12   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
13   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
14   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
15   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //  !"#$%&'
16   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ()*+,-./
17   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 01234567
18   0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89:;<=>?
19   0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // @ABCDEFG
20   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // HIJKLMNO
21   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PQRSTUVW
22   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // XYZ[\]^_
23   0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // `abcdefg
24   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // hijklmno
25   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pqrstuvw
26   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // xyz{|}~.
27   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
28   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
29   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
30   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
31   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
32   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
33   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
34   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
35   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
36   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
37   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
38   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
39   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
40   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
41   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
42   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // ........
43 };
44 
iwhex2bin(const char * hex,int hexlen,char * out,int max)45 size_t iwhex2bin(const char *hex, int hexlen, char *out, int max) {
46   size_t pos = 0, vpos = 0;
47   uint8_t idx0, idx1;
48   while (pos < hexlen) {
49     if (!pos && (hexlen % 2)) { // first iteration + odd chars in hex
50       idx0 = '0';               // add '0' prefix
51       idx1 = hex[0];
52       pos += 1;
53     } else {                    // even chars in hex
54       idx0 = hex[pos];
55       idx1 = hex[pos + 1];
56       pos += 2;
57     }
58     out[vpos++] = (uint8_t) (ascii2hex[idx0] << 4) | ascii2hex[idx1];
59     if (vpos >= max) {
60       return vpos;
61     }
62   }
63   return vpos;
64 }
65 
iwbin2hex(char * const hex,const size_t hex_maxlen,const unsigned char * const bin,const size_t bin_len)66 char* iwbin2hex(
67   char* const                hex,
68   const size_t               hex_maxlen,
69   const unsigned char* const bin,
70   const size_t               bin_len
71   ) {
72   size_t i = (size_t) 0U;
73   unsigned int x;
74   int b;
75   int c;
76 
77   if ((bin_len >= SIZE_MAX / 2) || (hex_maxlen <= bin_len * 2U)) {
78     //errx(2, "bin2hex length wrong");
79     return 0;
80   }
81   while (i < bin_len) {
82     c = bin[i] & 0xf;
83     b = bin[i] >> 4;
84     x = (unsigned char) (87U + c + (((c - 10U) >> 8) & ~38U)) << 8
85         | (unsigned char) (87U + b + (((b - 10U) >> 8) & ~38U));
86     hex[i * 2U] = (char) x;
87     x >>= 8;
88     hex[i * 2U + 1U] = (char) x;
89     i++;
90   }
91   hex[i * 2U] = 0U;
92   return hex;
93 }
94 
iwitoa(int64_t v,char * buf,int max)95 int iwitoa(int64_t v, char *buf, int max) {
96 #define ITOA_SZSTEP(_step) if ((ret += (_step)) >= max) { \
97     *ptr = 0; \
98     return ret; \
99 }
100   int ret = 0;
101   char c, *ptr = buf, *p, *p1;
102   if (!v) {
103     ITOA_SZSTEP(1);
104     *ptr++ = '0';
105     *ptr = 0;
106     return ret;
107   }
108   // sign stuff
109   if (v < 0) {
110     if (IW_UNLIKELY(v == INT64_MIN)) {
111       return snprintf(buf, max, "-9223372036854775808");
112     } else {
113       v = -v;
114       ITOA_SZSTEP(1)
115       * ptr++ = '-';
116     }
117   }
118   // save start pointer
119   p = ptr;
120   while (v) {
121     if (++ret >= max) { //overflow condition
122       memmove(ptr, ptr + 1, p - ptr);
123       p--;
124     }
125     *p++ = '0' + v % 10;
126     v /= 10;
127   }
128   // save end pos
129   p1 = p;
130   // reverse result
131   while (p > ptr) {
132     c = *--p;
133     *p = *ptr;
134     *ptr++ = c;
135   }
136   ptr = p1;
137   *ptr = 0;
138   return ret;
139 
140 #undef ITOA_SZSTEP
141 }
142 
iwftoa(long double n,char s[static IWNUMBUF_SIZE])143 char* iwftoa(long double n, char s[static IWNUMBUF_SIZE]) {
144   static double PRECISION = 0.00000000000001;
145   // handle special cases
146   if (isnan(n)) {
147     strcpy(s, "nan");
148   } else if (isinf(n)) {
149     strcpy(s, "inf");
150   } else if (n == 0.0) { // -V550
151     strcpy(s, "0");
152   } else {
153     int digit, m, m1;
154     char *c = s;
155     int neg = (n < 0);
156     if (neg) {
157       n = -n;
158     }
159     // calculate magnitude
160     m = (int) log10l(n);
161     int useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
162     if (neg) {
163       *(c++) = '-';
164     }
165     // set up for scientific notation
166     if (useExp) {
167       if (m < 0) {
168         m -= 1;
169       }
170       n = n / pow(10.0, m);
171       m1 = m;
172       m = 0;
173     }
174     if (m < 1) {
175       m = 0;
176     }
177     // convert the number
178     while (n > PRECISION || m >= 0) {
179       double weight = pow(10.0, m);
180       if ((weight > 0) && !isinf(weight)) {
181         digit = (int) floorl(n / weight);
182         n -= (digit * weight);
183         *(c++) = '0' + digit;
184       }
185       if ((m == 0) && (n > 0)) {
186         *(c++) = '.';
187       }
188       m--;
189     }
190     if (useExp) {
191       // convert the exponent
192       int i, j;
193       *(c++) = 'e';
194       if (m1 > 0) {
195         *(c++) = '+';
196       } else {
197         *(c++) = '-';
198         m1 = -m1;
199       }
200       m = 0;
201       while (m1 > 0) {
202         *(c++) = '0' + m1 % 10;
203         m1 /= 10;
204         m++;
205       }
206       c -= m;
207       for (i = 0, j = m - 1; i < j; i++, j--) {
208         c[i] ^= c[j];
209         c[j] ^= c[i];
210         c[i] ^= c[j];
211       }
212       c += m;
213     }
214     *(c) = '\0';
215   }
216   return s;
217 }
218 
iwatoi(const char * str)219 int64_t iwatoi(const char *str) {
220   assert(str);
221   while (*str > '\0' && *str <= ' ') {
222     str++;
223   }
224   int sign = 1;
225   int64_t num = 0;
226   if (*str == '-') {
227     str++;
228     sign = -1;
229   } else if (*str == '+') {
230     str++;
231   }
232   if (!strcmp(str, "inf")) {
233     return (INT64_MAX * sign);
234   }
235   while (*str != '\0') {
236     if ((*str < '0') || (*str > '9')) {
237       break;
238     }
239     num = num * 10 + *str - '0';
240     str++;
241   }
242   return num * sign;
243 }
244 
iwatoi2(const char * str,size_t len)245 int64_t iwatoi2(const char *str, size_t len) {
246   while (len > 0 && *str > '\0' && *str <= ' ') {
247     str++;
248     len--;
249   }
250   if (len == 0) {
251     return 0;
252   }
253   int sign = 1;
254   int64_t num = 0;
255   if (*str == '-') {
256     str++;
257     len--;
258     sign = -1;
259   } else if (*str == '+') {
260     str++;
261     len--;
262   }
263   if (!strcmp(str, "inf")) {
264     return (INT64_MAX * sign);
265   }
266   while (len > 0 && *str != '\0') {
267     if ((*str < '0') || (*str > '9')) {
268       break;
269     }
270     num = num * 10 + *str - '0';
271     str++;
272     len--;
273   }
274   return num * sign;
275 }
276 
iwatof(const char * str)277 long double iwatof(const char *str) {
278   assert(str);
279   while (*str > '\0' && *str <= ' ') {
280     str++;
281   }
282   int sign = 1;
283   if (*str == '-') {
284     str++;
285     sign = -1;
286   } else if (*str == '+') {
287     str++;
288   }
289   if (!strcmp(str, "inf")) {
290     return HUGE_VAL * sign;
291   }
292   long double num = 0;
293   while (*str != '\0') {
294     if ((*str < '0') || (*str > '9')) {
295       break;
296     }
297     num = num * 10 + *str - '0';
298     str++;
299   }
300   if (*str == '.') {
301     str++;
302     long double fract = 0.0;
303     long double base = 10;
304     while (*str != '\0') {
305       if ((*str < '0') || (*str > '9')) {
306         break;
307       }
308       fract += (*str - '0') / base;
309       str++;
310       base *= 10;
311     }
312     num += fract;
313   }
314   if ((*str == 'e') || (*str == 'E')) {
315     str++;
316     num *= pow(10, iwatoi(str));
317   }
318   return num * sign;
319 }
320 
321 /**
322  * Compare two strings as real numbers
323  */
iwafcmp(const char * aptr,int asiz,const char * bptr,int bsiz)324 int iwafcmp(const char *aptr, int asiz, const char *bptr, int bsiz) {
325   const unsigned char *arp = (const unsigned char*) aptr;
326   const unsigned char *brp = (const unsigned char*) bptr;
327   int alen = asiz, blen = bsiz;
328   int64_t anum = 0, bnum = 0;
329   int asign = 1, bsign = 1;
330 
331   // A part
332   while (alen > 0 && (*arp <= ' ' || *arp == 0x7f)) {
333     arp++;
334     alen--;
335   }
336   if ((alen > 0) && (*arp == '-')) {
337     arp++;
338     alen--;
339     asign = -1;
340   }
341   while (alen > 0) {
342     int c = *arp;
343     if ((c < '0') || (c > '9')) {
344       break;
345     }
346     anum = anum * 10 + c - '0';
347     arp++;
348     alen--;
349   }
350   anum *= asign;
351 
352   // B part
353   while (blen > 0 && (*brp <= ' ' || *brp == 0x7f)) {
354     brp++;
355     blen--;
356   }
357   if ((blen > 0) && (*brp == '-')) {
358     brp++;
359     blen--;
360     bsign = -1;
361   }
362   while (blen > 0) {
363     int c = *brp;
364     if ((c < '0') || (c > '9')) {
365       break;
366     }
367     bnum = bnum * 10 + c - '0';
368     brp++;
369     blen--;
370   }
371   bnum *= bsign;
372   if (anum < bnum) {
373     return -1;
374   }
375   if (anum > bnum) {
376     return 1;
377   }
378   if (((alen > 1) && (*arp == '.')) || ((blen > 1) && (*brp == '.'))) {
379     long double aflt = 0;
380     long double bflt = 0;
381     if ((alen > 1) && (*arp == '.')) {
382       arp++;
383       alen--;
384       if (alen > IWNUMBUF_SIZE) {
385         alen = IWNUMBUF_SIZE;
386       }
387       long double base = 10;
388       while (alen > 0) {
389         if ((*arp < '0') || (*arp > '9')) {
390           break;
391         }
392         aflt += (*arp - '0') / base;
393         arp++;
394         alen--;
395         base *= 10;
396       }
397       aflt *= asign;
398     }
399     if ((blen > 1) && (*brp == '.')) {
400       brp++;
401       blen--;
402       if (blen > IWNUMBUF_SIZE) {
403         blen = IWNUMBUF_SIZE;
404       }
405       long double base = 10;
406       while (blen > 0) {
407         if ((*brp < '0') || (*brp > '9')) {
408           break;
409         }
410         bflt += (*brp - '0') / base;
411         brp++;
412         blen--;
413         base *= 10;
414       }
415       bflt *= bsign;
416     }
417     if (aflt < bflt) {
418       return -1;
419     }
420     if (aflt > bflt) {
421       return 1;
422     }
423   }
424   int rv = strncmp(aptr, bptr, MIN(asiz, bsiz));
425   if (!rv) {
426     return (asiz - bsiz);
427   } else {
428     return rv;
429   }
430 }
431 
432 /// MIT Licensed
433 /// Taken https://github.com/mattn/strtod/blob/master/strtod.c
434 
skipwhite(const char * q)435 static const char* skipwhite(const char *q) {
436   const char *p = q;
437   while (isspace(*p)) {
438     ++p;
439   }
440   return p;
441 }
442 
iwstrtod(const char * str,char ** end)443 double iwstrtod(const char *str, char **end) {
444   double d = 0.0;
445   int sign;
446   const char *p, *a;
447 
448   a = p = str;
449   p = skipwhite(p);
450 
451   /* decimal part */
452   sign = 1;
453   if (*p == '-') {
454     sign = -1;
455     ++p;
456   } else if (*p == '+') {
457     ++p;
458   }
459   if (isdigit(*p)) {
460     d = (double) (*p++ - '0');
461     while (*p && isdigit(*p)) {
462       d = d * 10.0 + (double) (*p - '0');
463       ++p;
464     }
465     a = p;
466   } else if (*p != '.') {
467     goto done;
468   }
469   d *= sign;
470 
471   /* fraction part */
472   if (*p == '.') {
473     double f = 0.0;
474     double base = 0.1;
475     ++p;
476 
477     if (isdigit(*p)) {
478       while (*p && isdigit(*p)) {
479         f += base * (*p - '0');
480         base /= 10.0;
481         ++p;
482       }
483     }
484     d += f * sign;
485     a = p;
486   }
487 
488   /* exponential part */
489   if ((*p == 'E') || (*p == 'e')) {
490     int e = 0;
491     ++p;
492 
493     sign = 1;
494     if (*p == '-') {
495       sign = -1;
496       ++p;
497     } else if (*p == '+') {
498       ++p;
499     }
500 
501     if (isdigit(*p)) {
502       while (*p == '0') {
503         ++p;
504       }
505       if (*p == '\0') {
506         --p;
507       }
508       e = (*p++ - '0');
509       while (*p && isdigit(*p)) {
510         e = e * 10 + (*p - '0');
511         ++p;
512       }
513       e *= sign;
514     } else if (!isdigit(*(a - 1))) {
515       a = str;
516       goto done;
517     } else if (*p == 0) {
518       goto done;
519     }
520 
521     if (d == 2.2250738585072011 && e == -308) {
522       d = 0.0;
523       a = p;
524       errno = ERANGE;
525       goto done;
526     }
527     if (d == 2.2250738585072012 && e <= -308) {
528       d *= 1.0e-308;
529       a = p;
530       goto done;
531     }
532     d *= pow(10.0, (double) e);
533     a = p;
534   } else if (p > str && !isdigit(*(p - 1))) {
535     a = str;
536     goto done;
537   }
538 
539 done:
540   if (end) {
541     *end = (char*) a;
542   }
543   return d;
544 }
545