| @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); |
| } |
| |