1 /**
2  * Parsing from string to standard types.
3  */
4 module bc..string.conv;
5 
6 import bc.string.ascii;
7 import bc.core.intrinsics;
8 import std.traits;
9 
10 alias cstring = const(char)[];
11 
12 //TODO: check for owerloads?
13 //TODO: use parseToken to fast check length of input number
14 
15 ParseResult!T parse(T)(cstring str) if (isIntegral!T && !is(T == enum))
16 {
17     pragma(inline, true);
18     if (!str.length) return ParseResult!T.init;
19 
20     size_t count;
21     static if (isSigned!T) {
22          ptrdiff_t res;
23         bool sign;
24         if (str[0] == '-') {
25             sign = true;
26             count++;
27         } else if (str[0] == '+')
28             count++;
29     } else size_t res;
30 
31     for (; count < str.length; ++count)
32     {
33         if (_expect(!str[count].isDigit, false)) return ParseResult!T.init;
34         res = res*10 + (str[count]-'0');
35     }
36 
37     if (_expect(res > T.max, false)) return ParseResult!T.init;
38 
39     static if (isSigned!T) {
40         if (sign) res = -res;
41     }
42     return ParseResult!T(cast(T)res, count);
43 }
44 
45 @safe unittest
46 {
47     assert("42".parse!int == ParseResult!int(42, 2));
48     assert("42".parse!uint == ParseResult!uint(42, 2));
49     assert("-42".parse!int == ParseResult!int(-42, 3));
50     assert("+42".parse!int == ParseResult!int(42, 3));
51 }
52 
53 /// Result of the parse functions
54 struct ParseResult(T)
55 {
56     T data;       /// parsed value
57     size_t count; /// Number of characters consumed while parsing (0 means that input couldn't be parsed into specified type)
58 
59     /// Checks if some data was actually parsed from the input
60     bool opCast(T)() const if(is(T == bool)) { return count > 0; }
61     // alias data this;
62 }