==> src/parse.c <==1/* Rust's integer and float FromStr, in C. */
2#include "mesh/parse.h"
3
4#include <stdlib.h>
5#include <string.h>
6#include <strings.h>
7
8static bool digits_u64(const char *s, unsigned base, uint64_t max, uint64_t *out) {
9 if (*s == '+') s++;
10 if (!*s) return false;
11 uint64_t v = 0;
12 for (; *s; s++) {
13 unsigned d;
14 if (*s >= '0' && *s <= '9') d = (unsigned)(*s - '0');
15 else if (base == 16 && *s >= 'a' && *s <= 'f') d = (unsigned)(*s - 'a' + 10);
16 else if (base == 16 && *s >= 'A' && *s <= 'F') d = (unsigned)(*s - 'A' + 10);
17 else return false;
18 if (v > (max - d) / base) return false;
19 v = v * base + d;
20 }
21 *out = v;
22 return true;
23}
24
25bool mp_u64(const char *s, uint64_t *out) { return digits_u64(s, 10, UINT64_MAX, out); }
26bool mp_hex_u64(const char *s, uint64_t *out) { return digits_u64(s, 16, UINT64_MAX, out); }
27
28bool mp_u32(const char *s, uint32_t *out) {
29 uint64_t v;
30 if (!digits_u64(s, 10, UINT32_MAX, &v)) return false;
31 *out = (uint32_t)v;
32 return true;
33}
34
35bool mp_u16(const char *s, uint16_t *out) {
36 uint64_t v;
37 if (!digits_u64(s, 10, UINT16_MAX, &v)) return false;
38 *out = (uint16_t)v;
39 return true;
40}
41
42bool mp_hex_u32(const char *s, uint32_t *out) {
43 uint64_t v;
44 if (!digits_u64(s, 16, UINT32_MAX, &v)) return false;
45 *out = (uint32_t)v;
46 return true;
47}
48
49bool mp_i32(const char *s, int32_t *out) {
50 bool neg = *s == '-';
51 uint64_t v;
52 if (!digits_u64(neg ? s + 1 : s, 10, neg ? (uint64_t)INT32_MAX + 1 : INT32_MAX, &v)) return false;
53 if (neg && s[1] == '+') return false;
54 *out = neg ? (int32_t)(-(int64_t)v) : (int32_t)v;
55 return true;
56}
57
58static bool float_syntax(const char *s) {
59 const char *p = s;
60 if (*p == '+' || *p == '-') p++;
61 if (strcasecmp(p, "inf") == 0 || strcasecmp(p, "infinity") == 0 || strcasecmp(p, "nan") == 0) return true;
62 int whole = 0, frac = 0;
63 while (*p >= '0' && *p <= '9') p++, whole++;
64 if (*p == '.') {
65 p++;
66 while (*p >= '0' && *p <= '9') p++, frac++;
67 }
68 if (!whole && !frac) return false;
69 if (*p == 'e' || *p == 'E') {
70 p++;
71 if (*p == '+' || *p == '-') p++;
72 int ex = 0;
73 while (*p >= '0' && *p <= '9') p++, ex++;
74 if (!ex) return false;
75 }
76 return *p == 0;
77}
78
79bool mp_f64(const char *s, double *out) {
80 if (!float_syntax(s)) return false;
81 *out = strtod(s, NULL);
82 return true;
83}
84
85bool mp_f32(const char *s, float *out) {
86 if (!float_syntax(s)) return false;
87 *out = strtof(s, NULL);
88 return true;
89}