@@ -669,4 +669,325 @@ private static byte ParseHexByte(char c1, char c2)
669
669
}
670
670
}
671
671
}
672
+
673
+ enum ParseState
674
+ {
675
+ LeadingWhite ,
676
+ Sign ,
677
+ Number ,
678
+ DecimalPoint ,
679
+ FractionNumber ,
680
+ Exponent ,
681
+ ExponentSign ,
682
+ ExponentValue ,
683
+ TrailingWhite
684
+ }
685
+
686
+ internal static class SignedInteger < T > where T : struct , IComparable < T > , IEquatable < T > , IConvertible
687
+ {
688
+ private static readonly TypeCode typeCode ;
689
+ private static readonly long minValue ;
690
+ private static readonly long maxValue ;
691
+
692
+ static SignedInteger ( )
693
+ {
694
+ typeCode = Type . GetTypeCode ( typeof ( T ) ) ;
695
+
696
+ switch ( typeCode )
697
+ {
698
+ case TypeCode . SByte :
699
+ minValue = sbyte . MinValue ;
700
+ maxValue = sbyte . MaxValue ;
701
+ break ;
702
+ case TypeCode . Int16 :
703
+ minValue = short . MinValue ;
704
+ maxValue = short . MaxValue ;
705
+ break ;
706
+ case TypeCode . Int32 :
707
+ minValue = int . MinValue ;
708
+ maxValue = int . MaxValue ;
709
+ break ;
710
+ case TypeCode . Int64 :
711
+ minValue = long . MinValue ;
712
+ maxValue = long . MaxValue ;
713
+ break ;
714
+ default :
715
+ throw new NotSupportedException ( $ "{ typeof ( T ) . Name } is not a signed integer") ;
716
+ }
717
+ }
718
+
719
+ internal static object ParseNullableObject ( ReadOnlySpan < char > value )
720
+ {
721
+ if ( value . IsNullOrEmpty ( ) )
722
+ return null ;
723
+
724
+ return ParseObject ( value ) ;
725
+ }
726
+
727
+ internal static object ParseObject ( ReadOnlySpan < char > value )
728
+ {
729
+ var result = ParseInt64 ( value ) ;
730
+ switch ( typeCode )
731
+ {
732
+ case TypeCode . SByte :
733
+ return ( sbyte ) result ;
734
+ case TypeCode . Int16 :
735
+ return ( short ) result ;
736
+ case TypeCode . Int32 :
737
+ return ( int ) result ;
738
+ default :
739
+ return result ;
740
+ }
741
+ }
742
+
743
+ public static sbyte ParseSByte ( ReadOnlySpan < char > value ) => ( sbyte ) ParseInt64 ( value ) ;
744
+ public static short ParseInt16 ( ReadOnlySpan < char > value ) => ( short ) ParseInt64 ( value ) ;
745
+ public static int ParseInt32 ( ReadOnlySpan < char > value ) => ( int ) ParseInt64 ( value ) ;
746
+
747
+ public static long ParseInt64 ( ReadOnlySpan < char > value )
748
+ {
749
+ if ( value . IsEmpty )
750
+ throw new FormatException ( MemoryProvider . BadFormat ) ;
751
+
752
+ long result = 0 ;
753
+ int i = 0 ;
754
+ int end = value . Length ;
755
+ var state = ParseState . LeadingWhite ;
756
+ bool negative = false ;
757
+
758
+ //skip leading whitespaces
759
+ while ( i < end && JsonUtils . IsWhiteSpace ( value [ i ] ) ) i ++ ;
760
+
761
+ if ( i == end )
762
+ throw new FormatException ( MemoryProvider . BadFormat ) ;
763
+
764
+ //skip leading zeros
765
+ while ( i < end && value [ i ] == '0' )
766
+ {
767
+ state = ParseState . Number ;
768
+ i ++ ;
769
+ }
770
+
771
+ while ( i < end )
772
+ {
773
+ var c = value [ i ++ ] ;
774
+
775
+ switch ( state )
776
+ {
777
+ case ParseState . LeadingWhite :
778
+ if ( c == '-' )
779
+ {
780
+ negative = true ;
781
+ state = ParseState . Sign ;
782
+ }
783
+ else if ( c == '0' )
784
+ {
785
+ state = ParseState . TrailingWhite ;
786
+ }
787
+ else if ( c > '0' && c <= '9' )
788
+ {
789
+ result = - ( c - '0' ) ;
790
+ state = ParseState . Number ;
791
+ }
792
+ else throw new FormatException ( MemoryProvider . BadFormat ) ;
793
+
794
+ break ;
795
+ case ParseState . Sign :
796
+ if ( c == '0' )
797
+ {
798
+ state = ParseState . TrailingWhite ;
799
+ }
800
+ else if ( c > '0' && c <= '9' )
801
+ {
802
+ result = - ( c - '0' ) ;
803
+ state = ParseState . Number ;
804
+ }
805
+ else throw new FormatException ( MemoryProvider . BadFormat ) ;
806
+
807
+ break ;
808
+ case ParseState . Number :
809
+ if ( c >= '0' && c <= '9' )
810
+ {
811
+ checked
812
+ {
813
+ result = 10 * result - ( c - '0' ) ;
814
+ }
815
+
816
+ if ( result < minValue
817
+ ) //check only minvalue, because in absolute value it's greater than maxvalue
818
+ throw DefaultMemory . CreateOverflowException ( maxValue ) ;
819
+ }
820
+ else if ( JsonUtils . IsWhiteSpace ( c ) )
821
+ {
822
+ state = ParseState . TrailingWhite ;
823
+ }
824
+ else throw new FormatException ( MemoryProvider . BadFormat ) ;
825
+
826
+ break ;
827
+ case ParseState . TrailingWhite :
828
+ if ( JsonUtils . IsWhiteSpace ( c ) )
829
+ {
830
+ state = ParseState . TrailingWhite ;
831
+ }
832
+ else throw new FormatException ( MemoryProvider . BadFormat ) ;
833
+
834
+ break ;
835
+ }
836
+ }
837
+
838
+ if ( state != ParseState . Number && state != ParseState . TrailingWhite )
839
+ throw new FormatException ( MemoryProvider . BadFormat ) ;
840
+
841
+ if ( negative )
842
+ return result ;
843
+
844
+ checked
845
+ {
846
+ result = - result ;
847
+ }
848
+
849
+ if ( result > maxValue )
850
+ throw DefaultMemory . CreateOverflowException ( maxValue ) ;
851
+
852
+ return result ;
853
+ }
854
+ }
855
+
856
+ internal static class UnsignedInteger < T > where T : struct , IComparable < T > , IEquatable < T > , IConvertible
857
+ {
858
+ private static readonly TypeCode typeCode ;
859
+ private static readonly ulong maxValue ;
860
+
861
+ static UnsignedInteger ( )
862
+ {
863
+ typeCode = Type . GetTypeCode ( typeof ( T ) ) ;
864
+
865
+ switch ( typeCode )
866
+ {
867
+ case TypeCode . Byte :
868
+ maxValue = byte . MaxValue ;
869
+ break ;
870
+ case TypeCode . UInt16 :
871
+ maxValue = ushort . MaxValue ;
872
+ break ;
873
+ case TypeCode . UInt32 :
874
+ maxValue = uint . MaxValue ;
875
+ break ;
876
+ case TypeCode . UInt64 :
877
+ maxValue = ulong . MaxValue ;
878
+ break ;
879
+ default :
880
+ throw new NotSupportedException ( $ "{ typeof ( T ) . Name } is not a signed integer") ;
881
+ }
882
+ }
883
+
884
+ internal static object ParseNullableObject ( ReadOnlySpan < char > value )
885
+ {
886
+ if ( value . IsNullOrEmpty ( ) )
887
+ return null ;
888
+
889
+ return ParseObject ( value ) ;
890
+ }
891
+
892
+ internal static object ParseObject ( ReadOnlySpan < char > value )
893
+ {
894
+ var result = ParseUInt64 ( value ) ;
895
+ switch ( typeCode )
896
+ {
897
+ case TypeCode . Byte :
898
+ return ( byte ) result ;
899
+ case TypeCode . UInt16 :
900
+ return ( ushort ) result ;
901
+ case TypeCode . UInt32 :
902
+ return ( uint ) result ;
903
+ default :
904
+ return result ;
905
+ }
906
+ }
907
+
908
+ public static byte ParseByte ( ReadOnlySpan < char > value ) => ( byte ) ParseUInt64 ( value ) ;
909
+ public static ushort ParseUInt16 ( ReadOnlySpan < char > value ) => ( ushort ) ParseUInt64 ( value ) ;
910
+ public static uint ParseUInt32 ( ReadOnlySpan < char > value ) => ( uint ) ParseUInt64 ( value ) ;
911
+
912
+ internal static ulong ParseUInt64 ( ReadOnlySpan < char > value )
913
+ {
914
+ if ( value . IsEmpty )
915
+ throw new FormatException ( MemoryProvider . BadFormat ) ;
916
+
917
+ ulong result = 0 ;
918
+ int i = 0 ;
919
+ int end = value . Length ;
920
+ var state = ParseState . LeadingWhite ;
921
+
922
+ //skip leading whitespaces
923
+ while ( i < end && JsonUtils . IsWhiteSpace ( value [ i ] ) ) i ++ ;
924
+
925
+ if ( i == end )
926
+ throw new FormatException ( MemoryProvider . BadFormat ) ;
927
+
928
+ //skip leading zeros
929
+ while ( i < end && value [ i ] == '0' )
930
+ {
931
+ state = ParseState . Number ;
932
+ i ++ ;
933
+ }
934
+
935
+ while ( i < end )
936
+ {
937
+ var c = value [ i ++ ] ;
938
+
939
+ switch ( state )
940
+ {
941
+ case ParseState . LeadingWhite :
942
+ if ( JsonUtils . IsWhiteSpace ( c ) )
943
+ break ;
944
+ if ( c == '0' )
945
+ {
946
+ state = ParseState . TrailingWhite ;
947
+ }
948
+ else if ( c > '0' && c <= '9' )
949
+ {
950
+ result = ( ulong ) ( c - '0' ) ;
951
+ state = ParseState . Number ;
952
+ }
953
+ else throw new FormatException ( MemoryProvider . BadFormat ) ;
954
+
955
+
956
+ break ;
957
+ case ParseState . Number :
958
+ if ( c >= '0' && c <= '9' )
959
+ {
960
+ checked
961
+ {
962
+ result = 10 * result + ( ulong ) ( c - '0' ) ;
963
+ }
964
+
965
+ if ( result > maxValue
966
+ ) //check only minvalue, because in absolute value it's greater than maxvalue
967
+ throw DefaultMemory . CreateOverflowException ( maxValue ) ;
968
+ }
969
+ else if ( JsonUtils . IsWhiteSpace ( c ) )
970
+ {
971
+ state = ParseState . TrailingWhite ;
972
+ }
973
+ else throw new FormatException ( MemoryProvider . BadFormat ) ;
974
+
975
+ break ;
976
+ case ParseState . TrailingWhite :
977
+ if ( JsonUtils . IsWhiteSpace ( c ) )
978
+ {
979
+ state = ParseState . TrailingWhite ;
980
+ }
981
+ else throw new FormatException ( MemoryProvider . BadFormat ) ;
982
+
983
+ break ;
984
+ }
985
+ }
986
+
987
+ if ( state != ParseState . Number && state != ParseState . TrailingWhite )
988
+ throw new FormatException ( MemoryProvider . BadFormat ) ;
989
+
990
+ return result ;
991
+ }
992
+ }
672
993
}
0 commit comments