@@ -477,14 +477,59 @@ internal enum TokenizerMode
477477 Signature , // i.e. class or method declaration
478478 }
479479
480+ /// <summary>
481+ /// Indicates which suffix character(s) are present in the numeric literal being parsed by TryGetNumberValue.
482+ /// </summary>
480483 [ Flags ]
481484 internal enum NumberSuffixFlags
482485 {
486+ /// <summary>
487+ /// Indicates no suffix, a raw numeric literal. May be parsed as Int32, Int64, or Double.
488+ /// </summary>
483489 None = 0x0 ,
490+
491+ /// <summary>
492+ /// Indicates 'u' suffix for unsigned integers. May be parsed as UInt32 or UInt64, depending on the value.
493+ /// </summary>
484494 Unsigned = 0x1 ,
485- Short = 0x2 ,
486- Long = 0x4 ,
487- Decimal = 0x8
495+
496+ /// <summary>
497+ /// Indicates 'y' suffix for signed byte (sbyte) values.
498+ /// </summary>
499+ SignedByte = 0x2 ,
500+
501+ /// <summary>
502+ /// Indicates 'uy' suffix for unsigned byte values.
503+ /// This is a compound value, representing both SignedByte and Unsigned flags being set.
504+ /// </summary>
505+ UnsignedByte = 0x3 ,
506+
507+ /// <summary>
508+ /// Indicates 's' suffix for short (Int16) integers.
509+ /// </summary>
510+ Short = 0x4 ,
511+
512+ /// <summary>
513+ /// Indicates 'us' suffix for ushort (UInt16) integers.
514+ /// This is a compound flag value, representing both Unsigned and Short flags being set.
515+ /// </summary>
516+ UnsignedShort = 0x5 ,
517+
518+ /// <summary>
519+ /// Indicates 'l' suffix for long (Int64) integers.
520+ /// </summary>
521+ Long = 0x8 ,
522+
523+ /// <summary>
524+ /// Indicates 'ul' suffix for ulong (UInt64) integers.
525+ /// This is a compound flag value, representing both Unsigned and Long flags being set.
526+ /// </summary>
527+ UnsignedLong = 0x9 ,
528+
529+ /// <summary>
530+ /// Indicates 'd' suffix for decimal (128-bit) real numbers.
531+ /// </summary>
532+ Decimal = 0x10
488533 }
489534
490535 //
@@ -3292,12 +3337,18 @@ private static bool TryGetNumberValue(string strNum, bool hex, bool real, Number
32923337 case NumberSuffixFlags . Short :
32933338 result = ( short ) ( ( short ) Convert . ChangeType ( doubleValue , typeof ( short ) , CultureInfo . InvariantCulture ) * multiplier ) ;
32943339 break ;
3295- case NumberSuffixFlags . Unsigned | NumberSuffixFlags . Long :
3340+ case NumberSuffixFlags . SignedByte :
3341+ result = ( sbyte ) ( ( sbyte ) Convert . ChangeType ( doubleValue , typeof ( sbyte ) , CultureInfo . InvariantCulture ) * multiplier ) ;
3342+ break ;
3343+ case NumberSuffixFlags . UnsignedLong :
32963344 result = ( ulong ) Convert . ChangeType ( doubleValue , typeof ( ulong ) , CultureInfo . InvariantCulture ) * ( ulong ) multiplier ;
32973345 break ;
3298- case NumberSuffixFlags . Unsigned | NumberSuffixFlags . Short :
3346+ case NumberSuffixFlags . UnsignedShort :
32993347 result = ( ushort ) ( ( ushort ) Convert . ChangeType ( doubleValue , typeof ( ushort ) , CultureInfo . InvariantCulture ) * multiplier ) ;
33003348 break ;
3349+ case NumberSuffixFlags . UnsignedByte :
3350+ result = ( byte ) ( ( byte ) Convert . ChangeType ( doubleValue , typeof ( byte ) , CultureInfo . InvariantCulture ) * multiplier ) ;
3351+ break ;
33013352 case NumberSuffixFlags . Unsigned :
33023353 ulong testresult = ( ulong ) Convert . ChangeType ( doubleValue , typeof ( ulong ) , CultureInfo . InvariantCulture ) * ( ulong ) multiplier ;
33033354 if ( testresult < uint . MaxValue )
@@ -3355,6 +3406,16 @@ private static bool TryGetNumberValue(string strNum, bool hex, bool real, Number
33553406 return true ;
33563407 }
33573408
3409+ result = null ;
3410+ return false ;
3411+ case NumberSuffixFlags . SignedByte :
3412+ // Multiplier for hex-parsed values can be negative to permit - prefix for hex values
3413+ if ( Math . Abs ( multiplier ) == 1 && sbyte . TryParse ( strNum , style , NumberFormatInfo . InvariantInfo , out sbyte sb ) )
3414+ {
3415+ result = ( sbyte ) ( sb * multiplier ) ;
3416+ return true ;
3417+ }
3418+
33583419 result = null ;
33593420 return false ;
33603421 case NumberSuffixFlags . Unsigned :
@@ -3376,7 +3437,7 @@ private static bool TryGetNumberValue(string strNum, bool hex, bool real, Number
33763437
33773438 result = null ;
33783439 return false ;
3379- case NumberSuffixFlags . Unsigned | NumberSuffixFlags . Long :
3440+ case NumberSuffixFlags . UnsignedLong :
33803441 if ( ulong . TryParse ( strNum , style , NumberFormatInfo . InvariantInfo , out ulong ul ) )
33813442 {
33823443 result = ( ulong ) ( ul * ( ulong ) multiplier ) ;
@@ -3385,13 +3446,24 @@ private static bool TryGetNumberValue(string strNum, bool hex, bool real, Number
33853446
33863447 result = null ;
33873448 return false ;
3388- case NumberSuffixFlags . Unsigned | NumberSuffixFlags . Short :
3449+ case NumberSuffixFlags . UnsignedShort :
33893450 if ( ushort . TryParse ( strNum , style , NumberFormatInfo . InvariantInfo , out ushort us ) )
33903451 {
33913452 result = ( ushort ) ( us * ( ushort ) multiplier ) ;
33923453 return true ;
33933454 }
33943455
3456+ result = null ;
3457+ return false ;
3458+ case NumberSuffixFlags . UnsignedByte :
3459+ // If multiplier is negative or greater than 1, we can assume it will fail since the
3460+ // minimum multiplier is 1024 (already exceeds byte.MaxValue), and byte is unsigned
3461+ if ( multiplier == 1 && byte . TryParse ( strNum , style , NumberFormatInfo . InvariantInfo , out byte b ) )
3462+ {
3463+ result = b ;
3464+ return true ;
3465+ }
3466+
33953467 result = null ;
33963468 return false ;
33973469 default :
@@ -3603,6 +3675,10 @@ private string ScanNumberHelper(char firstChar, out bool hex, out bool real, out
36033675 case 'D' :
36043676 suffix |= NumberSuffixFlags . Decimal ;
36053677 break ;
3678+ case 'y' :
3679+ case 'Y' :
3680+ suffix |= NumberSuffixFlags . SignedByte ;
3681+ break ;
36063682 default :
36073683 notNumber = true ;
36083684 break ;
@@ -3625,6 +3701,10 @@ private string ScanNumberHelper(char firstChar, out bool hex, out bool real, out
36253701 case 'S' :
36263702 suffix |= NumberSuffixFlags . Short ;
36273703 break ;
3704+ case 'y' :
3705+ case 'Y' :
3706+ suffix |= NumberSuffixFlags . SignedByte ;
3707+ break ;
36283708 default :
36293709 notNumber = true ;
36303710 break ;
0 commit comments