static_noinline bool read_number_raw()

in include/yyjson/yyjson.c [3857:3927]


static_noinline bool read_number_raw(u8 **ptr,
                                     u8 **pre,
                                     yyjson_read_flag flg,
                                     yyjson_val *val,
                                     const char **msg) {
    
#define return_err(_pos, _msg) do { \
    *msg = _msg; \
    *end = _pos; \
    return false; \
} while (false)
    
#define return_raw() do { \
    val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \
    val->uni.str = (const char *)hdr; \
    *pre = cur; *end = cur; return true; \
} while (false)
    
    u8 *hdr = *ptr;
    u8 *cur = *ptr;
    u8 **end = ptr;
    
    /* add null-terminator for previous raw string */
    if (*pre) **pre = '\0';
    
    /* skip sign */
    cur += (*cur == '-');
    
    /* read first digit, check leading zero */
    if (unlikely(!digi_is_digit(*cur))) {
        if (true) {
            if (read_inf_or_nan(*hdr == '-', &cur, pre, val)) return_raw();
        }
        return_err(cur, "no digit after minus sign");
    }
    
    /* read integral part */
    if (*cur == '0') {
        cur++;
        if (unlikely(digi_is_digit(*cur))) {
            return_err(cur - 1, "number with leading zero is not allowed");
        }
        if (!digi_is_fp(*cur)) return_raw();
    } else {
        while (digi_is_digit(*cur)) cur++;
        if (!digi_is_fp(*cur)) return_raw();
    }
    
    /* read fraction part */
    if (*cur == '.') {
        cur++;
        if (!digi_is_digit(*cur++)) {
            return_err(cur, "no digit after decimal point");
        }
        while (digi_is_digit(*cur)) cur++;
    }
    
    /* read exponent part */
    if (digi_is_exp(*cur)) {
        cur += 1 + digi_is_sign(cur[1]);
        if (!digi_is_digit(*cur++)) {
            return_err(cur, "no digit after exponent sign");
        }
        while (digi_is_digit(*cur)) cur++;
    }
    
    return_raw();
    
#undef return_err
#undef return_raw
}