Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog.dd
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ $(COMMENT Pending changelog for 2.073. This will get copied to dlang.org and
)

$(BUGSTITLE Library Changes,
$(LI Conversions from strings to number types using $(REF to, std,conv)
and $(REF parse, std,conv) were optimized. On average, integer types
are three times faster, and floating point types are 40% faster.)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change log should be updated. ping @wilzbach . You wanted to change current change log system

)

$(BUGSTITLE Library Changes,
Expand Down
111 changes: 65 additions & 46 deletions std/conv.d
Original file line number Diff line number Diff line change
Expand Up @@ -2553,34 +2553,53 @@ Target parse(Target, Source)(ref Source p)
return new ConvException(text(msg, " for input \"", p, "\"."), fn, ln);
}

// special cases for auto-decoding.
// Can't use std.utf.byCodeUnit because it copies
// the range instead of modifying in place
static auto customFront(ref Source r)
{
static if (isAutodecodableString!Source)
return r[0];
else
return r.front;
}

static void customPopFront(ref Source r)
{
static if (isAutodecodableString!Source)
r = r[1 .. $];
else
r.popFront;
}

enforce(!p.empty, bailOut());

char sign = 0; /* indicating + */
switch (p.front)
bool sign = false;
switch (customFront(p))
{
case '-':
sign++;
p.popFront();
sign = true;
customPopFront(p);
enforce(!p.empty, bailOut());
if (toLower(p.front) == 'i')
if (toLower(customFront(p)) == 'i')
goto case 'i';
enforce(!p.empty, bailOut());
break;
case '+':
p.popFront();
customPopFront(p);
enforce(!p.empty, bailOut());
break;
case 'i': case 'I':
p.popFront();
customPopFront(p);
enforce(!p.empty, bailOut());
if (toLower(p.front) == 'n')
if (toLower(customFront(p)) == 'n')
{
p.popFront();
customPopFront(p);
enforce(!p.empty, bailOut());
if (toLower(p.front) == 'f')
if (toLower(customFront(p)) == 'f')
{
// 'inf'
p.popFront();
customPopFront(p);
return sign ? -Target.infinity : Target.infinity;
}
}
Expand All @@ -2589,16 +2608,16 @@ Target parse(Target, Source)(ref Source p)
}

bool isHex = false;
bool startsWithZero = p.front == '0';
bool startsWithZero = customFront(p) == '0';
if (startsWithZero)
{
p.popFront();
customPopFront(p);
if (p.empty)
{
return (sign) ? -0.0 : 0.0;
}

isHex = p.front == 'x' || p.front == 'X';
isHex = customFront(p) == 'x' || customFront(p) == 'X';
}

real ldval = 0.0;
Expand All @@ -2613,10 +2632,10 @@ Target parse(Target, Source)(ref Source p)
int anydigits = 0;
uint ndigits = 0;

p.popFront();
customPopFront(p);
while (!p.empty)
{
int i = p.front;
int i = customFront(p);
while (isHexDigit(i))
{
anydigits = 1;
Expand Down Expand Up @@ -2647,21 +2666,21 @@ Target parse(Target, Source)(ref Source p)
exp += 4;
}
exp -= dot;
p.popFront();
customPopFront(p);
if (p.empty)
break;
i = p.front;
i = customFront(p);
if (i == '_')
{
p.popFront();
customPopFront(p);
if (p.empty)
break;
i = p.front;
i = customFront(p);
}
}
if (i == '.' && !dot)
{
p.popFront();
customPopFront(p);
dot = 4;
}
else
Expand All @@ -2680,20 +2699,20 @@ Target parse(Target, Source)(ref Source p)
}

enforce(anydigits, bailOut());
enforce(!p.empty && (p.front == 'p' || p.front == 'P'),
enforce(!p.empty && (customFront(p) == 'p' || customFront(p) == 'P'),
bailOut("Floating point parsing: exponent is required"));
char sexp;
int e;

sexp = 0;
p.popFront();
customPopFront(p);
if (!p.empty)
{
switch (p.front)
switch (customFront(p))
{
case '-': sexp++;
goto case;
case '+': p.popFront(); enforce(!p.empty,
case '+': customPopFront(p); enforce(!p.empty,
new ConvException("Error converting input"~
" to floating point"));
break;
Expand All @@ -2702,13 +2721,13 @@ Target parse(Target, Source)(ref Source p)
}
ndigits = 0;
e = 0;
while (!p.empty && isDigit(p.front))
while (!p.empty && isDigit(customFront(p)))
{
if (e < 0x7FFFFFFF / 10 - 10) // prevent integer overflow
{
e = e * 10 + p.front - '0';
e = e * 10 + customFront(p) - '0';
}
p.popFront();
customPopFront(p);
ndigits = 1;
}
exp += (sexp) ? -e : e;
Expand Down Expand Up @@ -2806,25 +2825,25 @@ Target parse(Target, Source)(ref Source p)
}
else // not hex
{
if (toUpper(p.front) == 'N' && !startsWithZero)
if (toUpper(customFront(p)) == 'N' && !startsWithZero)
{
// nan
p.popFront();
enforce(!p.empty && toUpper(p.front) == 'A',
customPopFront(p);
enforce(!p.empty && toUpper(customFront(p)) == 'A',
new ConvException("error converting input to floating point"));
p.popFront();
enforce(!p.empty && toUpper(p.front) == 'N',
customPopFront(p);
enforce(!p.empty && toUpper(customFront(p)) == 'N',
new ConvException("error converting input to floating point"));
// skip past the last 'n'
p.popFront();
customPopFront(p);
return typeof(return).nan;
}

bool sawDigits = startsWithZero;

while (!p.empty)
{
int i = p.front;
int i = customFront(p);
while (isDigit(i))
{
sawDigits = true; /* must have at least 1 digit */
Expand All @@ -2840,21 +2859,21 @@ Target parse(Target, Source)(ref Source p)
exp++;
}
exp -= dot;
p.popFront();
customPopFront(p);
if (p.empty)
break;
i = p.front;
i = customFront(p);
if (i == '_')
{
p.popFront();
customPopFront(p);
if (p.empty)
break;
i = p.front;
i = customFront(p);
}
}
if (i == '.' && !dot)
{
p.popFront();
customPopFront(p);
dot++;
}
else
Expand All @@ -2864,15 +2883,15 @@ Target parse(Target, Source)(ref Source p)
}
enforce(sawDigits, new ConvException("no digits seen"));
}
if (!p.empty && (p.front == 'e' || p.front == 'E'))
if (!p.empty && (customFront(p) == 'e' || customFront(p) == 'E'))
{
char sexp;
int e;

sexp = 0;
p.popFront();
customPopFront(p);
enforce(!p.empty, new ConvException("Unexpected end of input"));
switch (p.front)
switch (customFront(p))
{
case '-': sexp++;
goto case;
Expand All @@ -2882,13 +2901,13 @@ Target parse(Target, Source)(ref Source p)
}
bool sawDigits = 0;
e = 0;
while (!p.empty && isDigit(p.front))
while (!p.empty && isDigit(customFront(p)))
{
if (e < 0x7FFFFFFF / 10 - 10) // prevent integer overflow
{
e = e * 10 + p.front - '0';
e = e * 10 + customFront(p) - '0';
}
p.popFront();
customPopFront(p);
sawDigits = 1;
}
exp += (sexp) ? -e : e;
Expand Down