mirror of
https://github.com/dlang/phobos.git
synced 2025-04-26 21:22:20 +03:00
This commit is contained in:
parent
271ae6219d
commit
fd4979ab99
1 changed files with 170 additions and 79 deletions
249
std/conv.d
249
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
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue