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