Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit d55088a

Browse files
andralexdlang-bot
authored andcommitted
(un)signedToTempString: Make radix a template parameter to avoid integral division
1 parent 2ebce17 commit d55088a

File tree

6 files changed

+90
-50
lines changed

6 files changed

+90
-50
lines changed

src/core/demangle.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ pure @safe:
279279

280280
UnsignedStringBuf buf = void;
281281

282-
auto s = unsignedToTempString(val, buf, 16);
282+
auto s = unsignedToTempString!16(val, buf);
283283
int slen = cast(int)s.length;
284284
if (slen < width)
285285
{

src/core/internal/abort.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,6 @@ void abort(scope string msg, scope string filename = __FILE__, size_t line = __L
4848
UnsignedStringBuf strbuff = void;
4949

5050
// write an appropriate message, then abort the program
51-
writeStr("Aborting from ", filename, "(", line.unsignedToTempString(strbuff, 10), ") ", msg);
51+
writeStr("Aborting from ", filename, "(", line.unsignedToTempString(strbuff), ") ", msg);
5252
c_abort();
5353
}

src/core/internal/string.d

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,30 @@ Params:
2828
Returns:
2929
The unsigned integer value as a string of characters
3030
*/
31-
char[] unsignedToTempString()(ulong value, return scope char[] buf, uint radix = 10) @safe
31+
char[] unsignedToTempString(uint radix = 10)(ulong value, return scope char[] buf) @safe
32+
if (radix >= 2 && radix <= 16)
33+
{
34+
size_t i = buf.length;
35+
do
36+
{
37+
uint x = void;
38+
if (value < radix)
39+
{
40+
x = cast(uint)value;
41+
value = 0;
42+
}
43+
else
44+
{
45+
x = cast(uint)(value % radix);
46+
value /= radix;
47+
}
48+
buf[--i] = cast(char)((radix <= 10 || x < 10) ? x + '0' : x - 10 + 'a');
49+
} while (value);
50+
return buf[i .. $];
51+
}
52+
53+
// TEMPORARY. Delete after the related Phobos PR is merged.
54+
char[] unsignedToTempString()(ulong value, return scope char[] buf, uint radix) @safe
3255
{
3356
if (radix < 2)
3457
// not a valid radix, just return an empty string
@@ -77,46 +100,46 @@ Params:
77100
Returns:
78101
The unsigned integer value as a string of characters
79102
*/
80-
auto unsignedToTempString()(ulong value, uint radix = 10) @safe
103+
auto unsignedToTempString(uint radix = 10)(ulong value) @safe
81104
{
82105
TempStringNoAlloc!() result = void;
83-
result._len = unsignedToTempString(value, result._buf, radix).length & 0xff;
106+
result._len = unsignedToTempString!radix(value, result._buf).length & 0xff;
84107
return result;
85108
}
86109

87110
unittest
88111
{
89112
UnsignedStringBuf buf;
90-
assert(0.unsignedToTempString(buf, 10) == "0");
91-
assert(1.unsignedToTempString(buf, 10) == "1");
92-
assert(12.unsignedToTempString(buf, 10) == "12");
93-
assert(0x12ABCF .unsignedToTempString(buf, 16) == "12abcf");
94-
assert(long.sizeof.unsignedToTempString(buf, 10) == "8");
95-
assert(uint.max.unsignedToTempString(buf, 10) == "4294967295");
96-
assert(ulong.max.unsignedToTempString(buf, 10) == "18446744073709551615");
113+
assert(0.unsignedToTempString(buf) == "0");
114+
assert(1.unsignedToTempString(buf) == "1");
115+
assert(12.unsignedToTempString(buf) == "12");
116+
assert(0x12ABCF .unsignedToTempString!16(buf) == "12abcf");
117+
assert(long.sizeof.unsignedToTempString(buf) == "8");
118+
assert(uint.max.unsignedToTempString(buf) == "4294967295");
119+
assert(ulong.max.unsignedToTempString(buf) == "18446744073709551615");
97120

98121
// use stack allocated struct version
99-
assert(0.unsignedToTempString(10) == "0");
122+
assert(0.unsignedToTempString == "0");
100123
assert(1.unsignedToTempString == "1");
101124
assert(12.unsignedToTempString == "12");
102-
assert(0x12ABCF .unsignedToTempString(16) == "12abcf");
125+
assert(0x12ABCF .unsignedToTempString!16 == "12abcf");
103126
assert(long.sizeof.unsignedToTempString == "8");
104127
assert(uint.max.unsignedToTempString == "4294967295");
105128
assert(ulong.max.unsignedToTempString == "18446744073709551615");
106129

107130
// test bad radices
108-
assert(100.unsignedToTempString(buf, 1) == "");
109-
assert(100.unsignedToTempString(buf, 0) == "");
131+
assert(!is(typeof(100.unsignedToTempString!1(buf))));
132+
assert(!is(typeof(100.unsignedToTempString!0(buf) == "")));
110133
}
111134

112135
alias SignedStringBuf = char[20];
113136

114-
char[] signedToTempString(long value, return scope char[] buf, uint radix = 10) @safe
137+
char[] signedToTempString(uint radix = 10)(long value, return scope char[] buf) @safe
115138
{
116139
bool neg = value < 0;
117140
if (neg)
118141
value = cast(ulong)-value;
119-
auto r = unsignedToTempString(value, buf, radix);
142+
auto r = unsignedToTempString!radix(value, buf);
120143
if (neg)
121144
{
122145
// about to do a slice without a bounds check
@@ -127,12 +150,12 @@ char[] signedToTempString(long value, return scope char[] buf, uint radix = 10)
127150
return r;
128151
}
129152

130-
auto signedToTempString(long value, uint radix = 10) @safe
153+
auto signedToTempString(uint radix = 10)(long value) @safe
131154
{
132155
bool neg = value < 0;
133156
if (neg)
134157
value = cast(ulong)-value;
135-
auto r = unsignedToTempString(value, radix);
158+
auto r = unsignedToTempString!radix(value);
136159
if (neg)
137160
{
138161
r._len++;
@@ -141,37 +164,54 @@ auto signedToTempString(long value, uint radix = 10) @safe
141164
return r;
142165
}
143166

167+
// TEMPORARY. Delete after the related Phobos PR is merged.
168+
char[] signedToTempString()(long value, return scope char[] buf, uint radix) @safe
169+
{
170+
bool neg = value < 0;
171+
if (neg)
172+
value = cast(ulong)-value;
173+
auto r = unsignedToTempString(value, buf, radix);
174+
if (neg)
175+
{
176+
// about to do a slice without a bounds check
177+
auto trustedSlice(return char[] r) @trusted { assert(r.ptr > buf.ptr); return (r.ptr-1)[0..r.length+1]; }
178+
r = trustedSlice(r);
179+
r[0] = '-';
180+
}
181+
return r;
182+
}
183+
144184
unittest
145185
{
146186
SignedStringBuf buf;
147-
assert(0.signedToTempString(buf, 10) == "0");
187+
assert(0.signedToTempString(buf) == "0");
148188
assert(1.signedToTempString(buf) == "1");
149189
assert((-1).signedToTempString(buf) == "-1");
150190
assert(12.signedToTempString(buf) == "12");
151191
assert((-12).signedToTempString(buf) == "-12");
152-
assert(0x12ABCF .signedToTempString(buf, 16) == "12abcf");
153-
assert((-0x12ABCF) .signedToTempString(buf, 16) == "-12abcf");
192+
assert(0x12ABCF .signedToTempString!16(buf) == "12abcf");
193+
assert((-0x12ABCF) .signedToTempString!16(buf) == "-12abcf");
154194
assert(long.sizeof.signedToTempString(buf) == "8");
155195
assert(int.max.signedToTempString(buf) == "2147483647");
156196
assert(int.min.signedToTempString(buf) == "-2147483648");
157197
assert(long.max.signedToTempString(buf) == "9223372036854775807");
158198
assert(long.min.signedToTempString(buf) == "-9223372036854775808");
159199

160200
// use stack allocated struct version
161-
assert(0.signedToTempString(10) == "0");
201+
assert(0.signedToTempString() == "0");
162202
assert(1.signedToTempString == "1");
163203
assert((-1).signedToTempString == "-1");
164204
assert(12.signedToTempString == "12");
165205
assert((-12).signedToTempString == "-12");
166-
assert(0x12ABCF .signedToTempString(16) == "12abcf");
167-
assert((-0x12ABCF) .signedToTempString(16) == "-12abcf");
206+
assert(0x12ABCF .signedToTempString!16 == "12abcf");
207+
assert((-0x12ABCF) .signedToTempString!16 == "-12abcf");
168208
assert(long.sizeof.signedToTempString == "8");
169209
assert(int.max.signedToTempString == "2147483647");
170210
assert(int.min.signedToTempString == "-2147483648");
171211
assert(long.max.signedToTempString == "9223372036854775807");
172212
assert(long.min.signedToTempString == "-9223372036854775808");
173-
assert(long.max.signedToTempString(2) == "111111111111111111111111111111111111111111111111111111111111111");
174-
assert(long.min.signedToTempString(2) == "-1000000000000000000000000000000000000000000000000000000000000000");
213+
assert(long.max.signedToTempString!2 == "111111111111111111111111111111111111111111111111111111111111111");
214+
assert(long.min.signedToTempString!2 == "-1000000000000000000000000000000000000000000000000000000000000000");
175215
}
176216

177217

src/core/internal/util/array.d

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ private void _enforceSameLength(const char[] action,
4141
string msg = "Array lengths don't match for ";
4242
msg ~= action;
4343
msg ~= ": ";
44-
msg ~= length1.unsignedToTempString(tmpBuff, 10);
44+
msg ~= length1.unsignedToTempString(tmpBuff);
4545
msg ~= " != ";
46-
msg ~= length2.unsignedToTempString(tmpBuff, 10);
46+
msg ~= length2.unsignedToTempString(tmpBuff);
4747
assert(0, msg);
4848
}
4949

@@ -59,9 +59,9 @@ private void _enforceNoOverlap(const char[] action,
5959
string msg = "Overlapping arrays in ";
6060
msg ~= action;
6161
msg ~= ": ";
62-
msg ~= overlappedBytes.unsignedToTempString(tmpBuff, 10);
62+
msg ~= overlappedBytes.unsignedToTempString(tmpBuff);
6363
msg ~= " byte(s) overlap of ";
64-
msg ~= bytes.unsignedToTempString(tmpBuff, 10);
64+
msg ~= bytes.unsignedToTempString(tmpBuff);
6565
assert(0, msg);
6666
}
6767

src/core/time.d

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,7 @@ public:
15841584
unit = "μs";
15851585
else
15861586
unit = plural ? units : units[0 .. $-1];
1587-
res ~= signedToTempString(val, 10);
1587+
res ~= signedToTempString(val);
15881588
res ~= " ";
15891589
res ~= unit;
15901590
}
@@ -1806,9 +1806,9 @@ unittest
18061806
auto _str(F)(F val)
18071807
{
18081808
static if (is(F == int) || is(F == long))
1809-
return signedToTempString(val, 10);
1809+
return signedToTempString(val);
18101810
else
1811-
return unsignedToTempString(val, 10);
1811+
return unsignedToTempString(val);
18121812
}
18131813

18141814
foreach (F; AliasSeq!(int,uint,long,ulong,float,double,real))
@@ -2405,10 +2405,10 @@ assert(before + timeElapsed == after);
24052405
string toString() const pure nothrow
24062406
{
24072407
static if (clockType == ClockType.normal)
2408-
return "MonoTime(" ~ signedToTempString(_ticks, 10) ~ " ticks, " ~ signedToTempString(ticksPerSecond, 10) ~ " ticks per second)";
2408+
return "MonoTime(" ~ signedToTempString(_ticks) ~ " ticks, " ~ signedToTempString(ticksPerSecond) ~ " ticks per second)";
24092409
else
2410-
return "MonoTimeImpl!(ClockType." ~ _clockName ~ ")(" ~ signedToTempString(_ticks, 10) ~ " ticks, " ~
2411-
signedToTempString(ticksPerSecond, 10) ~ " ticks per second)";
2410+
return "MonoTimeImpl!(ClockType." ~ _clockName ~ ")(" ~ signedToTempString(_ticks) ~ " ticks, " ~
2411+
signedToTempString(ticksPerSecond) ~ " ticks per second)";
24122412
}
24132413

24142414
version (CoreUnittest) unittest
@@ -2428,9 +2428,9 @@ assert(before + timeElapsed == after);
24282428
else
24292429
eat(str, "MonoTimeImpl!(ClockType."~_clockName~")(");
24302430

2431-
eat(str, signedToTempString(mt._ticks, 10));
2431+
eat(str, signedToTempString(mt._ticks));
24322432
eat(str, " ticks, ");
2433-
eat(str, signedToTempString(ticksPerSecond, 10));
2433+
eat(str, signedToTempString(ticksPerSecond));
24342434
eat(str, " ticks per second)");
24352435
}
24362436

@@ -3970,9 +3970,9 @@ string doubleToString(double value) @safe pure nothrow
39703970
if (value < 0 && cast(long)value == 0)
39713971
result = "-0";
39723972
else
3973-
result = signedToTempString(cast(long)value, 10).idup;
3973+
result = signedToTempString(cast(long)value).idup;
39743974
result ~= '.';
3975-
result ~= unsignedToTempString(cast(ulong)(_abs((value - cast(long)value) * 1_000_000) + .5), 10);
3975+
result ~= unsignedToTempString(cast(ulong)(_abs((value - cast(long)value) * 1_000_000) + .5));
39763976

39773977
while (result[$-1] == '0')
39783978
result = result[0 .. $-1];
@@ -3996,7 +3996,7 @@ unittest
39963996

39973997
version (CoreUnittest) const(char)* numToStringz()(long value) @trusted pure nothrow
39983998
{
3999-
return (signedToTempString(value, 10) ~ "\0").ptr;
3999+
return (signedToTempString(value) ~ "\0").ptr;
40004000
}
40014001

40024002

@@ -4121,9 +4121,9 @@ version (CoreUnittest) void assertApprox(D, E)(D actual,
41214121
{
41224122
if (actual.length < lower.length || actual.length > upper.length)
41234123
{
4124-
throw new AssertError(msg ~ (": [" ~ signedToTempString(lower.length, 10) ~ "] [" ~
4125-
signedToTempString(actual.length, 10) ~ "] [" ~
4126-
signedToTempString(upper.length, 10) ~ "]").idup,
4124+
throw new AssertError(msg ~ (": [" ~ signedToTempString(lower.length) ~ "] [" ~
4125+
signedToTempString(actual.length) ~ "] [" ~
4126+
signedToTempString(upper.length) ~ "]").idup,
41274127
__FILE__, line);
41284128
}
41294129
}
@@ -4145,7 +4145,7 @@ version (CoreUnittest) void assertApprox()(long actual,
41454145
size_t line = __LINE__)
41464146
{
41474147
if (actual < lower)
4148-
throw new AssertError(msg ~ ": lower: " ~ signedToTempString(actual, 10).idup, __FILE__, line);
4148+
throw new AssertError(msg ~ ": lower: " ~ signedToTempString(actual).idup, __FILE__, line);
41494149
if (actual > upper)
4150-
throw new AssertError(msg ~ ": upper: " ~ signedToTempString(actual, 10).idup, __FILE__, line);
4150+
throw new AssertError(msg ~ ": upper: " ~ signedToTempString(actual).idup, __FILE__, line);
41514151
}

src/object.d

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ class TypeInfo_StaticArray : TypeInfo
628628
import core.internal.string : unsignedToTempString;
629629

630630
char[20] tmpBuff = void;
631-
return value.toString() ~ "[" ~ unsignedToTempString(len, tmpBuff, 10) ~ "]";
631+
return value.toString() ~ "[" ~ unsignedToTempString(len, tmpBuff) ~ "]";
632632
}
633633

634634
override bool opEquals(Object o)
@@ -2006,7 +2006,7 @@ class Throwable : Object
20062006

20072007
sink(typeid(this).name);
20082008
sink("@"); sink(file);
2009-
sink("("); sink(unsignedToTempString(line, tmpBuff, 10)); sink(")");
2009+
sink("("); sink(unsignedToTempString(line, tmpBuff)); sink(")");
20102010

20112011
if (msg.length)
20122012
{

0 commit comments

Comments
 (0)