@@ -1027,6 +1027,8 @@ private double convertStringToDoubleOrThrow(String str) throws NumberFormatExcep
1027
1027
StringBuilder s = null ;
1028
1028
int n = str .length ();
1029
1029
1030
+ boolean containsUnderscores = false ;
1031
+ boolean containsN = false ;
1030
1032
for (int i = 0 ; i < n ; i ++) {
1031
1033
char ch = str .charAt (i );
1032
1034
if (ch == '\u0000' || ch == 'x' || ch == 'X' ) {
@@ -1045,21 +1047,52 @@ private double convertStringToDoubleOrThrow(String str) throws NumberFormatExcep
1045
1047
}
1046
1048
s .setCharAt (i , ' ' );
1047
1049
}
1048
- }
1049
- String sval = s != null ? s .toString () : str .trim ();
1050
- String lowSval = sval .toLowerCase (Locale .ENGLISH );
1051
- if (lowSval .equals ("nan" ) || lowSval .equals ("+nan" )) {
1052
- return Double .NaN ;
1053
- } else if (lowSval .equals ("-nan" )) {
1054
- return Math .copySign (Double .NaN , -1 );
1055
- } else if (lowSval .equals ("inf" ) || lowSval .equals ("+inf" ) || lowSval .equals ("infinity" ) || lowSval .equals ("+infinity" )) {
1056
- return Double .POSITIVE_INFINITY ;
1057
- } else if (lowSval .equals ("-inf" ) || lowSval .equals ("-infinity" )) {
1058
- return Double .NEGATIVE_INFINITY ;
1050
+ containsUnderscores |= ch == '_' ;
1051
+ containsN |= ch == 'n' || ch == 'N' ;
1052
+ }
1053
+ String sval = s != null ? s .toString ().trim () : str ;
1054
+ if (containsUnderscores ) {
1055
+ sval = checkAndRemoveUnderscores (sval );
1056
+ }
1057
+ if (containsN ) {
1058
+ String lowSval = sval .toLowerCase (Locale .ENGLISH );
1059
+ if (lowSval .equals ("nan" ) || lowSval .equals ("+nan" )) {
1060
+ return Double .NaN ;
1061
+ } else if (lowSval .equals ("-nan" )) {
1062
+ return Math .copySign (Double .NaN , -1 );
1063
+ } else if (lowSval .equals ("inf" ) || lowSval .equals ("+inf" ) || lowSval .equals ("infinity" ) || lowSval .equals ("+infinity" )) {
1064
+ return Double .POSITIVE_INFINITY ;
1065
+ } else if (lowSval .equals ("-inf" ) || lowSval .equals ("-infinity" )) {
1066
+ return Double .NEGATIVE_INFINITY ;
1067
+ }
1059
1068
}
1060
1069
return Double .parseDouble (sval );
1061
1070
}
1062
1071
1072
+ private static String checkAndRemoveUnderscores (String src ) {
1073
+ StringBuilder sb = new StringBuilder ();
1074
+ char prev = 0 ;
1075
+ int len = src .length ();
1076
+ for (int i = 0 ; i < len ; i ++) {
1077
+ char ch = src .charAt (i );
1078
+ if (ch == '_' ) {
1079
+ if (!(prev >= '0' && prev <= '9' )) {
1080
+ throw new NumberFormatException ();
1081
+ }
1082
+ } else {
1083
+ if (prev == '_' && !(ch >= '0' && ch <= '9' )) {
1084
+ throw new NumberFormatException ();
1085
+ }
1086
+ sb .append (ch );
1087
+ }
1088
+ prev = ch ;
1089
+ }
1090
+ if (prev == '_' ) {
1091
+ throw new NumberFormatException ();
1092
+ }
1093
+ return sb .toString ();
1094
+ }
1095
+
1063
1096
@ Specialization (guards = "!isNativeClass(cls)" )
1064
1097
Object floatFromNone (Object cls , @ SuppressWarnings ("unused" ) PNone arg ) {
1065
1098
if (isPrimitiveFloat (cls )) {
0 commit comments