1
1
#include "ruby.h"
2
2
#include "../fbuffer/fbuffer.h"
3
+ #include "../vendor/fpconv.c"
3
4
4
5
#include <math.h>
5
6
#include <ctype.h>
@@ -1054,8 +1055,9 @@ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data
1054
1055
{
1055
1056
double value = RFLOAT_VALUE (obj );
1056
1057
char allow_nan = state -> allow_nan ;
1057
- if (!allow_nan ) {
1058
- if (isinf (value ) || isnan (value )) {
1058
+ if (isinf (value ) || isnan (value )) {
1059
+ /* for NaN and Infinity values we either raise an error or rely on Float#to_s. */
1060
+ if (!allow_nan ) {
1059
1061
if (state -> strict && state -> as_json ) {
1060
1062
VALUE casted_obj = rb_proc_call_with_block (state -> as_json , 1 , & obj , Qnil );
1061
1063
if (casted_obj != obj ) {
@@ -1067,8 +1069,24 @@ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data
1067
1069
}
1068
1070
raise_generator_error (obj , "%" PRIsVALUE " not allowed in JSON" , rb_funcall (obj , i_to_s , 0 ));
1069
1071
}
1072
+
1073
+ VALUE tmp = rb_funcall (obj , i_to_s , 0 );
1074
+ fbuffer_append_str (buffer , tmp );
1075
+ return ;
1070
1076
}
1071
- fbuffer_append_str (buffer , rb_funcall (obj , i_to_s , 0 ));
1077
+
1078
+ /* This implementation writes directly into the buffer. We reserve
1079
+ * the 24 characters that fpconv_dtoa states as its maximum, plus
1080
+ * 2 more characters for the potential ".0" suffix.
1081
+ */
1082
+ fbuffer_inc_capa (buffer , 26 );
1083
+ char * d = buffer -> ptr + buffer -> len ;
1084
+ int len = fpconv_dtoa (value , d );
1085
+
1086
+ /* fpconv_dtoa converts a float to its shortest string representation,
1087
+ * but it adds a ".0" if this is a plain integer.
1088
+ */
1089
+ buffer -> len += len ;
1072
1090
}
1073
1091
1074
1092
static void generate_json_fragment (FBuffer * buffer , struct generate_json_data * data , JSON_Generator_State * state , VALUE obj )
0 commit comments