• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   return vpos;
61 }
62 
iwitoa(int64_t v,char * buf,int max)63 int iwitoa(int64_t v, char *buf, int max) {
64 #define ITOA_SZSTEP(_step) if ((ret += (_step)) >= max) { \
65     *ptr = 0; \
66     return ret; \
67   }
68   int ret = 0;
69   char c, *ptr = buf, *p, *p1;
70   if (!v) {
71     ITOA_SZSTEP(1);
72     *ptr++ = '0';
73     *ptr = 0;
74     return ret;
75   }
76   // sign stuff
77   if (v < 0) {
78     v = -v;
79     ITOA_SZSTEP(1)
80     *ptr++ = '-';
81   }
82   // save start pointer
83   p = ptr;
84   while (v) {
85     if (++ret >= max) { //overflow condition
86       memmove(ptr, ptr + 1, p - ptr);
87       p--;
88     }
89     *p++ = '0' + v % 10;
90     v /= 10;
91   }
92   // save end pos
93   p1 = p;
94   // reverse result
95   while (p > ptr) {
96     c = *--p;
97     *p = *ptr;
98     *ptr++ = c;
99   }
100   ptr = p1;
101   *ptr = 0;
102   return ret;
103 
104 #undef ITOA_SZSTEP
105 }
106 
iwftoa(long double n,char s[static IWFTOA_BUFSIZE])107 char *iwftoa(long double n, char s[static IWFTOA_BUFSIZE]) {
108   static double PRECISION = 0.00000000000001;
109   // handle special cases
110   if (isnan(n)) {
111     strcpy(s, "nan");
112   } else if (isinf(n)) {
113     strcpy(s, "inf");
114   } else if (n == 0.0) { // -V550
115     strcpy(s, "0");
116   } else {
117     int digit, m, m1;
118     char *c = s;
119     int neg = (n < 0);
120     if (neg) {
121       n = -n;
122     }
123     // calculate magnitude
124     m = (int) log10l(n);
125     int useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
126     if (neg) {
127       *(c++) = '-';
128     }
129     // set up for scientific notation
130     if (useExp) {
131       if (m < 0) {
132         m -= 1;
133       }
134       n = n / pow(10.0, m);
135       m1 = m;
136       m = 0;
137     }
138     if (m < 1) {
139       m = 0;
140     }
141     // convert the number
142     while (n > PRECISION || m >= 0) {
143       double weight = pow(10.0, m);
144       if (weight > 0 && !isinf(weight)) {
145         digit = (int) floorl(n / weight);
146         n -= (digit * weight);
147         *(c++) = '0' + digit;
148       }
149       if (m == 0 && n > 0) {
150         *(c++) = '.';
151       }
152       m--;
153     }
154     if (useExp) {
155       // convert the exponent
156       int i, j;
157       *(c++) = 'e';
158       if (m1 > 0) {
159         *(c++) = '+';
160       } else {
161         *(c++) = '-';
162         m1 = -m1;
163       }
164       m = 0;
165       while (m1 > 0) {
166         *(c++) = '0' + m1 % 10;
167         m1 /= 10;
168         m++;
169       }
170       c -= m;
171       for (i = 0, j = m - 1; i < j; i++, j--) {
172         c[i] ^= c[j];
173         c[j] ^= c[i];
174         c[i] ^= c[j];
175       }
176       c += m;
177     }
178     *(c) = '\0';
179   }
180   return s;
181 }
182 
iwatoi(const char * str)183 int64_t iwatoi(const char *str) {
184   assert(str);
185   while (*str > '\0' && *str <= ' ') {
186     str++;
187   }
188   int sign = 1;
189   int64_t num = 0;
190   if (*str == '-') {
191     str++;
192     sign = -1;
193   } else if (*str == '+') {
194     str++;
195   }
196   if (!strcmp(str, "inf")) return (INT64_MAX * sign);
197   while (*str != '\0') {
198     if (*str < '0' || *str > '9') break;
199     num = num * 10 + *str - '0';
200     str++;
201   }
202   return num * sign;
203 }
204 
iwatof(const char * str)205 long double iwatof(const char *str) {
206   assert(str);
207   while (*str > '\0' && *str <= ' ') {
208     str++;
209   }
210   int sign = 1;
211   if (*str == '-') {
212     str++;
213     sign = -1;
214   } else if (*str == '+') {
215     str++;
216   }
217   if (!strcmp(str, "inf")) {
218     return HUGE_VAL * sign;
219   }
220   long double num = 0;
221   while (*str != '\0') {
222     if (*str < '0' || *str > '9') {
223       break;
224     }
225     num = num * 10 + *str - '0';
226     str++;
227   }
228   if (*str == '.') {
229     str++;
230     long double fract = 0.0;
231     long double base = 10;
232     while (*str != '\0') {
233       if (*str < '0' || *str > '9') {
234         break;
235       }
236       fract += (*str - '0') / base;
237       str++;
238       base *= 10;
239     }
240     num += fract;
241   }
242   if (*str == 'e' || *str == 'E') {
243     str++;
244     num *= pow(10, iwatoi(str));
245   }
246   return num * sign;
247 }
248 
249 /**
250  * Compare two strings as real numbers
251  */
iwafcmp(const char * aptr,int asiz,const char * bptr,int bsiz)252 int iwafcmp(const char *aptr, int asiz, const char *bptr, int bsiz) {
253   const unsigned char *arp = (const unsigned char *) aptr;
254   const unsigned char *brp = (const unsigned char *) bptr;
255   int alen = asiz, blen = bsiz;
256   int64_t anum = 0, bnum = 0;
257   int asign = 1, bsign = 1;
258 
259   // A part
260   while (alen > 0 && (*arp <= ' ' || *arp == 0x7f)) {
261     arp++;
262     alen--;
263   }
264   if (alen > 0 && *arp == '-') {
265     arp++;
266     alen--;
267     asign = -1;
268   }
269   while (alen > 0) {
270     int c = *arp;
271     if (c < '0' || c > '9') break;
272     anum = anum * 10 + c - '0';
273     arp++;
274     alen--;
275   }
276   anum *= asign;
277 
278   // B part
279   while (blen > 0 && (*brp <= ' ' || *brp == 0x7f)) {
280     brp++;
281     blen--;
282   }
283   if (blen > 0 && *brp == '-') {
284     brp++;
285     blen--;
286     bsign = -1;
287   }
288   while (blen > 0) {
289     int c = *brp;
290     if (c < '0' || c > '9') break;
291     bnum = bnum * 10 + c - '0';
292     brp++;
293     blen--;
294   }
295   bnum *= bsign;
296   if (anum < bnum) return -1;
297   if (anum > bnum) return 1;
298   if ((alen > 1 && *arp == '.') || (blen > 1 && *brp == '.')) {
299     long double aflt = 0;
300     long double bflt = 0;
301     if (alen > 1 && *arp == '.') {
302       arp++;
303       alen--;
304       if (alen > IWFTOA_BUFSIZE) alen = IWFTOA_BUFSIZE;
305       long double base = 10;
306       while (alen > 0) {
307         if (*arp < '0' || *arp > '9') break;
308         aflt += (*arp - '0') / base;
309         arp++;
310         alen--;
311         base *= 10;
312       }
313       aflt *= asign;
314     }
315     if (blen > 1 && *brp == '.') {
316       brp++;
317       blen--;
318       if (blen > IWFTOA_BUFSIZE) blen = IWFTOA_BUFSIZE;
319       long double base = 10;
320       while (blen > 0) {
321         if (*brp < '0' || *brp > '9') break;
322         bflt += (*brp - '0') / base;
323         brp++;
324         blen--;
325         base *= 10;
326       }
327       bflt *= bsign;
328     }
329     if (aflt < bflt) return -1;
330     if (aflt > bflt) return 1;
331   }
332   int rv = strncmp(aptr, bptr, MIN(asiz, bsiz));
333   if (!rv) {
334     return (asiz - bsiz);
335   } else {
336     return rv;
337   }
338 }
339