diff --git a/std/conv.d b/std/conv.d index 6c0e0158d..9c7d914fa 100644 --- a/std/conv.d +++ b/std/conv.d @@ -2470,7 +2470,8 @@ if (isIntegral!Target && !is(Target == enum) && alias source = s; } - size_t count = 0; + static if (doCount) + size_t count = 0; if (source.empty) goto Lerr; @@ -2485,7 +2486,8 @@ if (isIntegral!Target && !is(Target == enum) && sign = true; goto case '+'; case '+': - ++count; + static if (doCount) + ++count; source.popFront(); if (source.empty) @@ -2504,7 +2506,8 @@ if (isIntegral!Target && !is(Target == enum) && { Target v = cast(Target) c; - ++count; + static if (doCount) + ++count; source.popFront(); while (!source.empty) @@ -2520,7 +2523,8 @@ if (isIntegral!Target && !is(Target == enum) && // Note: `v` can become negative here in case of parsing // the most negative value: v = cast(Target) (v * 10 + c); - ++count; + static if (doCount) + ++count; source.popFront(); } else @@ -2877,7 +2881,8 @@ do alias s = source; } - size_t count = 0; + static if (doCount) + size_t count = 0; auto found = false; do { @@ -2904,7 +2909,8 @@ do auto nextv = v.mulu(radix, overflow).addu(c - '0', overflow); enforce!ConvOverflowException(!overflow && nextv <= Target.max, "Overflow in integral conversion"); v = cast(Target) nextv; - ++count; + static if (doCount) + ++count; s.popFront(); found = true; } while (!s.empty); @@ -3163,36 +3169,35 @@ if (isFloatingPoint!Target && !is(Target == enum) && enforce(!p.empty, bailOut()); - size_t count = 0; bool sign = false; switch (p.front) { case '-': sign = true; - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty, bailOut()); if (toLower(p.front) == 'i') goto case 'i'; break; case '+': - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty, bailOut()); break; case 'i': case 'I': // inf - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty && toUpper(p.front) == 'N', bailOut("error converting input to floating point")); - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty && toUpper(p.front) == 'F', bailOut("error converting input to floating point")); // skip past the last 'f' - ++count; + static if (doCount) ++count; p.popFront(); advanceSource(); static if (doCount) @@ -3210,7 +3215,7 @@ if (isFloatingPoint!Target && !is(Target == enum) && bool startsWithZero = p.front == '0'; if (startsWithZero) { - ++count; + static if (doCount) ++count; p.popFront(); if (p.empty) { @@ -3228,23 +3233,23 @@ if (isFloatingPoint!Target && !is(Target == enum) && isHex = p.front == 'x' || p.front == 'X'; if (isHex) { - ++count; + static if (doCount) ++count; p.popFront(); } } else if (toLower(p.front) == 'n') { // nan - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty && toUpper(p.front) == 'A', bailOut("error converting input to floating point")); - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty && toUpper(p.front) == 'N', bailOut("error converting input to floating point")); // skip past the last 'n' - ++count; + static if (doCount) ++count; p.popFront(); advanceSource(); static if (doCount) @@ -3332,14 +3337,14 @@ if (isFloatingPoint!Target && !is(Target == enum) && exp += expIter; } exp -= dot; - ++count; + static if (doCount) ++count; p.popFront(); if (p.empty) break; i = p.front; if (i == '_') { - ++count; + static if (doCount) ++count; p.popFront(); if (p.empty) break; @@ -3348,7 +3353,7 @@ if (isFloatingPoint!Target && !is(Target == enum) && } if (i == '.' && !dot) { - ++count; + static if (doCount) ++count; p.popFront(); dot += expIter; } @@ -3373,14 +3378,14 @@ if (isFloatingPoint!Target && !is(Target == enum) && char sexp = 0; int e = 0; - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty, new ConvException("Unexpected end of input")); switch (p.front) { case '-': sexp++; goto case; - case '+': ++count; + case '+': static if (doCount) ++count; p.popFront(); break; default: {} @@ -3392,7 +3397,7 @@ if (isFloatingPoint!Target && !is(Target == enum) && { e = e * 10 + p.front - '0'; } - ++count; + static if (doCount) ++count; p.popFront(); sawDigits = true; } @@ -4098,7 +4103,12 @@ if (isDynamicArray!Target && !is(Target == enum) && auto result = appender!Target(); parseCheck!s(lbracket); - size_t count = 1 + skipWS!(Source, Yes.doCount)(s); + static if (doCount) + size_t count = 1; + static if (doCount) + count += skipWS!(Source, Yes.doCount)(s); + else + skipWS!(Source, No.doCount)(s); if (s.empty) throw convError!(Source, Target)(s); if (s.front == rbracket) @@ -4106,36 +4116,54 @@ if (isDynamicArray!Target && !is(Target == enum) && s.popFront(); static if (doCount) { - return tuple!("data", "count")(result.data, ++count); + ++count; + return tuple!("data", "count")(result.data, count); } else { return result.data; } } - for (;; s.popFront(), count += 1 + skipWS!(Source, Yes.doCount)(s)) + for (;;) { if (!s.empty && s.front == rbracket) break; - auto r = parseElement!(WideElementType!Target, Source, Yes.doCount)(s); - result ~= r.data; - count += r.count + skipWS!(Source, Yes.doCount)(s); + static if (doCount) + { + auto r = parseElement!(WideElementType!Target, Source, Yes.doCount)(s); + result ~= r.data; + count += r.count; + count += skipWS!(Source, Yes.doCount)(s); + } + else + { + auto r = parseElement!(WideElementType!Target, Source, No.doCount)(s); + result ~= r; + skipWS!(Source, No.doCount)(s); + } if (s.empty) throw convError!(Source, Target)(s); if (s.front != comma) break; + s.popFront(); + static if (doCount) + ++count; + static if (doCount) + count += skipWS!(Source, Yes.doCount)(s); + else + skipWS!(Source, No.doCount)(s); } parseCheck!s(rbracket); static if (doCount) { - return tuple!("data", "count")(result.data, ++count); + ++count; + return tuple!("data", "count")(result.data, count); } else { return result.data; } } - /// @safe pure unittest { @@ -4286,7 +4314,12 @@ if (isStaticArray!Target && !is(Target == enum) && Target result = void; parseCheck!s(lbracket); - size_t count = 1 + skipWS!(Source, Yes.doCount)(s); + static if (doCount) + size_t count = 1; + static if (doCount) + count += skipWS!(Source, Yes.doCount)(s); + else + skipWS!(Source, No.doCount)(s); if (s.empty) throw convError!(Source, Target)(s); if (s.front == rbracket) @@ -4298,7 +4331,8 @@ if (isStaticArray!Target && !is(Target == enum) && s.popFront(); static if (doCount) { - return tuple!("data", "count")(result, ++count); + ++count; + return tuple!("data", "count")(result, count); } else { @@ -4306,13 +4340,23 @@ if (isStaticArray!Target && !is(Target == enum) && } } } - for (size_t i = 0; ; s.popFront(), count += 1 + skipWS!(Source, Yes.doCount)(s)) + for (size_t i = 0; ; ) { if (i == result.length) goto Lmanyerr; - auto r = parseElement!(ElementType!Target, Source, Yes.doCount)(s); - result[i++] = r.data; - count += r.count + skipWS!(Source, Yes.doCount)(s); + static if (doCount) + { + auto r = parseElement!(ElementType!Target, Source, Yes.doCount)(s); + result[i++] = r.data; + count += r.count; + count += skipWS!(Source, Yes.doCount)(s); + } + else + { + auto r = parseElement!(ElementType!Target, Source, No.doCount)(s); + result[i++] = r; + skipWS!(Source, No.doCount)(s); + } if (s.empty) throw convError!(Source, Target)(s); if (s.front != comma) @@ -4321,21 +4365,27 @@ if (isStaticArray!Target && !is(Target == enum) && goto Lfewerr; break; } + s.popFront(); + static if (doCount) + ++count; + static if (doCount) + count += skipWS!(Source, Yes.doCount)(s); + else + skipWS!(Source, No.doCount)(s); } parseCheck!s(rbracket); static if (doCount) { - return tuple!("data", "count")(result, ++count); + ++count; + return tuple!("data", "count")(result, count); } else { return result; } - Lmanyerr: throw parseError(text("Too many elements in input, ", result.length, " elements expected.")); - Lfewerr: throw parseError(text("Too few elements in input, ", result.length, " elements expected.")); } @@ -4393,46 +4443,60 @@ if (isAssociativeArray!Target && !is(Target == enum) && alias ValType = typeof(Target.init.values[0]); Target result; + static if (doCount) size_t count; parseCheck!s(lbracket); - size_t count = 1 + skipWS!(Source, Yes.doCount)(s); + static if (doCount) + count = 1 + skipWS!(Source, Yes.doCount)(s); + else + skipWS!(Source, No.doCount)(s); if (s.empty) throw convError!(Source, Target)(s); if (s.front == rbracket) { s.popFront(); + static if (doCount) + return tuple!("data", "count")(result, count + 1); + else + return result; + } + for (;;) + { static if (doCount) { - return tuple!("data", "count")(result, ++count); + auto key = parseElement!(KeyType, Source, Yes.doCount)(s); + count += key.count + skipWS!(Source, Yes.doCount)(s); + parseCheck!s(keyval); + count += 1 + skipWS!(Source, Yes.doCount)(s); + auto val = parseElement!(ValType, Source, Yes.doCount)(s); + count += val.count + skipWS!(Source, Yes.doCount)(s); + result[key.data] = val.data; } else { - return result; + auto key = parseElement!(KeyType, Source, No.doCount)(s); + skipWS!(Source, No.doCount)(s); + parseCheck!s(keyval); + skipWS!(Source, No.doCount)(s); + auto val = parseElement!(ValType, Source, No.doCount)(s); + skipWS!(Source, No.doCount)(s); + result[key] = val; } - } - for (;; s.popFront(), count += 1 + skipWS!(Source, Yes.doCount)(s)) - { - auto key = parseElement!(KeyType, Source, Yes.doCount)(s); - count += key.count + skipWS!(Source, Yes.doCount)(s); - parseCheck!s(keyval); - count += 1 + skipWS!(Source, Yes.doCount)(s); - auto val = parseElement!(ValType, Source, Yes.doCount)(s); - count += val.count + skipWS!(Source, Yes.doCount)(s); - result[key.data] = val.data; if (s.empty) throw convError!(Source, Target)(s); if (s.front != comma) break; + s.popFront(); + static if (doCount) + count += 1 + skipWS!(Source, Yes.doCount)(s); + else + skipWS!(Source, No.doCount)(s); } parseCheck!s(rbracket); static if (doCount) - { - return tuple!("data", "count")(result, ++count); - } + return tuple!("data", "count")(result, count + 1); else - { return result; - } } /// @@ -4489,7 +4553,9 @@ private auto parseEscape(Source, Flag!"doCount" doCount = No.doCount)(ref Source if (isInputRange!Source && isSomeChar!(ElementType!Source)) { parseCheck!s('\\'); - size_t count = 1; + size_t count; + static if (doCount) + count = 1; if (s.empty) throw parseError("Unterminated escape sequence"); @@ -4507,15 +4573,15 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source)) throw parseError("Hex digit is missing"); return isAlpha(c) ? ((c & ~0x20) - ('A' - 10)) : c - '0'; } - // We need to do octals separate, because they need a lookahead to find out, // where the escape sequence ends. auto first = s.front; if (first >= '0' && first <= '7') { dchar c1 = s.front; - ++count; s.popFront(); + static if (doCount) + ++count; if (s.empty) { static if (doCount) @@ -4539,8 +4605,9 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source)) return cast (dchar)(c1 - '0'); } } - ++count; s.popFront(); + static if (doCount) + ++count; dchar c3 = s.front; if (c3 < '0' || c3 > '7') { @@ -4553,8 +4620,9 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source)) return cast (dchar) (8 * (c1 - '0') + (c2 - '0')); } } - ++count; s.popFront(); + static if (doCount) + ++count; if (c1 > '3') throw parseError("Octal sequence is larger than \\377"); static if (doCount) @@ -4585,14 +4653,16 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source)) case 'x': result = getHexDigit() << 4; result |= getHexDigit(); - count += 2; + static if (doCount) + count += 2; break; case 'u': result = getHexDigit() << 12; result |= getHexDigit() << 8; result |= getHexDigit() << 4; result |= getHexDigit(); - count += 4; + static if (doCount) + count += 4; break; case 'U': result = getHexDigit() << 28; @@ -4603,7 +4673,8 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source)) result |= getHexDigit() << 8; result |= getHexDigit() << 4; result |= getHexDigit(); - count += 8; + static if (doCount) + count += 8; break; default: throw parseError("Unknown escape character " ~ to!string(s.front)); @@ -4643,7 +4714,6 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source)) // https://issues.dlang.org/show_bug.cgi?id=9621 (Named Character Entities) //'\&', '\"', ]; - foreach (i ; 0 .. s1.length) { assert(s2[i] == parseEscape(s1[i])); @@ -4696,7 +4766,9 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum } parseCheck!s('\"'); - size_t count = 1; + size_t count; + static if (doCount) + count = 1; if (s.empty) throw convError!(Source, Target)(s); if (s.front == '\"') @@ -4704,13 +4776,13 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum s.popFront(); static if (doCount) { - return tuple!("data", "count")(result.data, ++count); + count++; + return tuple!("data", "count")(result.data, count); } else { return result.data; } - } while (true) { @@ -4722,20 +4794,30 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum s.popFront(); static if (doCount) { - return tuple!("data", "count")(result.data, ++count); + count++; + return tuple!("data", "count")(result.data, count); } else { return result.data; } case '\\': - auto r = parseEscape!(typeof(s), Yes.doCount)(s); - result.put(r[0]); - count += r[1]; + static if (doCount) + { + auto r = parseEscape!(typeof(s), Yes.doCount)(s); + result.put(r[0]); + count += r[1]; + } + else + { + auto r = parseEscape!(typeof(s), No.doCount)(s); + result.put(r); + } break; default: result.put(s.front); - ++count; + static if (doCount) + count++; s.popFront(); break; } @@ -4751,21 +4833,30 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum Unqual!Target c; parseCheck!s('\''); - size_t count = 1; + size_t count; + static if (doCount) + count = 1; if (s.empty) throw convError!(Source, Target)(s); - ++count; // for the following if-else sequence + static if (doCount) + count++; if (s.front != '\\') { c = s.front; s.popFront(); } else - c = parseEscape(s); + { + static if (doCount) + c = parseEscape!(typeof(s), Yes.doCount)(s).data; + else + c = parseEscape!(typeof(s), No.doCount)(s); + } parseCheck!s('\''); static if (doCount) { - return tuple!("data", "count")(c, ++count); + count++; + return tuple!("data", "count")(c, count); } else {