skip to content
==> src/rs_parse.c <==
1/* Rust's integer parsing (core::num, from_str_radix): sign, digits, overflow checks. */
2#include "mesh/rs_parse.h"
3
4static int digit(char c, unsigned radix) {
5    unsigned d;
6    if (c >= '0' && c <= '9') d = (unsigned)(c - '0');
7    else if (c >= 'a' && c <= 'z') d = (unsigned)(c - 'a') + 10;
8    else if (c >= 'A' && c <= 'Z') d = (unsigned)(c - 'A') + 10;
9    else return -1;
10    return d < radix ? (int)d : -1;
11}
12
13bool rs_parse_uint(const char *s, size_t n, unsigned radix, uint64_t max, uint64_t *out) {
14    size_t i = 0;
15    if (n && s[0] == '+') i = 1;
16    if (i >= n) return false;
17    uint64_t v = 0;
18    for (; i < n; i++) {
19        int d = digit(s[i], radix);
20        if (d < 0) return false;
21        if (v > (max - (uint64_t)d) / radix) return false;
22        v = v * radix + (uint64_t)d;
23    }
24    *out = v;
25    return true;
26}
27
28bool rs_parse_int(const char *s, size_t n, int64_t min, int64_t max, int64_t *out) {
29    size_t i = 0;
30    bool neg = false;
31    if (n && (s[0] == '+' || s[0] == '-')) {
32        neg = s[0] == '-';
33        i = 1;
34    }
35    if (i >= n) return false;
36    /* Accumulate the magnitude as unsigned against the bound of its sign. */
37    uint64_t lim = neg ? (uint64_t)(-(min + 1)) + 1 : (uint64_t)max, v = 0;
38    for (; i < n; i++) {
39        int d = digit(s[i], 10);
40        if (d < 0) return false;
41        if (v > (lim - (uint64_t)d) / 10) return false;
42        v = v * 10 + (uint64_t)d;
43    }
44    *out = neg ? (v == 0 ? 0 : -(int64_t)(v - 1) - 1) : (int64_t)v;
45    return true;
46}