1 #include "iwconv.h"
2 #include <math.h>
3 #include <string.h>
4 #include <assert.h>
5 
6 // mapping of ASCII characters to hex values
7 const uint8_t ascii2hex[] = {
8   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
9   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
10   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
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, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 01234567
15   0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89:;<=>?
16   0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // @ABCDEFG
17   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // HIJKLMNO
18   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PQRSTUVW
19   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // XYZ[\]^_
20   0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // `abcdefg
21   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // hijklmno
22   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pqrstuvw
23   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // xyz{|}~.
24   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
25   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
26   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
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 };
41 
iwhex2bin(const char * hex,int hexlen,char * out,int max)42 size_t iwhex2bin(const char *hex, int hexlen, char *out, int max) {
43   size_t pos = 0, vpos = 0;
44   uint8_t idx0, idx1;
45   while (pos < hexlen) {
46     if (!pos && (hexlen % 2)) { // first iteration + odd chars in hex
47       idx0 = '0';               // add '0' prefix
48       idx1 = hex[0];
49       pos += 1;
50     } else {                    // even chars in hex
51       idx0 = hex[pos];
52       idx1 = hex[pos + 1];
53       pos += 2;
54     }
55     out[vpos++] = (uint8_t) (ascii2hex[idx0] << 4) | ascii2hex[idx1];
56     if (vpos >= max) {
57       return vpos;
58     }
59   }
60   ;
61   return vpos;
62 }
63 
iwbin2hex(char * const hex,const size_t hex_maxlen,const unsigned char * const bin,const size_t bin_len)64 char* iwbin2hex(
65   char* const                hex,
66   const size_t               hex_maxlen,
67   const unsigned char* const bin,
68   const size_t               bin_len) {
69 
70   size_t i = (size_t) 0U;
71   unsigned int x;
72   int b;
73   int c;
74 
75   if ((bin_len >= SIZE_MAX / 2) || (hex_maxlen <= bin_len * 2U)) {
76     //errx(2, "bin2hex length wrong");
77     return 0;
78   }
79   while (i < bin_len) {
80     c = bin[i] & 0xf;
81     b = bin[i] >> 4;
82     x = (unsigned char) (87U + c + (((c - 10U) >> 8) & ~38U)) << 8
83         | (unsigned char) (87U + b + (((b - 10U) >> 8) & ~38U));
84     hex[i * 2U] = (char) x;
85     x >>= 8;
86     hex[i * 2U + 1U] = (char) x;
87     i++;
88   }
89   hex[i * 2U] = 0U;
90   return hex;
91 }
92 
iwitoa(int64_t v,char * buf,int max)93 int iwitoa(int64_t v, char *buf, int max) {
94 #define ITOA_SZSTEP(_step) if ((ret += (_step)) >= max) { \
95     *ptr = 0; \
96     return ret; \
97 }
98   int ret = 0;
99   char c, *ptr = buf, *p, *p1;
100   if (!v) {
101     ITOA_SZSTEP(1);
102     *ptr++ = '0';
103     *ptr = 0;
104     return ret;
105   }
106   // sign stuff
107   if (v < 0) {
108     v = -v;
109     ITOA_SZSTEP(1)
110     * ptr++ = '-';
111   }
112   // save start pointer
113   p = ptr;
114   while (v) {
115     if (++ret >= max) { //overflow condition
116       memmove(ptr, ptr + 1, p - ptr);
117       p--;
118     }
119     *p++ = '0' + v % 10;
120     v /= 10;
121   }
122   // save end pos
123   p1 = p;
124   // reverse result
125   while (p > ptr) {
126     c = *--p;
127     *p = *ptr;
128     *ptr++ = c;
129   }
130   ptr = p1;
131   *ptr = 0;
132   return ret;
133 
134 #undef ITOA_SZSTEP
135 }
136 
iwftoa(long double n,char s[static IWFTOA_BUFSIZE])137 char* iwftoa(long double n, char s[static IWFTOA_BUFSIZE]) {
138   static double PRECISION = 0.00000000000001;
139   // handle special cases
140   if (isnan(n)) {
141     strcpy(s, "nan");
142   } else if (isinf(n)) {
143     strcpy(s, "inf");
144   } else if (n == 0.0) { // -V550
145     strcpy(s, "0");
146   } else {
147     int digit, m, m1;
148     char *c = s;
149     int neg = (n < 0);
150     if (neg) {
151       n = -n;
152     }
153     // calculate magnitude
154     m = (int) log10l(n);
155     int useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
156     if (neg) {
157       *(c++) = '-';
158     }
159     // set up for scientific notation
160     if (useExp) {
161       if (m < 0) {
162         m -= 1;
163       }
164       n = n / pow(10.0, m);
165       m1 = m;
166       m = 0;
167     }
168     if (m < 1) {
169       m = 0;
170     }
171     // convert the number
172     while (n > PRECISION || m >= 0) {
173       double weight = pow(10.0, m);
174       if ((weight > 0) && !isinf(weight)) {
175         digit = (int) floorl(n / weight);
176         n -= (digit * weight);
177         *(c++) = '0' + digit;
178       }
179       if ((m == 0) && (n > 0)) {
180         *(c++) = '.';
181       }
182       m--;
183     }
184     if (useExp) {
185       // convert the exponent
186       int i, j;
187       *(c++) = 'e';
188       if (m1 > 0) {
189         *(c++) = '+';
190       } else {
191         *(c++) = '-';
192         m1 = -m1;
193       }
194       m = 0;
195       while (m1 > 0) {
196         *(c++) = '0' + m1 % 10;
197         m1 /= 10;
198         m++;
199       }
200       c -= m;
201       for (i = 0, j = m - 1; i < j; i++, j--) {
202         c[i] ^= c[j];
203         c[j] ^= c[i];
204         c[i] ^= c[j];
205       }
206       c += m;
207     }
208     *(c) = '\0';
209   }
210   return s;
211 }
212 
iwatoi(const char * str)213 int64_t iwatoi(const char *str) {
214   assert(str);
215   while (*str > '\0' && *str <= ' ') {
216     str++;
217   }
218   int sign = 1;
219   int64_t num = 0;
220   if (*str == '-') {
221     str++;
222     sign = -1;
223   } else if (*str == '+') {
224     str++;
225   }
226   if (!strcmp(str, "inf")) {
227     return (INT64_MAX * sign);
228   }
229   while (*str != '\0') {
230     if ((*str < '0') || (*str > '9')) {
231       break;
232     }
233     num = num * 10 + *str - '0';
234     str++;
235   }
236   return num * sign;
237 }
238 
iwatof(const char * str)239 long double iwatof(const char *str) {
240   assert(str);
241   while (*str > '\0' && *str <= ' ') {
242     str++;
243   }
244   int sign = 1;
245   if (*str == '-') {
246     str++;
247     sign = -1;
248   } else if (*str == '+') {
249     str++;
250   }
251   if (!strcmp(str, "inf")) {
252     return HUGE_VAL * sign;
253   }
254   long double num = 0;
255   while (*str != '\0') {
256     if ((*str < '0') || (*str > '9')) {
257       break;
258     }
259     num = num * 10 + *str - '0';
260     str++;
261   }
262   if (*str == '.') {
263     str++;
264     long double fract = 0.0;
265     long double base = 10;
266     while (*str != '\0') {
267       if ((*str < '0') || (*str > '9')) {
268         break;
269       }
270       fract += (*str - '0') / base;
271       str++;
272       base *= 10;
273     }
274     num += fract;
275   }
276   if ((*str == 'e') || (*str == 'E')) {
277     str++;
278     num *= pow(10, iwatoi(str));
279   }
280   return num * sign;
281 }
282 
283 /**
284  * Compare two strings as real numbers
285  */
iwafcmp(const char * aptr,int asiz,const char * bptr,int bsiz)286 int iwafcmp(const char *aptr, int asiz, const char *bptr, int bsiz) {
287   const unsigned char *arp = (const unsigned char*) aptr;
288   const unsigned char *brp = (const unsigned char*) bptr;
289   int alen = asiz, blen = bsiz;
290   int64_t anum = 0, bnum = 0;
291   int asign = 1, bsign = 1;
292 
293   // A part
294   while (alen > 0 && (*arp <= ' ' || *arp == 0x7f)) {
295     arp++;
296     alen--;
297   }
298   if ((alen > 0) && (*arp == '-')) {
299     arp++;
300     alen--;
301     asign = -1;
302   }
303   while (alen > 0) {
304     int c = *arp;
305     if ((c < '0') || (c > '9')) {
306       break;
307     }
308     anum = anum * 10 + c - '0';
309     arp++;
310     alen--;
311   }
312   anum *= asign;
313 
314   // B part
315   while (blen > 0 && (*brp <= ' ' || *brp == 0x7f)) {
316     brp++;
317     blen--;
318   }
319   if ((blen > 0) && (*brp == '-')) {
320     brp++;
321     blen--;
322     bsign = -1;
323   }
324   while (blen > 0) {
325     int c = *brp;
326     if ((c < '0') || (c > '9')) {
327       break;
328     }
329     bnum = bnum * 10 + c - '0';
330     brp++;
331     blen--;
332   }
333   bnum *= bsign;
334   if (anum < bnum) {
335     return -1;
336   }
337   if (anum > bnum) {
338     return 1;
339   }
340   if (((alen > 1) && (*arp == '.')) || ((blen > 1) && (*brp == '.'))) {
341     long double aflt = 0;
342     long double bflt = 0;
343     if ((alen > 1) && (*arp == '.')) {
344       arp++;
345       alen--;
346       if (alen > IWFTOA_BUFSIZE) {
347         alen = IWFTOA_BUFSIZE;
348       }
349       long double base = 10;
350       while (alen > 0) {
351         if ((*arp < '0') || (*arp > '9')) {
352           break;
353         }
354         aflt += (*arp - '0') / base;
355         arp++;
356         alen--;
357         base *= 10;
358       }
359       aflt *= asign;
360     }
361     if ((blen > 1) && (*brp == '.')) {
362       brp++;
363       blen--;
364       if (blen > IWFTOA_BUFSIZE) {
365         blen = IWFTOA_BUFSIZE;
366       }
367       long double base = 10;
368       while (blen > 0) {
369         if ((*brp < '0') || (*brp > '9')) {
370           break;
371         }
372         bflt += (*brp - '0') / base;
373         brp++;
374         blen--;
375         base *= 10;
376       }
377       bflt *= bsign;
378     }
379     if (aflt < bflt) {
380       return -1;
381     }
382     if (aflt > bflt) {
383       return 1;
384     }
385   }
386   int rv = strncmp(aptr, bptr, MIN(asiz, bsiz));
387   if (!rv) {
388     return (asiz - bsiz);
389   } else {
390     return rv;
391   }
392 }
393