StrReadFmt

Table of Contents

StrReadFmt

Description

Parse input string according to format string with rust-style placeholders, extracting values into provided arguments. This is a macro wrapper around StrReadFmtInternal.

Parameters

NameDirectionDescription
inputinInput string to parse (must be null-terminated).
fmtstrinFormat string with {} placeholders (must be null-terminated). argument should be a modifiable l-value wrapped with &variable.

Success

Returns a const char* pointing to the beginning of the unparsed portion of the input string after successful parsing.

Failure

Failure occurs within StrReadFmtInternal. Refer to its documentation for details on failure behavior (typically logs error messages and does not return).

Usage example (Cross-references)

    if (StrStartsWithZstr(line, "[.") && StrEndsWithZstr(line, "]")) {
    Str rule_name = StrInit();
    StrReadFmt(line->data, "[.{}]", rule_name);
    
    if (rule_name.length) {
    // Test signed integers
    i8 i8_val = 0;
    StrReadFmt("-42", "{}", i8_val);
    success = success && (i8_val == -42);
    
    i16 i16_val = 0;
    StrReadFmt("-1234", "{}", i16_val);
    success = success && (i16_val == -1234);
    
    i32 i32_val = 0;
    StrReadFmt("-123456", "{}", i32_val);
    success = success && (i32_val == -123456);
    
    i64 i64_val = 0;
    StrReadFmt("-1234567890", "{}", i64_val);
    success = success && (i64_val == -1234567890LL);
    // Test unsigned integers
    u8 u8_val = 0;
    StrReadFmt("42", "{}", u8_val);
    success = success && (u8_val == 42);
    
    u16 u16_val = 0;
    StrReadFmt("1234", "{}", u16_val);
    success = success && (u16_val == 1234);
    
    u32 u32_val = 0;
    StrReadFmt("123456", "{}", u32_val);
    success = success && (u32_val == 123456);
    
    u64 u64_val = 0;
    StrReadFmt("1234567890", "{}", u64_val);
    success = success && (u64_val == 1234567890ULL);
    // Test edge cases
    i8_val = 0;
    StrReadFmt("127", "{}", i8_val);
    success = success && (i8_val == 127);
    
    i8_val = 0;
    StrReadFmt("-128", "{}", i8_val);
    success = success && (i8_val == -128);
    
    u8_val = 0;
    StrReadFmt("255", "{}", u8_val);
    success = success && (u8_val == 255);
    
    u8_val = 0;
    StrReadFmt("0", "{}", u8_val);
    success = success && (u8_val == 0);
    // Test leading zeros
    i32_val = 0;
    StrReadFmt("000042", "{}", i32_val);
    success = success && (i32_val == 42);
    
    i32_val = 0;
    StrReadFmt("-000042", "{}", i32_val);
    success = success && (i32_val == -42);
    // Test whitespace handling
    i32_val = 0;
    StrReadFmt("   42", "{}", i32_val);
    success = success && (i32_val == 42);
    
    i32_val = 0;
    StrReadFmt("42   ", "{}", i32_val);
    success = success && (i32_val == 42);
    
    i32_val = 0;
    StrReadFmt("  42  ", "{}", i32_val);
    success = success && (i32_val == 42);
    
    u32 val = 0;
    StrReadFmt("0xdeadbeef", "{}", val);
    success = success && (val == 0xdeadbeef);
    
    val = 0;
    StrReadFmt("0xDEADBEEF", "{}", val);
    success = success && (val == 0xDEADBEEF);
    // Test hex edge cases
    val = 0;
    StrReadFmt("0x0", "{}", val);
    success = success && (val == 0);
    
    val = 0;
    StrReadFmt("0xf", "{}", val);
    success = success && (val == 0xf);
    
    val = 0;
    StrReadFmt("0xaBcDeF", "{}", val);
    success = success && (val == 0xabcdef);
    
    i8 val = 0;
    StrReadFmt("0b101010", "{}", val);
    success = success && (val == 42);
    // Test binary edge cases
    val = 0;
    StrReadFmt("0b0", "{}", val);
    success = success && (val == 0);
    
    val = 0;
    StrReadFmt("0b1", "{}", val);
    success = success && (val == 1);
    
    i32 val = 0;
    StrReadFmt("0o755", "{}", val);
    success = success && (val == 0755);
    
    val = 0;
    StrReadFmt("755", "{}", val);
    success = success && (val == 755);
    // Test octal edge cases
    val = 0;
    StrReadFmt("0o0", "{}", val);
    success = success && (val == 0);
    
    val = 0;
    StrReadFmt("0o7", "{}", val);
    success = success && (val == 7);
    // Test basic float values
    f32 f32_val = 0.0f;
    StrReadFmt("3.14159", "{}", f32_val);
    success = success && float_equals(f32_val, 3.14159f);
    
    f64 f64_val = 0.0;
    StrReadFmt("3.14159265359", "{}", f64_val);
    success = success && double_equals(f64_val, 3.14159265359);
    // Test float edge cases
    f64_val = 1.0;
    StrReadFmt("0.0", "{}", f64_val);
    success = success && double_equals(f64_val, 0.0);
    
    f64_val = 1.0;
    StrReadFmt("-0.0", "{}", f64_val);
    // Special case for -0.0 which compares equal to 0.0 but has different bit pattern
    // We'll just check if it's close to zero
    
    f64_val = 0.0;
    StrReadFmt("42.0", "{}", f64_val);
    success = success && double_equals(f64_val, 42.0);
    
    f64_val = 0.0;
    StrReadFmt("0.42", "{}", f64_val);
    success = success && double_equals(f64_val, 0.42);
    
    f64 val = 0.0;
    StrReadFmt("1.23e4", "{}", val);
    success = success && double_equals(val, 12300.0);
    
    val = 0.0;
    StrReadFmt("1.23E4", "{}", val);
    success = success && double_equals(val, 12300.0);
    
    val = 0.0;
    StrReadFmt("1.23e+4", "{}", val);
    success = success && double_equals(val, 12300.0);
    
    val = 0.0;
    StrReadFmt("1.23e-4", "{}", val);
    success = success && double_equals(val, 0.000123);
    // Test scientific notation edge cases
    val = 0.0;
    StrReadFmt("1.0e0", "{}", val);
    success = success && double_equals(val, 1.0);
    
    val = 0.0;
    StrReadFmt("1.0E-0", "{}", val);
    success = success && double_equals(val, 1.0);
    
    val = 0.0;
    StrReadFmt("1.0e+0", "{}", val);
    success = success && double_equals(val, 1.0);
    // Test basic string reading
    Str s = StrInit();
    StrReadFmt("Hello", "{}", s);
    
    Str expected = StrInitFromZstr("Hello");
    
    // Test quoted string reading
    StrReadFmt("\"Hello, World!\"", "{}", s);
    
    expected = StrInitFromZstr("Hello, World!");
    i32 num  = 0;
    Str name = StrInit();
    StrReadFmt("Count: 42, Name: Alice", "Count: {}, Name: {}", num, name);
    
    success = success && (num == 42);
    // Test with different order
    f64 val = 0.0;
    StrReadFmt("Value: 3.14, Name: Bob", "Value: {}, Name: {}", val, name);
    
    success = success && double_equals(val, 3.14);
    // Test mismatched format
    i32 num = 42;
    StrReadFmt("Count: forty-two", "Count: {}", num);
    // The value should remain unchanged since the parsing should fail
    success = success && (num == 42);
    // Test invalid integer
    num = 42;
    StrReadFmt("Count: abc", "Count: {}", num);
    success = success && (num == 42);
    // Test overflow
    i8 small = 42;
    StrReadFmt("Value: 1000", "Value: {}", small);
    success = success && (small == 42);
    // Test reading single character into u8
    u8 u8_val = 0;
    StrReadFmt("A", "{c}", u8_val);
    printf("u8_val = %d, expected = %d, pass = %s\n", u8_val, 'A', (u8_val == 'A') ? "true" : "false");
    success = success && (u8_val == 'A');
    
    u8_val = 0;
    StrReadFmt("z", "{c}", u8_val);
    printf("u8_val = %d, expected = %d, pass = %s\n", u8_val, 'z', (u8_val == 'z') ? "true" : "false");
    success = success && (u8_val == 'z');
    // Test reading single character into signed integers
    i8 i8_val = 0;
    StrReadFmt("B", "{c}", i8_val);
    printf("i8_val = %d, expected = %d, pass = %s\n", i8_val, 'B', (i8_val == 'B') ? "true" : "false");
    success = success && (i8_val == 'B');
    
    i16 i16_val = 0;
    StrReadFmt("C", "{c}", i16_val);
    printf("i16_val = %d, expected = %d, pass = %s\n", i16_val, 'C', (i16_val == 'C') ? "true" : "false");
    success = success && (i16_val == 'C');
    
    i32 i32_val = 0;
    StrReadFmt("D", "{c}", i32_val);
    printf("i32_val = %d, expected = %d, pass = %s\n", i32_val, 'D', (i32_val == 'D') ? "true" : "false");
    success = success && (i32_val == 'D');
    
    i64 i64_val = 0;
    StrReadFmt("E", "{c}", i64_val);
    printf("i64_val = %lld, expected = %d, pass = %s\n", i64_val, 'E', (i64_val == 'E') ? "true" : "false");
    success = success && (i64_val == 'E');
    // Test reading single character into unsigned integers
    u16 u16_val = 0;
    StrReadFmt("F", "{c}", u16_val);
    printf("u16_val = %d, expected = %d, pass = %s\n", u16_val, 'F', (u16_val == 'F') ? "true" : "false");
    success = success && (u16_val == 'F');
    
    u32 u32_val = 0;
    StrReadFmt("G", "{c}", u32_val);
    printf("u32_val = %d, expected = %d, pass = %s\n", u32_val, 'G', (u32_val == 'G') ? "true" : "false");
    success = success && (u32_val == 'G');
    
    u64 u64_val = 0;
    StrReadFmt("H", "{c}", u64_val);
    printf("u64_val = %llu, expected = %d, pass = %s\n", u64_val, 'H', (u64_val == 'H') ? "true" : "false");
    success = success && (u64_val == 'H');
    // For u16, read 2 characters
    u16_val = 0;
    StrReadFmt("AB", "{c}", u16_val);
    bool u16_multi_pass = (ZstrCompareN((const char*)&u16_val, "AB", 2) == 0);
    printf("u16_val multi-char test: comparing memory with 'AB', pass = %s\n", u16_multi_pass ? "true" : "false");
    // For i16, read 2 characters
    i16_val = 0;
    StrReadFmt("CD", "{c}", i16_val);
    bool i16_multi_pass = (ZstrCompareN((const char*)&i16_val, "CD", 2) == 0);
    printf("i16_val multi-char test: comparing memory with 'CD', pass = %s\n", i16_multi_pass ? "true" : "false");
    // For u32, read up to 4 characters
    u32_val = 0;
    StrReadFmt("EFGH", "{c}", u32_val);
    bool u32_multi_pass = (ZstrCompareN((const char*)&u32_val, "EFGH", 4) == 0);
    printf("u32_val multi-char test: comparing memory with 'EFGH', pass = %s\n", u32_multi_pass ? "true" : "false");
    // For i32, read up to 4 characters
    i32_val = 0;
    StrReadFmt("IJKL", "{c}", i32_val);
    bool i32_multi_pass = (ZstrCompareN((const char*)&i32_val, "IJKL", 4) == 0);
    printf("i32_val multi-char test: comparing memory with 'IJKL', pass = %s\n", i32_multi_pass ? "true" : "false");
    // For u64, read up to 8 characters
    u64_val = 0;
    StrReadFmt("MNOPQRST", "{c}", u64_val);
    bool u64_multi_pass = (ZstrCompareN((const char*)&u64_val, "MNOPQRST", 8) == 0);
    printf("u64_val multi-char test: comparing memory with 'MNOPQRST', pass = %s\n", u64_multi_pass ? "true" : "false");
    // For i64, read up to 8 characters
    i64_val = 0;
    StrReadFmt("UVWXYZab", "{c}", i64_val);
    bool i64_multi_pass = (ZstrCompareN((const char*)&i64_val, "UVWXYZab", 8) == 0);
    printf("i64_val multi-char test: comparing memory with 'UVWXYZab', pass = %s\n", i64_multi_pass ? "true" : "false");
    // Test reading characters into float types (should interpret as character ordinals)
    f32 f32_val = 0.0f;
    StrReadFmt("A", "{c}", f32_val);
    bool f32_pass = (f32_val == (f32)'A');
    printf("f32_val = %f, expected = %f, pass = %s\n", f32_val, (f32)'A', f32_pass ? "true" : "false");
    
    f64 f64_val = 0.0;
    StrReadFmt("B", "{c}", f64_val);
    bool f64_pass = (f64_val == (f64)'B');
    printf("f64_val = %f, expected = %f, pass = %s\n", f64_val, (f64)'B', f64_pass ? "true" : "false");
    // Test with high ASCII characters
    u8_val = 0;
    StrReadFmt("~", "{c}", u8_val);
    bool tilde_pass = (u8_val == '~');
    printf("u8_val = %d, expected = %d (~), pass = %s\n", u8_val, '~', tilde_pass ? "true" : "false");
    // Test partial reads for larger types with fewer characters
    u32_val = 0;
    StrReadFmt("XY", "{c}", u32_val);
    bool xy_pass = (ZstrCompareN((const char*)&u32_val, "XY", 2) == 0);
    printf("u32_val partial test: comparing memory with 'XY', pass = %s\n", xy_pass ? "true" : "false");
    
    u64_val = 0;
    StrReadFmt("abc", "{c}", u64_val);
    bool abc_pass = (ZstrCompareN((const char*)&u64_val, "abc", 3) == 0);
    printf("u64_val partial test: comparing memory with 'abc', pass = %s\n", abc_pass ? "true" : "false");
    // Test that :c has no effect on string types (should work like regular string reading)
    Str str_val = StrInit();
    StrReadFmt("Hello", "{c}", str_val);
    
    Str  expected = StrInitFromZstr("Hello");
    // Test :c with quoted strings (should work like regular string reading)
    str_val = StrInit();
    StrReadFmt("\"World\"", "{c}", str_val);
    
    expected             = StrInitFromZstr("World");
    const char* input  = "Hello World";
    
    StrReadFmt(input, "{a}", result);
    
    printf("Test 1 - :a (lowercase)\n");
    const char* input  = "hello world";
    
    StrReadFmt(input, "{A}", result);
    
    printf("Test 2 - :A (uppercase)\n");
    const char* input  = "\"MiXeD CaSe\"";
    
    StrReadFmt(input, "{a}", result);
    
    printf("Test 3 - :a with quoted string\n");
    const char* input  = "\"abc123XYZ\"";
    
    StrReadFmt(input, "{A}", result);
    
    printf("Test 4 - :A with mixed alphanumeric\n");
    const char* input  = "Hello World";
    
    StrReadFmt(input, "{c}", result);
    
    printf("Test 5 - :c (no case conversion)\n");
    // Test 1: Reading binary string
    BitVec bv1 = BitVecInit();
    StrReadFmt("10110", "{}", bv1);
    Str result1 = BitVecToStr(&bv1);
    success     = success && (ZstrCompare(result1.data, "10110") == 0);
    // Test 2: Reading hex format
    BitVec bv2 = BitVecInit();
    StrReadFmt("0xDEAD", "{}", bv2);
    u64 value2 = BitVecToInteger(&bv2);
    success    = success && (value2 == 0xDEAD);
    // Test 3: Reading octal format
    BitVec bv3 = BitVecInit();
    StrReadFmt("0o755", "{}", bv3);
    u64 value3 = BitVecToInteger(&bv3);
    success    = success && (value3 == 0755);
    // Test 4: Reading with whitespace
    BitVec bv4 = BitVecInit();
    StrReadFmt("   1101", "{}", bv4);
    Str result4 = BitVecToStr(&bv4);
    success     = success && (ZstrCompare(result4.data, "1101") == 0);
    // Test 5: Reading zero values
    BitVec bv5 = BitVecInit();
    StrReadFmt("0", "{}", bv5);
    Str result5 = BitVecToStr(&bv5);
    success     = success && (ZstrCompare(result5.data, "0") == 0);

Share :

Related Posts

JW_INT_KV

JW_INT_KV Description Write a key and integer value to a JSON object.

Read More

JW_STR_KV

JW_STR_KV Description Write a key and string value into a JSON object.

Read More

JW_STR

JW_STR Description Append a string value (quoted) to the JSON.

Read More