Skip to content

Commit 4a24cc8

Browse files
authored
ToString() reimplementation (#118)
1 parent 695eaac commit 4a24cc8

File tree

2 files changed

+19
-230
lines changed

2 files changed

+19
-230
lines changed

nanoFramework.CoreLibrary/System/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414
[assembly: AssemblyProduct("nanoFramework mscorlib")]
1515
[assembly: AssemblyCopyright("Copyright (c) .NET Foundation and Contributors")]
1616

17-
[assembly: AssemblyNativeVersion("100.5.0.4")]
17+
[assembly: AssemblyNativeVersion("100.5.0.5")]

nanoFramework.CoreLibrary/System/Number.cs

Lines changed: 18 additions & 229 deletions
Original file line numberDiff line numberDiff line change
@@ -282,238 +282,27 @@ internal static class Number
282282
{
283283
public static String Format(Object value, bool isInteger, String format, NumberFormatInfo info)
284284
{
285-
char formatCh;
286-
int precision;
287-
ValidateFormat(format, out formatCh, out precision);
288-
289-
String result = FormatNative(value, formatCh, precision);
290-
291-
if (isInteger)
292-
{
293-
// Special case : type is integer, value = 0 and format string = "N0"
294-
// No processing needed, simply return "0" (native code returns empty string for this special case)
295-
if (isInteger && result == String.Empty && format == "N0") return "0";
296-
297-
return PostProcessInteger(value, result, formatCh, precision, info);
298-
}
299-
return PostProcessFloat(result, formatCh, precision, info);
285+
String ret = FormatNative(
286+
value,
287+
isInteger,
288+
format,
289+
info.NumberDecimalSeparator,
290+
info.NegativeSign,
291+
info.NumberGroupSeparator,
292+
info.NumberGroupSizes);
293+
294+
return ret;
300295
}
301296

302297
[MethodImpl(MethodImplOptions.InternalCall)]
303-
private static extern String FormatNative(Object value, char format, int precision);
304-
305-
private static void ValidateFormat(String format, out char formatCh, out int precision)
306-
{
307-
precision = 0;
308-
309-
if (format == null || format == "")
310-
{
311-
formatCh = 'G';
312-
return;
313-
}
314-
315-
formatCh = format[0];
316-
317-
// ToUpper, since all the supported format characters are invariant in case
318-
if (formatCh >= 'a' && formatCh <= 'z')
319-
{
320-
formatCh = (char)(formatCh - ('a' - 'A'));
321-
}
322-
323-
int formatLen = format.Length;
324-
325-
if (formatLen > 1)
326-
{
327-
if (formatLen > 4)
328-
{
329-
// Invalid Format
330-
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
331-
throw new ArgumentException();
332-
#pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one
333-
}
334-
335-
for (int i = 1; i < formatLen; i++)
336-
{
337-
var digit = (ushort)(format[i] - '0');
338-
339-
if (digit > 9)
340-
{
341-
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
342-
throw new ArgumentException();
343-
#pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one
344-
}
345-
346-
precision = precision * 10 + digit;
347-
}
348-
}
349-
350-
// Set default precision, if neccessary + check for valid formatCh
351-
switch (formatCh)
352-
{
353-
case 'G':
354-
break;
355-
case 'X':
356-
case 'F':
357-
case 'N':
358-
case 'D':
359-
if (formatLen == 1) precision = 2; // if no precision is specified, use the default
360-
break;
361-
default:
362-
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
363-
throw new ArgumentException();
364-
#pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one
365-
}
366-
}
298+
private static extern String FormatNative(
299+
Object value,
300+
bool isInteger,
301+
String format,
302+
String numberDecimalSeparator,
303+
String negativeSign,
304+
String numberGroupSeparator,
305+
int[] numberGroupSizes);
367306

368-
private static String PostProcessInteger(Object value, String original, char format, int precision, NumberFormatInfo info)
369-
{
370-
String result = original;
371-
372-
switch (format)
373-
{
374-
case 'X':
375-
// truncate negative numbers to
376-
if (result.Length > precision && (result[0] == 'F' || result[0] == 'f'))
377-
{
378-
int len = result.Length;
379-
380-
if (value is sbyte || value is byte)
381-
{
382-
if (len > 2)
383-
{
384-
result = result.Substring(len - 2, 2);
385-
}
386-
}
387-
else if (value is short)
388-
{
389-
if (len > 4)
390-
{
391-
result = result.Substring(len - 4, 4);
392-
}
393-
}
394-
}
395-
break;
396-
397-
case 'N':
398-
// InsertGroupSeparators, AppendTrailingZeros, ReplaceNegativeSign
399-
result = InsertGroupSeparators(result, info);
400-
goto case 'F'; // falls through
401-
case 'F':
402-
// AppendTrailingZeros, ReplaceNegativeSign
403-
result = AppendTrailingZeros(result, precision, info);
404-
goto case 'G'; // falls through
405-
case 'G':
406-
result = ReplaceNegativeSign(result, info);
407-
break;
408-
}
409-
410-
return result;
411-
}
412-
413-
private static String PostProcessFloat(String original, char format, int precision, NumberFormatInfo info)
414-
{
415-
String result = original;
416-
417-
if (format == 'N')
418-
{
419-
result = InsertGroupSeparators(result, info);
420-
}
421-
422-
result = AppendFloatTrailingZeros(result, precision, info);
423-
result = ReplaceDecimalSeperator(result, info);
424-
result = ReplaceNegativeSign(result, info);
425-
426-
return result;
427-
}
428-
429-
private static String AppendTrailingZeros(String original, int count, NumberFormatInfo info)
430-
{
431-
if (count > 0)
432-
{
433-
return original + info.NumberDecimalSeparator + new String('0', count);
434-
}
435-
return original;
436-
}
437-
private static String AppendFloatTrailingZeros(String original, int count, NumberFormatInfo info)
438-
{
439-
// find decimal separator
440-
int pos = original.IndexOf('.');
441-
442-
if (pos != -1)
443-
{
444-
// is the string representation missing any trailing zeros?
445-
count = (original.Length - pos) - count - 1;
446-
if(count > 0)
447-
{
448-
return original + new String('0', count);
449-
}
450-
}
451-
return original;
452-
}
453-
454-
private static String ReplaceNegativeSign(String original, NumberFormatInfo info)
455-
{
456-
if (original[0] == '-')
457-
{
458-
return info.NegativeSign + original.Substring(1);
459-
}
460-
return original;
461-
}
462-
463-
private static String ReplaceDecimalSeperator(String original, NumberFormatInfo info)
464-
{
465-
int pos = original.IndexOf('.');
466-
467-
if (pos != -1)
468-
{
469-
return original.Substring(0, pos) + info.NumberDecimalSeparator + original.Substring(pos + 1);
470-
}
471-
return original;
472-
}
473-
474-
private static String InsertGroupSeparators(String original, NumberFormatInfo info)
475-
{
476-
int digitsStartPos = (original[0] == '-') ? 1 : 0;
477-
478-
int decimalPointPos = original.IndexOf('.');
479-
if (decimalPointPos == -1) decimalPointPos = original.Length;
480-
481-
String prefix = (digitsStartPos == 1) ? "-" : "";
482-
String suffix = original.Substring(decimalPointPos);
483-
String digits = original.Substring(digitsStartPos, decimalPointPos - digitsStartPos);
484-
485-
String result = String.Empty;
486-
487-
int[] groupSizes = info.NumberGroupSizes;
488-
489-
int sizeInd = 0;
490-
int size = groupSizes[sizeInd];
491-
int pos = digits.Length - size;
492-
493-
String seperator = info.NumberGroupSeparator;
494-
int lastSizeInd = groupSizes.Length - 1;
495-
496-
while (pos > 0)
497-
{
498-
result = seperator + digits.Substring(pos, size) + result;
499-
500-
if (sizeInd < lastSizeInd)
501-
{
502-
sizeInd++;
503-
size = groupSizes[sizeInd];
504-
505-
if (size == 0) // per spec, when we see a 0, we leave the remaining digits ungrouped.
506-
{
507-
break;
508-
}
509-
}
510-
511-
pos -= size;
512-
}
513-
514-
result = prefix + digits.Substring(0, size + pos) + result + suffix;
515-
516-
return result;
517-
}
518307
}
519308
}

0 commit comments

Comments
 (0)