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