| @safe pure unittest | |
| { | |
| import std.format.read; | |
| import std.format.spec : singleSpec; | |
| auto str = "false"; | |
| auto spec = singleSpec("%s"); | |
| assert(str.unformatValue!bool(spec) == false); | |
| str = "1"; | |
| spec = singleSpec("%d"); | |
| assert(str.unformatValue!bool(spec) == true); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| import std.format.spec : singleSpec; | |
| auto str = "null"; | |
| auto spec = singleSpec("%s"); | |
| assert(str.unformatValue!(typeof(null))(spec) == null); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| import std.format.spec : singleSpec; | |
| // signed decimal values | |
| auto str = "123"; | |
| auto spec = singleSpec("%s"); | |
| assert(str.unformatValue!int(spec) == 123); | |
| // hexadecimal values | |
| str = "ABC"; | |
| spec = singleSpec("%X"); | |
| assert(str.unformatValue!int(spec) == 2748); | |
| // octal values | |
| str = "11610"; | |
| spec = singleSpec("%o"); | |
| assert(str.unformatValue!int(spec) == 5000); | |
| // raw read, depends on endianess | |
| str = "\x75\x01"; | |
| spec = singleSpec("%r"); | |
| auto result = str.unformatValue!short(spec); | |
| assert(result == 373 /* little endian */ || result == 29953 /* big endian */ ); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| import std.format.spec : singleSpec; | |
| import std.math.operations : isClose; | |
| // natural notation | |
| auto str = "123.456"; | |
| auto spec = singleSpec("%s"); | |
| assert(str.unformatValue!double(spec).isClose(123.456)); | |
| // scientific notation | |
| str = "1e17"; | |
| spec = singleSpec("%e"); | |
| assert(str.unformatValue!double(spec).isClose(1e17)); | |
| // raw read, depends on endianess | |
| str = "\x40\x00\x00\xBF"; | |
| spec = singleSpec("%r"); | |
| auto result = str.unformatValue!float(spec); | |
| assert(isClose(result, -0.5) /* little endian */ || isClose(result, 2.0) /* big endian */ ); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| import std.format.spec : singleSpec; | |
| // only the first character is read | |
| auto str = "abc"; | |
| auto spec = singleSpec("%s"); | |
| assert(str.unformatValue!char(spec) == 'a'); | |
| // using a numerical format character treats the read number as unicode code point | |
| str = "65"; | |
| spec = singleSpec("%d"); | |
| assert(str.unformatValue!char(spec) == 'A'); | |
| str = "41"; | |
| spec = singleSpec("%x"); | |
| assert(str.unformatValue!char(spec) == 'A'); | |
| str = "10003"; | |
| spec = singleSpec("%d"); | |
| assert(str.unformatValue!dchar(spec) == '✓'); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| import std.format.spec : singleSpec; | |
| // string value | |
| string str = "aaa"; | |
| auto spec = singleSpec("%s"); | |
| assert(str.unformatValue!(dchar[])(spec) == "aaa"d); | |
| // fixed size array with characters | |
| str = "aaa"; | |
| spec = singleSpec("%s"); | |
| dchar[3] ret = ['a', 'a', 'a']; | |
| assert(str.unformatValue!(dchar[3])(spec) == ret); | |
| // dynamic array | |
| str = "[1, 2, 3, 4]"; | |
| spec = singleSpec("%s"); | |
| assert(str.unformatValue!(int[])(spec) == [1, 2, 3, 4]); | |
| // fixed size array with integers | |
| str = "[1, 2, 3, 4]"; | |
| spec = singleSpec("%s"); | |
| int[4] ret2 = [1, 2, 3, 4]; | |
| assert(str.unformatValue!(int[4])(spec) == ret2); | |
| // compound specifiers can be used for more control | |
| str = "1,2,3"; | |
| spec = singleSpec("%(%s,%)"); | |
| assert(str.unformatValue!(int[])(spec) == [1, 2, 3]); | |
| str = "cool"; | |
| spec = singleSpec("%(%c%)"); | |
| assert(str.unformatValue!(char[])(spec) == ['c', 'o', 'o', 'l']); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| import std.format.spec : singleSpec; | |
| // as single value | |
| auto str = `["one": 1, "two": 2]`; | |
| auto spec = singleSpec("%s"); | |
| assert(str.unformatValue!(int[string])(spec) == ["one": 1, "two": 2]); | |
| // with compound specifier for more control | |
| str = "1/1, 2/4, 3/9"; | |
| spec = singleSpec("%(%d/%d%|, %)"); | |
| assert(str.unformatValue!(int[int])(spec) == [1: 1, 2: 4, 3: 9]); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| string object; | |
| char cmp; | |
| int value; | |
| assert(formattedRead("angle < 36", "%s %c %d", object, cmp, value) == 3); | |
| assert(object == "angle"); | |
| assert(cmp == '<'); | |
| assert(value == 36); | |
| // reading may end early: | |
| assert(formattedRead("length >", "%s %c %d", object, cmp, value) == 2); | |
| assert(object == "length"); | |
| assert(cmp == '>'); | |
| // value is not changed: | |
| assert(value == 36); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| string a; | |
| int b; | |
| double c; | |
| assert("hello!124:34.5".formattedRead!"%s!%s:%s"(a, b, c) == 3); | |
| assert(a == "hello"); | |
| assert(b == 124); | |
| assert(c == 34.5); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| string item; | |
| double amount; | |
| assert("orange: (12%) 15.25".formattedRead("%s: (%*d%%) %f", item, amount) == 2); | |
| assert(item == "orange"); | |
| assert(amount == 15.25); | |
| // can also be used with tuples | |
| import std.typecons : Tuple; | |
| Tuple!(int, float) t; | |
| char[] line = "1 7643 2.125".dup; | |
| formattedRead(line, "%s %*u %s", t); | |
| assert(t[0] == 1 && t[1] == 2.125); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| import std.exception : assertThrown; | |
| import std.format : FormatException; | |
| import std.typecons : tuple; | |
| auto complete = "hello!34.5:124".formattedRead!(string, double, int)("%s!%s:%s"); | |
| assert(complete == tuple("hello", 34.5, 124)); | |
| // reading ends early | |
| assertThrown!FormatException("hello!34.5:".formattedRead!(string, double, int)("%s!%s:%s")); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| import std.format : FormatException; | |
| import std.typecons : tuple; | |
| auto result = "orange: (12%) 15.25".formattedRead!(string, double)("%s: (%*d%%) %f"); | |
| assert(result == tuple("orange", 15.25)); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| import std.exception : assertThrown; | |
| import std.format : FormatException; | |
| import std.typecons : tuple; | |
| auto expected = tuple("hello", 124, 34.5); | |
| auto result = "hello!124:34.5".formattedRead!("%s!%s:%s", string, int, double); | |
| assert(result == expected); | |
| assertThrown!FormatException("hello!34.5:".formattedRead!("%s!%s:%s", string, double, int)); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| import std.format : FormatException; | |
| import std.typecons : tuple; | |
| static assert(!__traits(compiles, "orange: (12%) 15.25".formattedRead!("%s: (%*d%%) %f", string, double))); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.format.read; | |
| import std.format.spec : singleSpec; | |
| string s = "42"; | |
| auto spec = singleSpec("%s"); | |
| assert(unformatValue!int(s, spec) == 42); | |
| } | |