StrReadFmt
Description
Parse input string according to format string with rust-style placeholders, extracting values into provided arguments. Delegates to the in-tree formatted-read backend.
The new
input value after a successful read will be in [input, input + len(input)]
Provided input string must be an assignable l-value. The macro automatically updates given input string to new parse position after a successful parse. If parse fails, the input pointer does not change.
The input must not be passed to any allocator’s deallocate call after use. The pointer value is updated on successful read; after the call it might be (input) + 1 or (input + 1233493783847394), neither of which is a valid free target.
Not providing an assignable input (first parameter) will result in undefined behavior. If you’re lucky you’ll get a segfault.
Parameters
| Name | Direction | Description |
|---|---|---|
input |
in | Input string to parse (must be null-terminated). |
fmtstr |
in | Format string with {} placeholders (must be null-terminated). argument should be a modifiable l-value wrapped with &variable. |
Usage example (from documentation)
void ParseInput(Zstr in, Zstr *out_rest, DefaultAllocator *alloc) {
Zstr p = in; // local cursor; in is not mutated
i32 id = 0;
Str name = StrInit(alloc);
StrReadFmt(p, "Person id = {} and name = {}", &id, &name);
// p now points one past the consumed text on success.
*out_rest = p;
StrDeinit(&name);
}Success
Statement form – input is advanced in place to point at the first character past the consumed text.
Failure
Backend logs an error and returns without consuming input; input is left pointing at its original position.
Usage example (Cross-references)
Usage examples (Cross-references)
- In
Http.c:118:
Str version = StrInit(alloc);
StrReadFmt(cursor, "{} {} {}\r\n", method, req->url, version);
if (cursor == in) {
LOG_ERROR("http request parse failed: invalid request line");- In
Http.c:160:
HttpHeader hh = HttpHeaderInit(alloc);
StrReadFmt(cursor, "{}: {}\r\n", hh.key, hh.value);
if (cursor == line_start) {
LOG_ERROR("failed to parse header line"); return i;
}
StrReadFmt(i, "({}, {})", p->x, p->y);
return i;
} return i;
}
StrReadFmt(i, "[{}..{}]", b->min, b->max);
return i;
} return i;
}
StrReadFmt(i, "{}:{}@{}", r->id, r->bbox, r->centroid);
return i;
} Zstr in = "(42, -9)";
Point2D p = {0};
StrReadFmt(in, "{}", p);
bool ok = (p.x == 42) && (p.y == -9); bool ok = StrAppendFmt(&out, "{}", src);
Zstr in = StrBegin(&out);
StrReadFmt(in, "{}", dst);
ok = ok && (dst.x == src.x) && (dst.y == src.y); bool ok = StrAppendFmt(&out, "{}", src);
Zstr in = StrBegin(&out);
StrReadFmt(in, "{}", dst);
ok = ok && (dst.min.x == src.min.x) && (dst.min.y == src.min.y); bool ok = StrAppendFmt(&out, "{}", src);
Zstr in = StrBegin(&out);
StrReadFmt(in, "{}", dst);
ok = ok && (dst.id == src.id);- In
Io.Read.c:50:
i8 i8_val = 0;
z = "-42";
StrReadFmt(z, "{}", i8_val);
success = success && (i8_val == -42);- In
Io.Read.c:55:
i16 i16_val = 0;
z = "-1234";
StrReadFmt(z, "{}", i16_val);
success = success && (i16_val == -1234);- In
Io.Read.c:60:
i32 i32_val = 0;
z = "-123456";
StrReadFmt(z, "{}", i32_val);
success = success && (i32_val == -123456);- In
Io.Read.c:65:
i64 i64_val = 0;
z = "-1234567890";
StrReadFmt(z, "{}", i64_val);
success = success && (i64_val == -1234567890LL);- In
Io.Read.c:70:
u8 u8_val = 0;
z = "42";
StrReadFmt(z, "{}", u8_val);
success = success && (u8_val == 42);- In
Io.Read.c:75:
u16 u16_val = 0;
z = "1234";
StrReadFmt(z, "{}", u16_val);
success = success && (u16_val == 1234);- In
Io.Read.c:80:
u32 u32_val = 0;
z = "123456";
StrReadFmt(z, "{}", u32_val);
success = success && (u32_val == 123456);- In
Io.Read.c:85:
u64 u64_val = 0;
z = "1234567890";
StrReadFmt(z, "{}", u64_val);
success = success && (u64_val == 1234567890ULL);- In
Io.Read.c:90:
i8_val = 0;
z = "127";
StrReadFmt(z, "{}", i8_val);
success = success && (i8_val == 127);- In
Io.Read.c:95:
i8_val = 0;
z = "-128";
StrReadFmt(z, "{}", i8_val);
success = success && (i8_val == -128);- In
Io.Read.c:100:
u8_val = 0;
z = "255";
StrReadFmt(z, "{}", u8_val);
success = success && (u8_val == 255);- In
Io.Read.c:105:
u8_val = 0;
z = "0";
StrReadFmt(z, "{}", u8_val);
success = success && (u8_val == 0);- In
Io.Read.c:110:
i32_val = 0;
z = "000042";
StrReadFmt(z, "{}", i32_val);
success = success && (i32_val == 42);- In
Io.Read.c:115:
i32_val = 0;
z = "-000042";
StrReadFmt(z, "{}", i32_val);
success = success && (i32_val == -42);- In
Io.Read.c:120:
i32_val = 0;
z = " 42";
StrReadFmt(z, "{}", i32_val);
success = success && (i32_val == 42);- In
Io.Read.c:125:
i32_val = 0;
z = "42 ";
StrReadFmt(z, "{}", i32_val);
success = success && (i32_val == 42);- In
Io.Read.c:130:
i32_val = 0;
z = " 42 ";
StrReadFmt(z, "{}", i32_val);
success = success && (i32_val == 42);- In
Io.Read.c:145:
u32 val = 0;
z = "0xdeadbeef";
StrReadFmt(z, "{}", val);
success = success && (val == 0xdeadbeef);- In
Io.Read.c:150:
val = 0;
z = "0xDEADBEEF";
StrReadFmt(z, "{}", val);
success = success && (val == 0xDEADBEEF);- In
Io.Read.c:155:
val = 0;
z = "0x0";
StrReadFmt(z, "{}", val);
success = success && (val == 0);- In
Io.Read.c:160:
val = 0;
z = "0xf";
StrReadFmt(z, "{}", val);
success = success && (val == 0xf);- In
Io.Read.c:165:
val = 0;
z = "0xaBcDeF";
StrReadFmt(z, "{}", val);
success = success && (val == 0xabcdef);- In
Io.Read.c:180:
i8 val = 0;
z = "0b101010";
StrReadFmt(z, "{}", val);
success = success && (val == 42);- In
Io.Read.c:185:
val = 0;
z = "0b0";
StrReadFmt(z, "{}", val);
success = success && (val == 0);- In
Io.Read.c:190:
val = 0;
z = "0b1";
StrReadFmt(z, "{}", val);
success = success && (val == 1);- In
Io.Read.c:205:
i32 val = 0;
z = "0o755";
StrReadFmt(z, "{}", val);
success = success && (val == 0755);- In
Io.Read.c:210:
val = 0;
z = "755";
StrReadFmt(z, "{}", val);
success = success && (val == 755);- In
Io.Read.c:215:
val = 0;
z = "0o0";
StrReadFmt(z, "{}", val);
success = success && (val == 0);- In
Io.Read.c:220:
val = 0;
z = "0o7";
StrReadFmt(z, "{}", val);
success = success && (val == 7);- In
Io.Read.c:235:
f32 f32_val = 0.0f;
z = "3.14159";
StrReadFmt(z, "{}", f32_val);
success = success && float_equals(f32_val, 3.14159f);- In
Io.Read.c:240:
f64 f64_val = 0.0;
z = "3.14159265359";
StrReadFmt(z, "{}", f64_val);
success = success && double_equals(f64_val, 3.14159265359);- In
Io.Read.c:245:
f64_val = 1.0;
z = "0.0";
StrReadFmt(z, "{}", f64_val);
success = success && double_equals(f64_val, 0.0);- In
Io.Read.c:250:
f64_val = 1.0;
z = "-0.0";
StrReadFmt(z, "{}", f64_val);
// -0.0 compares == to +0.0; the epsilon check captures the magnitude
// regardless of which sign bit the parser landed on.
- In
Io.Read.c:257:
f64_val = 0.0;
z = "42.0";
StrReadFmt(z, "{}", f64_val);
success = success && double_equals(f64_val, 42.0);- In
Io.Read.c:262:
f64_val = 0.0;
z = "0.42";
StrReadFmt(z, "{}", f64_val);
success = success && double_equals(f64_val, 0.42);- In
Io.Read.c:277:
f64 val = 0.0;
z = "1.23e4";
StrReadFmt(z, "{}", val);
success = success && double_equals(val, 12300.0);- In
Io.Read.c:282:
val = 0.0;
z = "1.23E4";
StrReadFmt(z, "{}", val);
success = success && double_equals(val, 12300.0);- In
Io.Read.c:287:
val = 0.0;
z = "1.23e+4";
StrReadFmt(z, "{}", val);
success = success && double_equals(val, 12300.0);- In
Io.Read.c:292:
val = 0.0;
z = "1.23e-4";
StrReadFmt(z, "{}", val);
success = success && double_equals(val, 0.000123);- In
Io.Read.c:297:
val = 0.0;
z = "1.0e0";
StrReadFmt(z, "{}", val);
success = success && double_equals(val, 1.0);- In
Io.Read.c:302:
val = 0.0;
z = "1.0E-0";
StrReadFmt(z, "{}", val);
success = success && double_equals(val, 1.0);- In
Io.Read.c:307:
val = 0.0;
z = "1.0e+0";
StrReadFmt(z, "{}", val);
success = success && double_equals(val, 1.0);- In
Io.Read.c:325:
Str s = StrInit(&alloc);
z = "Hello";
StrReadFmt(z, "{}", s);
Str expected = StrInitFromZstr("Hello", &alloc);- In
Io.Read.c:333:
z = "\"Hello, World!\"";
StrReadFmt(z, "{s}", s);
expected = StrInitFromZstr("Hello, World!", &alloc);- In
Io.Read.c:343:
z = "Allocator-backed";
StrReadFmt(z, "{s}", ZstrIO(zs, alloc_base));
success = success && (ZstrCompare(zs, "Allocator-backed") == 0);- In
Io.Read.c:347:
z = "\"Allocator-backed replacement\"";
StrReadFmt(z, "{s}", ZstrIO(zs, alloc_base));
success = success && (ZstrCompare(zs, "Allocator-backed replacement") == 0);
zstr_deinit(&zs, alloc_base);- In
Io.Read.c:370:
Str name = StrInit(&alloc);
z = "Count: 42, Name: Alice";
StrReadFmt(z, "Count: {}, Name: {}", num, name);
success = success && (num == 42);- In
Io.Read.c:381:
f64 val = 0.0;
z = "Value: 3.14, Name: Bob";
StrReadFmt(z, "Value: {}, Name: {}", val, name);
success = success && double_equals(val, 3.14);- In
Io.Read.c:406:
i32 num = 42;
z = "Count: forty-two";
StrReadFmt(z, "Count: {}", num);
success = success && (num == 42);- In
Io.Read.c:411:
num = 42;
z = "Count: abc";
StrReadFmt(z, "Count: {}", num);
success = success && (num == 42);- In
Io.Read.c:416:
i8 small = 42;
z = "Value: 1000";
StrReadFmt(z, "Value: {}", small);
success = success && (small == 42);- In
Io.Read.c:433:
u8 u8_val = 0;
z = "A";
StrReadFmt(z, "{c}", u8_val);
WriteFmt("u8_val = {}, expected = {}, pass = {}\n", u8_val, 'A', (u8_val == 'A') ? "true" : "false");
success = success && (u8_val == 'A');- In
Io.Read.c:439:
u8_val = 0;
z = "z";
StrReadFmt(z, "{c}", u8_val);
WriteFmt("u8_val = {}, expected = {}, pass = {}\n", u8_val, 'z', (u8_val == 'z') ? "true" : "false");
success = success && (u8_val == 'z');- In
Io.Read.c:445:
i8 i8_val = 0;
z = "B";
StrReadFmt(z, "{c}", i8_val);
WriteFmt("i8_val = {}, expected = {}, pass = {}\n", i8_val, 'B', (i8_val == 'B') ? "true" : "false");
success = success && (i8_val == 'B');- In
Io.Read.c:451:
i16 i16_val = 0;
z = "C";
StrReadFmt(z, "{c}", i16_val);
WriteFmt("i16_val = {}, expected = {}, pass = {}\n", i16_val, 'C', (i16_val == 'C') ? "true" : "false");
success = success && (i16_val == 'C');- In
Io.Read.c:457:
i32 i32_val = 0;
z = "D";
StrReadFmt(z, "{c}", i32_val);
WriteFmt("i32_val = {}, expected = {}, pass = {}\n", i32_val, 'D', (i32_val == 'D') ? "true" : "false");
success = success && (i32_val == 'D');- In
Io.Read.c:463:
i64 i64_val = 0;
z = "E";
StrReadFmt(z, "{c}", i64_val);
WriteFmt("i64_val = {}, expected = {}, pass = {}\n", i64_val, 'E', (i64_val == 'E') ? "true" : "false");
success = success && (i64_val == 'E');- In
Io.Read.c:469:
u16 u16_val = 0;
z = "F";
StrReadFmt(z, "{c}", u16_val);
WriteFmt("u16_val = {}, expected = {}, pass = {}\n", u16_val, 'F', (u16_val == 'F') ? "true" : "false");
success = success && (u16_val == 'F');- In
Io.Read.c:475:
u32 u32_val = 0;
z = "G";
StrReadFmt(z, "{c}", u32_val);
WriteFmt("u32_val = {}, expected = {}, pass = {}\n", u32_val, 'G', (u32_val == 'G') ? "true" : "false");
success = success && (u32_val == 'G');- In
Io.Read.c:481:
u64 u64_val = 0;
z = "H";
StrReadFmt(z, "{c}", u64_val);
WriteFmt("u64_val = {}, expected = {}, pass = {}\n", u64_val, 'H', (u64_val == 'H') ? "true" : "false");
success = success && (u64_val == 'H');- In
Io.Read.c:487:
u16_val = 0;
z = "AB";
StrReadFmt(z, "{c}", u16_val);
bool u16_multi_pass = (ZstrCompareN((Zstr)&u16_val, "AB", 2) == 0);
WriteFmt("u16_val multi-char test: comparing memory with 'AB', pass = {}\n", u16_multi_pass ? "true" : "false");- In
Io.Read.c:501:
i16_val = 0;
z = "CD";
StrReadFmt(z, "{c}", i16_val);
bool i16_multi_pass = (ZstrCompareN((Zstr)&i16_val, "CD", 2) == 0);
WriteFmt("i16_val multi-char test: comparing memory with 'CD', pass = {}\n", i16_multi_pass ? "true" : "false");- In
Io.Read.c:508:
u32_val = 0;
z = "EFGH";
StrReadFmt(z, "{c}", u32_val);
bool u32_multi_pass = (ZstrCompareN((Zstr)&u32_val, "EFGH", 4) == 0);
WriteFmt("u32_val multi-char test: comparing memory with 'EFGH', pass = {}\n", u32_multi_pass ? "true" : "false");- In
Io.Read.c:515:
i32_val = 0;
z = "IJKL";
StrReadFmt(z, "{c}", i32_val);
bool i32_multi_pass = (ZstrCompareN((Zstr)&i32_val, "IJKL", 4) == 0);
WriteFmt("i32_val multi-char test: comparing memory with 'IJKL', pass = {}\n", i32_multi_pass ? "true" : "false");- In
Io.Read.c:522:
u64_val = 0;
z = "MNOPQRST";
StrReadFmt(z, "{c}", u64_val);
bool u64_multi_pass = (ZstrCompareN((Zstr)&u64_val, "MNOPQRST", 8) == 0);
WriteFmt(- In
Io.Read.c:532:
i64_val = 0;
z = "UVWXYZab";
StrReadFmt(z, "{c}", i64_val);
bool i64_multi_pass = (ZstrCompareN((Zstr)&i64_val, "UVWXYZab", 8) == 0);
WriteFmt(- In
Io.Read.c:542:
f32 f32_val = 0.0f;
z = "A";
StrReadFmt(z, "{c}", f32_val);
bool f32_pass = (f32_val == (f32)'A');
WriteFmt("f32_val = {}, expected = {}, pass = {}\n", f32_val, (f32)'A', f32_pass ? "true" : "false");- In
Io.Read.c:549:
f64 f64_val = 0.0;
z = "B";
StrReadFmt(z, "{c}", f64_val);
bool f64_pass = (f64_val == (f64)'B');
WriteFmt("f64_val = {}, expected = {}, pass = {}\n", f64_val, (f64)'B', f64_pass ? "true" : "false");- In
Io.Read.c:556:
u8_val = 0;
z = "~";
StrReadFmt(z, "{c}", u8_val);
bool tilde_pass = (u8_val == '~');
WriteFmt("u8_val = {}, expected = {} (~), pass = {}\n", u8_val, '~', tilde_pass ? "true" : "false");- In
Io.Read.c:563:
u32_val = 0;
z = "XY";
StrReadFmt(z, "{c}", u32_val);
bool xy_pass = (ZstrCompareN((Zstr)&u32_val, "XY", 2) == 0);
WriteFmt("u32_val partial test: comparing memory with 'XY', pass = {}\n", xy_pass ? "true" : "false");- In
Io.Read.c:570:
u64_val = 0;
z = "abc";
StrReadFmt(z, "{c}", u64_val);
bool abc_pass = (ZstrCompareN((Zstr)&u64_val, "abc", 3) == 0);
WriteFmt("u64_val partial test: comparing memory with 'abc', pass = {}\n", abc_pass ? "true" : "false");- In
Io.Read.c:577:
Str str_val = StrInit(&alloc);
z = "Hello";
StrReadFmt(z, "{c}", str_val);
Str expected = StrInitFromZstr("Hello", &alloc);
bool str_pass = (StrCmp(&str_val, &expected) == 0);- In
Io.Read.c:587:
str_val = StrInit(&alloc);
z = "\"World\"";
StrReadFmt(z, "{cs}", str_val);
expected = StrInitFromZstr("World", &alloc);
bool quoted_str_pass = (StrCmp(&str_val, &expected) == 0);- In
Io.Read.c:615:
z = in;
StrReadFmt(z, "{a}", result);
WriteFmt("Test 1 - :a (lowercase)\n");- In
Io.Read.c:640:
z = in;
StrReadFmt(z, "{as}", result);
WriteFmt("Test 1.1 - :as (lowercase string single word)\n");- In
Io.Read.c:665:
z = in;
StrReadFmt(z, "{A}", result);
WriteFmt("Test 2 - :A (uppercase)\n");- In
Io.Read.c:691:
z = in;
StrReadFmt(z, "{A} {A}", result1, result2);
WriteFmt("Test 2 - :A (uppercase with split format)\n");- In
Io.Read.c:712:
z = in;
StrReadFmt(z, "{As}{A}", result1, result2);
// result1 must consume first word only
// result2 must consume the space after hello and then everything after it
- In
Io.Read.c:734:
z = in;
StrReadFmt(z, "{as}", result);
WriteFmt("Test 3 - :a with quoted string\n");- In
Io.Read.c:759:
z = in;
StrReadFmt(z, "{As}", result);
WriteFmt("Test 4 - :A with mixed alphanumeric\n");- In
Io.Read.c:784:
z = in;
StrReadFmt(z, "{c}", result);
WriteFmt("Test 5 - :c (no case conversion)\n");- In
Io.Read.c:820:
BitVec bv1 = BitVecInit(alloc_base);
z = "10110";
StrReadFmt(z, "{}", bv1);
Str result1 = BitVecToStr(&bv1);
success = success && (ZstrCompare(StrBegin(&result1), "10110") == 0);- In
Io.Read.c:833:
BitVec bv2 = BitVecInit(alloc_base);
z = "0xDEAD";
StrReadFmt(z, "{}", bv2);
u64 value2 = BitVecToInteger(&bv2);
success = success && (value2 == 0xDEAD);- In
Io.Read.c:841:
BitVec bv3 = BitVecInit(alloc_base);
z = "0o755";
StrReadFmt(z, "{}", bv3);
u64 value3 = BitVecToInteger(&bv3);
success = success && (value3 == 0755);- In
Io.Read.c:849:
BitVec bv4 = BitVecInit(alloc_base);
z = " 1101";
StrReadFmt(z, "{}", bv4);
Str result4 = BitVecToStr(&bv4);
success = success && (ZstrCompare(StrBegin(&result4), "1101") == 0);- In
Io.Read.c:862:
BitVec bv5 = BitVecInit(alloc_base);
z = "0";
StrReadFmt(z, "{}", bv5);
Str result5 = BitVecToStr(&bv5);
success = success && (ZstrCompare(StrBegin(&result5), "0") == 0);- In
Io.Read.c:898:
z = "123456789012345678901234567890";
StrReadFmt(z, "{}", dec);
dec_text = IntToStr(&dec);
success = success && (ZstrCompare(StrBegin(&dec_text), "123456789012345678901234567890") == 0);- In
Io.Read.c:903:
z = "deadbeefcafebabe1234";
StrReadFmt(z, "{x}", hex);
hex_text = IntToHexStr(&hex);
success = success && (ZstrCompare(StrBegin(&hex_text), "deadbeefcafebabe1234") == 0);- In
Io.Read.c:908:
z = "10100011";
StrReadFmt(z, "{b}", bin);
bin_text = IntToBinary(&bin);
success = success && (ZstrCompare(StrBegin(&bin_text), "10100011") == 0);- In
Io.Read.c:913:
z = "755";
StrReadFmt(z, "{o}", oct);
oct_text = IntToOctStr(&oct);
success = success && (ZstrCompare(StrBegin(&oct_text), "755") == 0);- In
Io.Read.c:948:
z = "1234567890.012345";
StrReadFmt(z, "{}", dec);
dec_text = FloatToStr(&dec);
success = success && (ZstrCompare(StrBegin(&dec_text), "1234567890.012345") == 0);- In
Io.Read.c:953:
z = "1.234567e+04";
StrReadFmt(z, "{e}", sci);
sci_text = FloatToStr(&sci);
success = success && (ZstrCompare(StrBegin(&sci_text), "12345.67") == 0);- In
Io.Read.c:958:
z = "-0.00125";
StrReadFmt(z, "{}", neg);
neg_text = FloatToStr(&neg);
success = success && (ZstrCompare(StrBegin(&neg_text), "-0.00125") == 0);- In
Proc.h:289:
ProcReadFromStdout((p), &UNPL(buf)); \
Zstr UNPL(in) = StrBegin(&UNPL(buf)); \
StrReadFmt(UNPL(in), __VA_ARGS__); \
StrDeinit(&UNPL(buf)); \
} while (0)- In
Proc.h:316:
ProcReadFromStderr((p), &UNPL(buf)); \
Zstr UNPL(in) = StrBegin(&UNPL(buf)); \
StrReadFmt(UNPL(in), __VA_ARGS__); \
StrDeinit(&UNPL(buf)); \
} while (0)
Last updated on