@@ -412,19 +412,48 @@ internal static unsafe void DecimalToNumber(scoped ref decimal d, ref NumberBuff
412412 number . CheckConsistency ( ) ;
413413 }
414414
415+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
415416 private static int GetFloatingPointMaxDigitsAndPrecision ( char fmt , ref int precision , NumberFormatInfo info , out bool isSignificantDigits )
416417 {
418+ // We want to fast path the common case of no format and general format + precision.
419+ // These are commonly encountered and the full switch is otherwise large enough to show up in hot path profiles
420+
417421 if ( fmt == 0 )
418422 {
419423 isSignificantDigits = true ;
420424 return precision ;
421425 }
422426
423- int maxDigits = precision ;
427+ // Bitwise-or with space (' ') converts any uppercase character to
428+ // lowercase and keeps unsupported characters as something unsupported.
429+ fmt |= ' ' ;
424430
425- switch ( fmt | 0x20 )
431+ if ( fmt == 'g' )
426432 {
427- case 'c' :
433+ // The general format uses the precision specifier to indicate the number of significant
434+ // digits to format. This defaults to the shortest roundtrippable string. Additionally,
435+ // given that we can't return zero significant digits, we treat 0 as returning the shortest
436+ // roundtrippable string as well.
437+
438+ isSignificantDigits = true ;
439+
440+ if ( precision == 0 )
441+ {
442+ precision = - 1 ;
443+ return 0 ;
444+ }
445+ return precision ;
446+ }
447+
448+ return Slow ( fmt , ref precision , info , out isSignificantDigits ) ;
449+
450+ static int Slow ( char fmt , ref int precision , NumberFormatInfo info , out bool isSignificantDigits )
451+ {
452+ int maxDigits = precision ;
453+
454+ switch ( fmt )
455+ {
456+ case 'c' :
428457 {
429458 // The currency format uses the precision specifier to indicate the number of
430459 // decimal digits to format. This defaults to NumberFormatInfo.CurrencyDecimalDigits.
@@ -438,7 +467,7 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
438467 break ;
439468 }
440469
441- case 'e' :
470+ case 'e' :
442471 {
443472 // The exponential format uses the precision specifier to indicate the number of
444473 // decimal digits to format. This defaults to 6. However, the exponential format
@@ -456,8 +485,8 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
456485 break ;
457486 }
458487
459- case 'f' :
460- case 'n' :
488+ case 'f' :
489+ case 'n' :
461490 {
462491 // The fixed-point and number formats use the precision specifier to indicate the number
463492 // of decimal digits to format. This defaults to NumberFormatInfo.NumberDecimalDigits.
@@ -471,23 +500,7 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
471500 break ;
472501 }
473502
474- case 'g' :
475- {
476- // The general format uses the precision specifier to indicate the number of significant
477- // digits to format. This defaults to the shortest roundtrippable string. Additionally,
478- // given that we can't return zero significant digits, we treat 0 as returning the shortest
479- // roundtrippable string as well.
480-
481- if ( precision == 0 )
482- {
483- precision = - 1 ;
484- }
485- isSignificantDigits = true ;
486-
487- break ;
488- }
489-
490- case 'p' :
503+ case 'p' :
491504 {
492505 // The percent format uses the precision specifier to indicate the number of
493506 // decimal digits to format. This defaults to NumberFormatInfo.PercentDecimalDigits.
@@ -505,7 +518,7 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
505518 break ;
506519 }
507520
508- case 'r' :
521+ case 'r' :
509522 {
510523 // The roundtrip format ignores the precision specifier and always returns the shortest
511524 // roundtrippable string.
@@ -516,14 +529,15 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
516529 break ;
517530 }
518531
519- default :
532+ default :
520533 {
521534 ThrowHelper . ThrowFormatException_BadFormatSpecifier ( ) ;
522535 goto case 'r' ; // unreachable
523536 }
524- }
537+ }
525538
526- return maxDigits ;
539+ return maxDigits ;
540+ }
527541 }
528542
529543 public static string FormatFloat < TNumber > ( TNumber value , string ? format , NumberFormatInfo info )
0 commit comments