mirror of
https://github.com/dlang/phobos.git
synced 2025-04-28 06:00:35 +03:00
Clean up after making formating floating point numbers @nogc.
This commit is contained in:
parent
afc2df6ef2
commit
3206e52aae
4 changed files with 976 additions and 1023 deletions
8
changelog/formatting_floats_nogc.dd
Normal file
8
changelog/formatting_floats_nogc.dd
Normal file
|
@ -0,0 +1,8 @@
|
|||
Floating point numbers don't allocate with the GC anymore.
|
||||
|
||||
The implementation of formatting floating point numbers has been
|
||||
reworked. We made sure that working examples never allocate with the
|
||||
GC, however, we are still using exceptions which are GC managed.
|
||||
Therefore, code that uses formatting correctly will never allocate,
|
||||
but in the case of exceptions, the GC will be used to allocate the
|
||||
exception. We are working on DIP 1008 to solve this issue.
|
File diff suppressed because it is too large
Load diff
|
@ -506,9 +506,7 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
|
|||
}
|
||||
|
||||
fs.spec = spec2;
|
||||
buf = printFloat(buf2[], w, val, fs, mode);
|
||||
len = buf.length;
|
||||
if (len == 0) return;
|
||||
printFloat(w, val, fs, mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -561,87 +559,87 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
|
|||
|
||||
len = min(n, buf2.length-1);
|
||||
buf = buf2;
|
||||
}
|
||||
|
||||
if (fs.flSeparator && !inf && !nan)
|
||||
{
|
||||
ptrdiff_t indexOfRemovable()
|
||||
if (fs.flSeparator && !inf && !nan)
|
||||
{
|
||||
if (len < 2)
|
||||
return -1;
|
||||
|
||||
size_t start = (buf[0 .. 1].indexOfAny(" 0123456789") == -1) ? 1 : 0;
|
||||
if (len < 2 + start)
|
||||
return -1;
|
||||
if ((buf[start] == ' ') || (buf[start] == '0' && buf[start + 1] != '.'))
|
||||
return start;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptrdiff_t dot, firstDigit, ePos, dotIdx, firstLen;
|
||||
size_t separatorScoreCnt;
|
||||
|
||||
while (true)
|
||||
{
|
||||
dot = buf[0 .. len].indexOf('.');
|
||||
firstDigit = buf[0 .. len].indexOfAny("0123456789");
|
||||
ePos = buf[0 .. len].indexOf('e');
|
||||
dotIdx = dot == -1 ? ePos == -1 ? len : ePos : dot;
|
||||
|
||||
firstLen = dotIdx - firstDigit;
|
||||
separatorScoreCnt = (firstLen > 0) ? (firstLen - 1) / fs.separators : 0;
|
||||
|
||||
ptrdiff_t removableIdx = (len + separatorScoreCnt > fs.width) ? indexOfRemovable() : -1;
|
||||
if ((removableIdx != -1) &&
|
||||
((firstLen - (buf[removableIdx] == '0' ? 2 : 1)) / fs.separators + len - 1 >= fs.width))
|
||||
ptrdiff_t indexOfRemovable()
|
||||
{
|
||||
buf[removableIdx .. $ - 1] = buf.dup[removableIdx + 1 .. $];
|
||||
len--;
|
||||
if (len < 2)
|
||||
return -1;
|
||||
|
||||
size_t start = (buf[0 .. 1].indexOfAny(" 0123456789") == -1) ? 1 : 0;
|
||||
if (len < 2 + start)
|
||||
return -1;
|
||||
if ((buf[start] == ' ') || (buf[start] == '0' && buf[start + 1] != '.'))
|
||||
return start;
|
||||
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
immutable afterDotIdx = (ePos != -1) ? ePos : len;
|
||||
ptrdiff_t dot, firstDigit, ePos, dotIdx, firstLen;
|
||||
size_t separatorScoreCnt;
|
||||
|
||||
// plus, minus, prefix
|
||||
if (firstDigit > 0)
|
||||
{
|
||||
put(w, buf[0 .. firstDigit]);
|
||||
}
|
||||
|
||||
// digits until dot with separator
|
||||
for (auto j = 0; j < firstLen; ++j)
|
||||
{
|
||||
if (j > 0 && (firstLen - j) % fs.separators == 0)
|
||||
while (true)
|
||||
{
|
||||
put(w, fs.separatorChar);
|
||||
dot = buf[0 .. len].indexOf('.');
|
||||
firstDigit = buf[0 .. len].indexOfAny("0123456789");
|
||||
ePos = buf[0 .. len].indexOf('e');
|
||||
dotIdx = dot == -1 ? ePos == -1 ? len : ePos : dot;
|
||||
|
||||
firstLen = dotIdx - firstDigit;
|
||||
separatorScoreCnt = (firstLen > 0) ? (firstLen - 1) / fs.separators : 0;
|
||||
|
||||
ptrdiff_t removableIdx = (len + separatorScoreCnt > fs.width) ? indexOfRemovable() : -1;
|
||||
if ((removableIdx != -1) &&
|
||||
((firstLen - (buf[removableIdx] == '0' ? 2 : 1)) / fs.separators + len - 1 >= fs.width))
|
||||
{
|
||||
buf[removableIdx .. $ - 1] = buf.dup[removableIdx + 1 .. $];
|
||||
len--;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
put(w, buf[j + firstDigit]);
|
||||
}
|
||||
|
||||
// print dot for decimal numbers only or with '#' format specifier
|
||||
if (dot != -1 || fs.flHash)
|
||||
{
|
||||
put(w, '.');
|
||||
}
|
||||
immutable afterDotIdx = (ePos != -1) ? ePos : len;
|
||||
|
||||
// digits after dot
|
||||
for (auto j = dotIdx + 1; j < afterDotIdx; ++j)
|
||||
{
|
||||
put(w, buf[j]);
|
||||
}
|
||||
// plus, minus, prefix
|
||||
if (firstDigit > 0)
|
||||
{
|
||||
put(w, buf[0 .. firstDigit]);
|
||||
}
|
||||
|
||||
// rest
|
||||
if (ePos != -1)
|
||||
{
|
||||
put(w, buf[afterDotIdx .. len]);
|
||||
// digits until dot with separator
|
||||
for (auto j = 0; j < firstLen; ++j)
|
||||
{
|
||||
if (j > 0 && (firstLen - j) % fs.separators == 0)
|
||||
{
|
||||
put(w, fs.separatorChar);
|
||||
}
|
||||
put(w, buf[j + firstDigit]);
|
||||
}
|
||||
|
||||
// print dot for decimal numbers only or with '#' format specifier
|
||||
if (dot != -1 || fs.flHash)
|
||||
{
|
||||
put(w, '.');
|
||||
}
|
||||
|
||||
// digits after dot
|
||||
for (auto j = dotIdx + 1; j < afterDotIdx; ++j)
|
||||
{
|
||||
put(w, buf[j]);
|
||||
}
|
||||
|
||||
// rest
|
||||
if (ePos != -1)
|
||||
{
|
||||
put(w, buf[afterDotIdx .. len]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
put(w, buf[0 .. len]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
put(w, buf[0 .. len]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1511,8 +1511,6 @@ Note:
|
|||
|
||||
$(UL
|
||||
$(LI An exception is thrown.)
|
||||
$(LI A floating point number of type `real` is formatted.)
|
||||
$(LI The representation of a floating point number exceeds 500 characters.)
|
||||
$(LI A custom `toString` function of a compound type allocates.))
|
||||
*/
|
||||
char[] sformat(Char, Args...)(return scope char[] buf, scope const(Char)[] fmt, Args args)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue