Skip to content

StrToF64

Description

Convert string to double

Parameters

Name Direction Description
str in String to convert
value out Where to store the result
config in Parse configuration (NULL for default parsing)

Success

Returns true and writes the parsed value into *value

Failure

Returns false when the input cannot be parsed; *value is left unchanged

Usage example (Cross-references)

Usage examples (Cross-references)
            // generic Str-to-float path; non-matching tokens fall back to
            // the digit-by-digit scan below.
            if (StrToF64(&temp, v, NULL)) {
                StrDeinit(&temp);
                DefaultAllocatorDeinit(&scratch);
        }
    
        if (!StrToF64(&temp, v, NULL)) {
            LOG_ERROR("Failed to parse f64");
            StrDeinit(&temp);
            // the digit-by-digit scan below.
            f64 val;
            if (StrToF64(&temp, &val, NULL)) {
                *v = (f32)val;
                StrDeinit(&temp);
        // f32 parser would duplicate the entire StrToF64 logic for no gain.
        f64 val;
        if (!StrToF64(&temp, &val, NULL)) {
            LOG_ERROR("Failed to parse f32");
            StrDeinit(&temp);
    }
    
    bool StrToF64(const Str *str, f64 *value, const StrParseConfig *config) {
        ValidateStr(str);
    // Test StrToF64 function
    bool test_str_to_f64(void) {
        WriteFmt("Testing StrToF64\n");
        DefaultAllocator alloc = DefaultAllocatorInit();
        Str  s       = StrInitFromZstr("123", &alloc);
        f64  value   = 0.0;
        bool success = StrToF64(&s, &value, NULL);
        bool result  = (success && F64Abs(value - 123.0) < 0.0001);
        StrDeinit(&s);
        s       = StrInitFromZstr("123.456", &alloc);
        success = StrToF64(&s, &value, NULL);
        result  = result && (success && F64Abs(value - 123.456) < 0.0001);
        StrDeinit(&s);
        s       = StrInitFromZstr("-123.456", &alloc);
        success = StrToF64(&s, &value, NULL);
        result  = result && (success && F64Abs(value - (-123.456)) < 0.0001);
        StrDeinit(&s);
        s       = StrInitFromZstr("1.23e2", &alloc);
        success = StrToF64(&s, &value, NULL);
        result  = result && (success && F64Abs(value - 123.0) < 0.0001);
        StrDeinit(&s);
        s       = StrInitFromZstr("0", &alloc);
        success = StrToF64(&s, &value, NULL);
        result  = result && (success && F64Abs(value) < 0.0001);
        StrDeinit(&s);
        s       = StrInitFromZstr("inf", &alloc);
        success = StrToF64(&s, &value, NULL);
        result  = result && (success && F64IsInf(value) && value > 0);
        StrDeinit(&s);
        s       = StrInitFromZstr("-inf", &alloc);
        success = StrToF64(&s, &value, NULL);
        result  = result && (success && F64IsInf(value) && value < 0);
        StrDeinit(&s);
        s       = StrInitFromZstr("nan", &alloc);
        success = StrToF64(&s, &value, NULL);
        result  = result && (success && F64IsNan(value));
        StrDeinit(&s);
        s       = StrInitFromZstr("not a number", &alloc);
        success = StrToF64(&s, &value, NULL);
        result  = result && (!success);
                StrFromF64(&s, f64_values[i], &config);
                f64  recovered_f64 = 0.0;
                bool success       = StrToF64(&s, &recovered_f64, NULL);
    
                // Allow for precision loss
        StrFromF64(&s, 1e-300, &fconfig);
        f64 recovered_small = 0.0;
        success             = StrToF64(&s, &recovered_small, NULL);
        result              = result && success && (recovered_small < 1e-299);
        StrFromF64(&s, 1e300, &fconfig);
        f64 recovered_large = 0.0;
        success             = StrToF64(&s, &recovered_large, NULL);
        result              = result && success && (recovered_large > 1e299);
    
                f64  recovered = 0.0;
                bool success   = StrToF64(&s, &recovered, NULL);
    
                // Allow for floating point precision issues
        f64 value = 0.0;
        // Should abort inside ValidateStr; the return is never reached on real code.
        StrToF64(&s, &value, NULL);
        return false;
    }
        Str              s     = StrInitFromZstr(" 1.5", &alloc);
        f64              value = 0.0;
        bool             ok    = StrToF64(&s, &value, NULL);
        bool             pass  = ok && F64Abs(value - 1.5) < 1e-9;
        StrDeinit(&s);
        Str              s     = StrInitFromZstr(" 1.0", &alloc);
        f64              value = 0.0;
        bool             ok    = StrToF64(&s, &value, NULL);
        bool             pass  = ok && F64Abs(value - 1.0) < 1e-9;
        StrDeinit(&s);
        Str              s     = StrInitFromZstr(" nan", &alloc);
        f64              value = 0.0;
        bool             ok    = StrToF64(&s, &value, NULL);
        bool             pass  = ok && F64IsNan(value);
        StrDeinit(&s);
        Str              s     = StrInitFromZstr(" inf", &alloc);
        f64              value = 0.0;
        bool             ok    = StrToF64(&s, &value, NULL);
        bool             pass  = ok && F64IsInf(value) && value > 0;
        StrDeinit(&s);
            view.length = 3; // logical " na"; "n " stays in-buffer past length
            f64 value   = 0.0;
            ok          = StrToF64(&view, &value, NULL);
        }
        return !ok;
            view.length = 3; // logical "-in"; "f " stays in-buffer past length
            f64 value   = 0.0;
            ok          = StrToF64(&view, &value, NULL);
        }
        return !ok;
        Str              s     = StrInitFromZstr("-5", &alloc);
        f64              value = 0.0;
        bool             ok    = StrToF64(&s, &value, NULL);
        bool             pass  = ok && F64Abs(value - (-5.0)) < 1e-9;
        StrDeinit(&s);
        Str              s     = StrInitFromZstr("+5", &alloc);
        f64              value = 0.0;
        bool             ok    = StrToF64(&s, &value, NULL);
        bool             pass  = ok && F64Abs(value - 5.0) < 1e-9;
        StrDeinit(&s);
        Str              s     = StrInitFromZstr("42", &alloc);
        f64              value = 0.0;
        bool             ok    = StrToF64(&s, &value, NULL);
        bool             pass  = ok && F64Abs(value - 42.0) < 1e-9;
        StrDeinit(&s);
        Str              s     = StrInitFromZstr(".5", &alloc);
        f64              value = 0.0;
        bool             ok    = StrToF64(&s, &value, NULL);
        bool             pass  = ok && F64Abs(value - 0.5) < 1e-9;
        StrDeinit(&s);
        Str              s     = StrInitFromZstr("5x", &alloc);
        f64              value = 0.0;
        bool             ok    = StrToF64(&s, &value, NULL); // non-strict default
        bool             pass  = ok && F64Abs(value - 5.0) < 1e-9;
        StrDeinit(&s);
        Str              s     = StrInitFromZstr("1e-2", &alloc);
        f64              value = 0.0;
        bool             ok    = StrToF64(&s, &value, NULL);
        bool             pass  = ok && F64Abs(value - 0.01) < 1e-9;
        StrDeinit(&s);
        Str              s     = StrInitFromZstr("1e5", &alloc);
        f64              value = 0.0;
        bool             ok    = StrToF64(&s, &value, NULL);
        bool             pass  = ok && F64Abs(value - 100000.0) < 1e-6;
        StrDeinit(&s);
        f64              value  = 0.0;
        StrParseConfig   config = {.strict = true, .trim_space = true, .base = 0};
        bool             ok     = StrToF64(&s, &value, &config);
        bool             pass   = ok && F64Abs(value - 5.0) < 1e-9;
        StrDeinit(&s);
        f64              value  = 0.0;
        StrParseConfig   config = {.strict = true, .trim_space = true, .base = 0};
        bool             ok     = StrToF64(&s, &value, &config);
        bool             pass   = ok && F64Abs(value - 5.0) < 1e-9;
        StrDeinit(&s);
        f64              value  = 0.0;
        StrParseConfig   config = {.strict = true, .trim_space = true, .base = 0};
        bool             ok     = StrToF64(&s, &value, &config);
        bool             pass   = ok && F64Abs(value - 5.0) < 1e-9;
        StrDeinit(&s);
        f64              value  = 0.0;
        StrParseConfig   config = {.strict = true, .trim_space = true, .base = 0};
        bool             ok     = StrToF64(&s, &value, &config);
        bool             pass   = ok && F64Abs(value - 42.0) < 1e-9;
        StrDeinit(&s);
    // success with value 1.0.
    static bool test_to_f64_missing_exponent_digits_fails(void) {
        WriteFmt("Testing StrToF64 rejects missing exponent digits (1108:14)\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        Str              s     = StrInitFromZstr("1e", &alloc);
        f64              value = 0.0;
        bool             ok    = StrToF64(&s, &value, NULL);
    
        // Real: "1e" has no exponent digits -> parse must fail.
            test_str_conversion_bounds_failures,
            test_str_conversion_invalid_input_failures,
            test_validate_str_guard,           // StrToF64 (Str.Mutants1)
            test_str_to_u64_validate_barrier,  // StrToU64 (Str.Mutants2)
            test_from_f64_null_aborts,         // StrFromF64 (Str.Mutants3)
Last updated on