From 17d13e20666d388aba04357d98f7ed092b58bccb Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Tue, 1 Nov 2016 13:58:07 +0200 Subject: [PATCH] Issue 5236 - [patch] std.format.formattedRead/unformatValue does not support the raw reading of integer types --- std/format.d | 104 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 36 deletions(-) diff --git a/std/format.d b/std/format.d index fa1a11690..cfd4cbf1d 100644 --- a/std/format.d +++ b/std/format.d @@ -4302,7 +4302,7 @@ T unformatValue(T, Range, Char)(ref Range input, ref FormatSpec!Char spec) import std.conv : parse, text; if (spec.spec == 's') { - return parse!T(input); + static if(__traits(compiles, parse!T(input)) ) return parse!T(input); } enforce(find(acceptedSpecs!long, spec.spec).length, text("Wrong unformat specifier '%", spec.spec , "' for ", T.stringof)); @@ -4359,7 +4359,38 @@ T unformatValue(T, Range, Char)(ref Range input, ref FormatSpec!Char spec) enforce(spec.spec == 's', text("Wrong unformat specifier '%", spec.spec , "' for ", T.stringof)); - return parse!T(input); + static if(__traits(compiles, parse!T(input)) ) return parse!T(input); +} + +private T rawReadWrapper(T, Range)(ref Range input) +{ + enforce( + isSomeString!Range || ElementType!(Range).sizeof == 1, + "Cannot parse input of type %s".format(Range.stringof) + ); + union X + { + ubyte[T.sizeof] raw; + T typed; + } + X x; + foreach (i; 0 .. T.sizeof) + { + static if (isSomeString!Range) + { + x.raw[i] = input[0]; + input = input[1 .. $]; + } + else + { + // TODO: recheck this + x.raw[i] = cast(ubyte) input.front; + input.popFront(); + } + } + + return x.typed; + } /** @@ -4368,6 +4399,7 @@ T unformatValue(T, Range, Char)(ref Range input, ref FormatSpec!Char spec) T unformatValue(T, Range, Char)(ref Range input, ref FormatSpec!Char spec) if (isInputRange!Range && isIntegral!T && !is(T == enum)) { + import std.algorithm.searching : find; import std.conv : parse, text; enforce(find(acceptedSpecs!T, spec.spec).length, @@ -4381,7 +4413,31 @@ T unformatValue(T, Range, Char)(ref Range input, ref FormatSpec!Char spec) spec.spec == 'b' ? 2 : spec.spec == 's' || spec.spec == 'd' || spec.spec == 'u' ? 10 : 0; assert(base != 0); - return parse!T(input, base); + + // raw read + //enforce(input.length >= T.sizeof); + if (spec.spec == 'r') return rawReadWrapper!T(input); + + enforce(find(acceptedSpecs!T, spec.spec).length, + text("Wrong unformat specifier '%", spec.spec , "' for ", T.stringof)); + + static if(__traits(compiles, parse!T(input, base)) ) return parse!T(input, base); + +} + +version(none)unittest +{ + union B + { + char[int.sizeof] untyped; + int typed; + } + B b; + b.typed = 5; + char[] input = b.untyped[]; + int witness; + formattedRead(input, "%r", &witness); + assert(witness == b.typed); } /** @@ -4392,40 +4448,16 @@ T unformatValue(T, Range, Char)(ref Range input, ref FormatSpec!Char spec) { import std.algorithm.searching : find; import std.conv : parse, text; - if (spec.spec == 'r') - { - // raw read - //enforce(input.length >= T.sizeof); - enforce( - isSomeString!Range || ElementType!(Range).sizeof == 1, - "Cannot parse input of type %s".format(Range.stringof) - ); - union X - { - ubyte[T.sizeof] raw; - T typed; - } - X x; - foreach (i; 0 .. T.sizeof) - { - static if (isSomeString!Range) - { - x.raw[i] = input[0]; - input = input[1 .. $]; - } - else - { - // TODO: recheck this - x.raw[i] = cast(ubyte) input.front; - input.popFront(); - } - } - return x.typed; - } + + + // raw read + //enforce(input.length >= T.sizeof); + if (spec.spec == 'r') return rawReadWrapper!T(input); + enforce(find(acceptedSpecs!T, spec.spec).length, text("Wrong unformat specifier '%", spec.spec , "' for ", T.stringof)); - return parse!T(input); + static if(__traits(compiles, parse!T(input)) ) return parse!T(input); } version(none)unittest @@ -4600,7 +4632,7 @@ T unformatValue(T, Range, Char)(ref Range input, ref FormatSpec!Char spec) enforce(spec.spec == 's', text("Wrong unformat specifier '%", spec.spec , "' for ", T.stringof)); - return parse!T(input); + static if(__traits(compiles, parse!T(input)) ) return parse!T(input); } @system pure unittest @@ -4694,7 +4726,7 @@ T unformatValue(T, Range, Char)(ref Range input, ref FormatSpec!Char spec) enforce(spec.spec == 's', text("Wrong unformat specifier '%", spec.spec , "' for ", T.stringof)); - return parse!T(input); + static if(__traits(compiles, parse!T(input)) ) return parse!T(input); } @system pure unittest