@@ -4300,10 +4300,9 @@ T unformatValue(T, Range, Char)(ref Range input, ref FormatSpec!Char spec)
4300
4300
{
4301
4301
import std.algorithm.searching : find;
4302
4302
import std.conv : parse, text;
4303
- if (spec.spec == ' s' )
4304
- {
4305
- return parse! T(input);
4306
- }
4303
+
4304
+ if (spec.spec == ' s' ) return parse! T(input);
4305
+
4307
4306
enforce(find(acceptedSpecs! long , spec.spec).length,
4308
4307
text(" Wrong unformat specifier '%" , spec.spec , " ' for " , T.stringof));
4309
4308
@@ -4362,14 +4361,58 @@ T unformatValue(T, Range, Char)(ref Range input, ref FormatSpec!Char spec)
4362
4361
return parse! T(input);
4363
4362
}
4364
4363
4364
+ /**
4365
+ * Function that performs raw reading. Used by unformatValue
4366
+ * for integral and float types.
4367
+ */
4368
+ private T rawRead (T, Range )(ref Range input)
4369
+ if (is (Unqual! (ElementEncodingType! Range ) == char )
4370
+ || is (Unqual! (ElementEncodingType! Range ) == byte )
4371
+ || is (Unqual! (ElementEncodingType! Range ) == ubyte ))
4372
+ {
4373
+ union X
4374
+ {
4375
+ ubyte [T.sizeof] raw;
4376
+ T typed;
4377
+ }
4378
+ X x;
4379
+ foreach (i; 0 .. T.sizeof)
4380
+ {
4381
+ static if (isSomeString! Range )
4382
+ {
4383
+ x.raw[i] = input[0 ];
4384
+ input = input[1 .. $];
4385
+ }
4386
+ else
4387
+ {
4388
+ // TODO: recheck this
4389
+ x.raw[i] = input.front;
4390
+ input.popFront();
4391
+ }
4392
+ }
4393
+ return x.typed;
4394
+ }
4395
+
4365
4396
/**
4366
4397
Reads an integral value and returns it.
4367
4398
*/
4368
4399
T unformatValue (T, Range , Char)(ref Range input, ref FormatSpec! Char spec)
4369
- if (isInputRange! Range && isIntegral! T && ! is (T == enum ))
4400
+ if (isInputRange! Range && isIntegral! T && ! is (T == enum ) && isSomeChar ! (ElementType ! Range ) )
4370
4401
{
4402
+
4371
4403
import std.algorithm.searching : find;
4372
4404
import std.conv : parse, text;
4405
+
4406
+ if (spec.spec == ' r' )
4407
+ {
4408
+ static if (is (Unqual! (ElementEncodingType! Range ) == char )
4409
+ || is (Unqual! (ElementEncodingType! Range ) == byte )
4410
+ || is (Unqual! (ElementEncodingType! Range ) == ubyte ))
4411
+ return rawRead! T(input);
4412
+ else
4413
+ throw new Exception (" The raw read specifier %r may only be used with narrow strings and ranges of bytes." );
4414
+ }
4415
+
4373
4416
enforce(find(acceptedSpecs! T, spec.spec).length,
4374
4417
text(" Wrong unformat specifier '%" , spec.spec , " ' for " , T.stringof));
4375
4418
@@ -4381,54 +4424,52 @@ T unformatValue(T, Range, Char)(ref Range input, ref FormatSpec!Char spec)
4381
4424
spec.spec == ' b' ? 2 :
4382
4425
spec.spec == ' s' || spec.spec == ' d' || spec.spec == ' u' ? 10 : 0 ;
4383
4426
assert (base != 0 );
4427
+
4384
4428
return parse! T(input, base);
4429
+
4430
+ }
4431
+
4432
+ unittest
4433
+ {
4434
+ union B
4435
+ {
4436
+ char [int .sizeof] untyped;
4437
+ int typed;
4438
+ }
4439
+ B b;
4440
+ b.typed = 5 ;
4441
+ char [] input = b.untyped[];
4442
+ int witness;
4443
+ formattedRead(input, " %r" , &witness);
4444
+ assert (witness == b.typed);
4385
4445
}
4386
4446
4387
4447
/**
4388
4448
Reads a floating-point value and returns it.
4389
4449
*/
4390
4450
T unformatValue (T, Range , Char)(ref Range input, ref FormatSpec! Char spec)
4391
- if (isFloatingPoint! T && ! is (T == enum ))
4451
+ if (isFloatingPoint! T && ! is (T == enum ) && isInputRange ! Range && isSomeChar ! (ElementType ! Range ) && ! is ( Range == enum ) )
4392
4452
{
4393
4453
import std.algorithm.searching : find;
4394
4454
import std.conv : parse, text;
4455
+
4395
4456
if (spec.spec == ' r' )
4396
4457
{
4397
- // raw read
4398
- // enforce(input.length >= T.sizeof);
4399
- enforce(
4400
- isSomeString! Range || ElementType! (Range ).sizeof == 1 ,
4401
- " Cannot parse input of type %s" .format(Range .stringof)
4402
- );
4403
- union X
4404
- {
4405
- ubyte [T.sizeof] raw;
4406
- T typed;
4407
- }
4408
- X x;
4409
- foreach (i; 0 .. T.sizeof)
4410
- {
4411
- static if (isSomeString! Range )
4412
- {
4413
- x.raw[i] = input[0 ];
4414
- input = input[1 .. $];
4415
- }
4416
- else
4417
- {
4418
- // TODO: recheck this
4419
- x.raw[i] = cast (ubyte ) input.front;
4420
- input.popFront();
4421
- }
4422
- }
4423
- return x.typed;
4458
+ static if (is (Unqual! (ElementEncodingType! Range ) == char )
4459
+ || is (Unqual! (ElementEncodingType! Range ) == byte )
4460
+ || is (Unqual! (ElementEncodingType! Range ) == ubyte ))
4461
+ return rawRead! T(input);
4462
+ else
4463
+ throw new Exception (" The raw read specifier %r may only be used with narrow strings and ranges of bytes." );
4424
4464
}
4465
+
4425
4466
enforce(find(acceptedSpecs! T, spec.spec).length,
4426
4467
text(" Wrong unformat specifier '%" , spec.spec , " ' for " , T.stringof));
4427
4468
4428
4469
return parse! T(input);
4429
4470
}
4430
4471
4431
- version ( none ) unittest
4472
+ unittest
4432
4473
{
4433
4474
union A
4434
4475
{
@@ -4470,7 +4511,7 @@ version(none)unittest
4470
4511
* Reads one character and returns it.
4471
4512
*/
4472
4513
T unformatValue (T, Range , Char)(ref Range input, ref FormatSpec! Char spec)
4473
- if (isInputRange! Range && isSomeChar! T && ! is (T == enum ))
4514
+ if (isInputRange! Range && isSomeChar! T && ! is (T == enum ) && isSomeChar ! (ElementType ! Range ) )
4474
4515
{
4475
4516
import std.algorithm.searching : find;
4476
4517
import std.conv : to, text;
0 commit comments