skip to content
==> 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}