Skip to content

Commit 5ff3bb5

Browse files
MatthiasJentschjosesimoes
authored andcommitted
Fixing issue #406: double.ToString() and float.ToString() not working as described (#841)
1 parent b2e11da commit 5ff3bb5

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

src/CLR/CorLib/corlib_native_System_Number.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,88 @@ void nf_GetFormatString(char* formatStr, char formatCh, int precision, bool isLo
1111
sprintf(formatStr, "%%%s%d%s%s", isFloat ? "." : isSigned ? "-0" : "0", precision, isLong ? "l" : isFloat ? "f" : "", formatCh == 'X' ? "X" : isFloat ? "" : isSigned ? "d" : "u");
1212
}
1313

14+
// remove the prepended zeros and (if possible) the decimal point in a float that's formated as string. e.g. "47.1100815000000" => "47.1100815" or "8.0000E-12" => "8E-12"
15+
void nf_RemovePrependedZeros(char* floatStr)
16+
{
17+
int length = hal_strlen_s(floatStr);
18+
// flag for finding the decimal point
19+
bool pointFound = false;
20+
// if not -1 we found the first zero after the decimal point
21+
int firstZero = -1;
22+
// if not -1 we found an "e" or "E" after the last zero of this is the string length
23+
int nextNonZero = length;
24+
25+
// iterate thru all chars
26+
for (int i = 0; i < length; i++)
27+
{
28+
// no decimal point found until now?
29+
if (!pointFound)
30+
{
31+
// is it the decimal point?
32+
if (floatStr[i] == '.')
33+
{
34+
pointFound = true;
35+
}
36+
37+
// next char
38+
continue;
39+
}
40+
41+
// at this point we found the decimal point
42+
// no zero found until now?
43+
if (firstZero == -1)
44+
{
45+
// is it a zero?
46+
if (floatStr[i] == '0')
47+
{
48+
// store the position of the first zero after the decimal point
49+
firstZero = i;
50+
}
51+
52+
// next char
53+
continue;
54+
}
55+
56+
// at this point we found the decimal point and the first zero
57+
// an "e" or "E" char stops the sequence of zeros
58+
if (floatStr[i] == 'e' || floatStr[i] == 'E')
59+
{
60+
// store the position of the e/E char
61+
nextNonZero = i;
62+
// done! we found the positions for the prepended zeros
63+
break;
64+
}
65+
66+
// at this point we found the decimal point and the first zero and the current char is not the e/E char
67+
// is this not a zero?
68+
if (floatStr[i] != '0')
69+
{
70+
// reset! we need to find another zero
71+
firstZero = -1;
72+
}
73+
}
74+
75+
// something to remove?
76+
if (pointFound && firstZero != -1 && nextNonZero != -1)
77+
{
78+
// is the char before the first zero the decimal point? => Remove the decimal point
79+
int startIndex = floatStr[firstZero - 1] == '.' ? firstZero - 1 : firstZero;
80+
// no e/E char after the last trailing zero?
81+
if (nextNonZero == length)
82+
{
83+
// we can cut away the prepended zeros by terminating the string at first zero
84+
floatStr[startIndex] = 0;
85+
}
86+
else
87+
{
88+
// otherwise we copy the last part over the prepended zeros and terminate the string
89+
int lengthToCopy = length - nextNonZero;
90+
memcpy(&floatStr[startIndex], &floatStr[nextNonZero], lengthToCopy);
91+
floatStr[startIndex + lengthToCopy] = 0;
92+
}
93+
}
94+
}
95+
1496
HRESULT Library_corlib_native_System_Number::FormatNative___STATIC__STRING__OBJECT__CHAR__I4( CLR_RT_StackFrame& stack )
1597
{
1698
NATIVE_PROFILE_CLR_CORE();
@@ -25,6 +107,7 @@ HRESULT Library_corlib_native_System_Number::FormatNative___STATIC__STRING__OBJE
25107
char formatStr[ 8 ];
26108
char formatCh = (char)pArgs[ 1 ].NumericByRef().u1;
27109
int precision = pArgs[ 2 ].NumericByRef().s4;
110+
bool shouldRemovePrependedZeros = false;
28111

29112
NANOCLR_CHECK_HRESULT(desc.InitializeFromObject( *value ));
30113
NANOCLR_CHECK_HRESULT(value->PerformUnboxing( desc.m_handlerCls ));
@@ -34,6 +117,7 @@ HRESULT Library_corlib_native_System_Number::FormatNative___STATIC__STRING__OBJE
34117
if(formatCh == 'G' && precision == 0)
35118
{
36119
precision = 1;
120+
shouldRemovePrependedZeros = true;
37121
}
38122

39123
switch(dt)
@@ -122,6 +206,10 @@ HRESULT Library_corlib_native_System_Number::FormatNative___STATIC__STRING__OBJE
122206
nf_GetFormatString(formatStr, formatCh, precision, false, true, false);
123207

124208
sprintf(result, formatStr, value->NumericByRef().r4);
209+
if (shouldRemovePrependedZeros)
210+
{
211+
nf_RemovePrependedZeros(result);
212+
}
125213
#else
126214
CLR_INT32 f = value->NumericByRef().r4;
127215
NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);
@@ -153,6 +241,10 @@ HRESULT Library_corlib_native_System_Number::FormatNative___STATIC__STRING__OBJE
153241
nf_GetFormatString(formatStr, formatCh, precision, false, true, false);
154242

155243
sprintf(result, formatStr, (CLR_DOUBLE_TEMP_CAST)value->NumericByRef().r8);
244+
if (shouldRemovePrependedZeros)
245+
{
246+
nf_RemovePrependedZeros(result);
247+
}
156248
#else
157249
CLR_INT64 d = (CLR_DOUBLE_TEMP_CAST)value->NumericByRef().r8;
158250
NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);

0 commit comments

Comments
 (0)