1
1
#include "../fbuffer/fbuffer.h"
2
2
#include "generator.h"
3
3
4
+ #ifndef RB_UNLIKELY
5
+ #define RB_UNLIKELY (cond ) (cond)
6
+ #endif
7
+
4
8
static VALUE mJSON , mExt , mGenerator , cState , mGeneratorMethods , mObject ,
5
9
mHash , mArray ,
6
10
#ifdef RUBY_INTEGER_UNIFICATION
@@ -417,9 +421,6 @@ static void State_free(void *ptr)
417
421
if (state -> space_before ) ruby_xfree (state -> space_before );
418
422
if (state -> object_nl ) ruby_xfree (state -> object_nl );
419
423
if (state -> array_nl ) ruby_xfree (state -> array_nl );
420
- if (state -> array_delim ) fbuffer_free (state -> array_delim );
421
- if (state -> object_delim ) fbuffer_free (state -> object_delim );
422
- if (state -> object_delim2 ) fbuffer_free (state -> object_delim2 );
423
424
ruby_xfree (state );
424
425
}
425
426
@@ -432,9 +433,6 @@ static size_t State_memsize(const void *ptr)
432
433
if (state -> space_before ) size += state -> space_before_len + 1 ;
433
434
if (state -> object_nl ) size += state -> object_nl_len + 1 ;
434
435
if (state -> array_nl ) size += state -> array_nl_len + 1 ;
435
- if (state -> array_delim ) size += FBUFFER_CAPA (state -> array_delim );
436
- if (state -> object_delim ) size += FBUFFER_CAPA (state -> object_delim );
437
- if (state -> object_delim2 ) size += FBUFFER_CAPA (state -> object_delim2 );
438
436
return size ;
439
437
}
440
438
@@ -644,24 +642,16 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
644
642
JSON_Generator_State * state = arg -> state ;
645
643
VALUE Vstate = arg -> Vstate ;
646
644
647
- char * object_nl = state -> object_nl ;
648
- long object_nl_len = state -> object_nl_len ;
649
- char * indent = state -> indent ;
650
- long indent_len = state -> indent_len ;
651
- char * delim = FBUFFER_PTR (state -> object_delim );
652
- long delim_len = FBUFFER_LEN (state -> object_delim );
653
- char * delim2 = FBUFFER_PTR (state -> object_delim2 );
654
- long delim2_len = FBUFFER_LEN (state -> object_delim2 );
655
645
long depth = state -> depth ;
656
646
int j ;
657
647
658
- if (arg -> iter > 0 ) fbuffer_append (buffer , delim , delim_len );
659
- if (object_nl ) {
660
- fbuffer_append (buffer , object_nl , object_nl_len );
648
+ if (arg -> iter > 0 ) fbuffer_append_char (buffer , ',' );
649
+ if (RB_UNLIKELY ( state -> object_nl ) ) {
650
+ fbuffer_append (buffer , state -> object_nl , state -> object_nl_len );
661
651
}
662
- if (indent ) {
652
+ if (RB_UNLIKELY ( state -> indent ) ) {
663
653
for (j = 0 ; j < depth ; j ++ ) {
664
- fbuffer_append (buffer , indent , indent_len );
654
+ fbuffer_append (buffer , state -> indent , state -> indent_len );
665
655
}
666
656
}
667
657
@@ -678,8 +668,10 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
678
668
break ;
679
669
}
680
670
681
- generate_json (buffer , Vstate , state , key_to_s );
682
- fbuffer_append (buffer , delim2 , delim2_len );
671
+ generate_json_string (buffer , Vstate , state , key_to_s );
672
+ if (RB_UNLIKELY (state -> space_before )) fbuffer_append (buffer , state -> space_before , state -> space_before_len );
673
+ fbuffer_append_char (buffer , ':' );
674
+ if (RB_UNLIKELY (state -> space )) fbuffer_append (buffer , state -> space , state -> space_len );
683
675
generate_json (buffer , Vstate , state , val );
684
676
685
677
arg -> iter ++ ;
@@ -688,10 +680,6 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
688
680
689
681
static void generate_json_object (FBuffer * buffer , VALUE Vstate , JSON_Generator_State * state , VALUE obj )
690
682
{
691
- char * object_nl = state -> object_nl ;
692
- long object_nl_len = state -> object_nl_len ;
693
- char * indent = state -> indent ;
694
- long indent_len = state -> indent_len ;
695
683
long max_nesting = state -> max_nesting ;
696
684
long depth = ++ state -> depth ;
697
685
int j ;
@@ -709,11 +697,11 @@ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
709
697
rb_hash_foreach (obj , json_object_i , (VALUE )& arg );
710
698
711
699
depth = -- state -> depth ;
712
- if (object_nl ) {
713
- fbuffer_append (buffer , object_nl , object_nl_len );
714
- if (indent ) {
700
+ if (RB_UNLIKELY ( state -> object_nl ) ) {
701
+ fbuffer_append (buffer , state -> object_nl , state -> object_nl_len );
702
+ if (RB_UNLIKELY ( state -> indent ) ) {
715
703
for (j = 0 ; j < depth ; j ++ ) {
716
- fbuffer_append (buffer , indent , indent_len );
704
+ fbuffer_append (buffer , state -> indent , state -> indent_len );
717
705
}
718
706
}
719
707
}
@@ -722,52 +710,51 @@ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
722
710
723
711
static void generate_json_array (FBuffer * buffer , VALUE Vstate , JSON_Generator_State * state , VALUE obj )
724
712
{
725
- char * array_nl = state -> array_nl ;
726
- long array_nl_len = state -> array_nl_len ;
727
- char * indent = state -> indent ;
728
- long indent_len = state -> indent_len ;
729
713
long max_nesting = state -> max_nesting ;
730
- char * delim = FBUFFER_PTR (state -> array_delim );
731
- long delim_len = FBUFFER_LEN (state -> array_delim );
732
714
long depth = ++ state -> depth ;
733
715
int i , j ;
734
716
if (max_nesting != 0 && depth > max_nesting ) {
735
717
rb_raise (eNestingError , "nesting of %ld is too deep" , -- state -> depth );
736
718
}
737
719
fbuffer_append_char (buffer , '[' );
738
- if (array_nl ) fbuffer_append (buffer , array_nl , array_nl_len );
720
+ if (RB_UNLIKELY ( state -> array_nl )) fbuffer_append (buffer , state -> array_nl , state -> array_nl_len );
739
721
for (i = 0 ; i < RARRAY_LEN (obj ); i ++ ) {
740
- if (i > 0 ) fbuffer_append (buffer , delim , delim_len );
741
- if (indent ) {
722
+ if (i > 0 ) {
723
+ fbuffer_append_char (buffer , ',' );
724
+ if (RB_UNLIKELY (state -> array_nl )) fbuffer_append (buffer , state -> array_nl , state -> array_nl_len );
725
+ }
726
+ if (RB_UNLIKELY (state -> indent )) {
742
727
for (j = 0 ; j < depth ; j ++ ) {
743
- fbuffer_append (buffer , indent , indent_len );
728
+ fbuffer_append (buffer , state -> indent , state -> indent_len );
744
729
}
745
730
}
746
- generate_json (buffer , Vstate , state , rb_ary_entry (obj , i ));
731
+ generate_json (buffer , Vstate , state , RARRAY_AREF (obj , i ));
747
732
}
748
733
state -> depth = -- depth ;
749
- if (array_nl ) {
750
- fbuffer_append (buffer , array_nl , array_nl_len );
751
- if (indent ) {
734
+ if (RB_UNLIKELY ( state -> array_nl ) ) {
735
+ fbuffer_append (buffer , state -> array_nl , state -> array_nl_len );
736
+ if (RB_UNLIKELY ( state -> indent ) ) {
752
737
for (j = 0 ; j < depth ; j ++ ) {
753
- fbuffer_append (buffer , indent , indent_len );
738
+ fbuffer_append (buffer , state -> indent , state -> indent_len );
754
739
}
755
740
}
756
741
}
757
742
fbuffer_append_char (buffer , ']' );
758
743
}
759
744
760
- static int enc_utf8_compatible_p (rb_encoding * enc )
745
+ static int usascii_encindex , utf8_encindex ;
746
+
747
+ static int enc_utf8_compatible_p (int enc_idx )
761
748
{
762
- if (enc == rb_usascii_encoding () ) return 1 ;
763
- if (enc == rb_utf8_encoding () ) return 1 ;
749
+ if (enc_idx == usascii_encindex ) return 1 ;
750
+ if (enc_idx == utf8_encindex ) return 1 ;
764
751
return 0 ;
765
752
}
766
753
767
754
static void generate_json_string (FBuffer * buffer , VALUE Vstate , JSON_Generator_State * state , VALUE obj )
768
755
{
769
756
fbuffer_append_char (buffer , '"' );
770
- if (!enc_utf8_compatible_p (rb_enc_get (obj ))) {
757
+ if (!enc_utf8_compatible_p (RB_ENCODING_GET (obj ))) {
771
758
obj = rb_str_export_to_enc (obj , rb_utf8_encoding ());
772
759
}
773
760
convert_UTF8_to_JSON (buffer , obj , state -> ascii_only , state -> script_safe );
@@ -827,35 +814,56 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
827
814
static void generate_json (FBuffer * buffer , VALUE Vstate , JSON_Generator_State * state , VALUE obj )
828
815
{
829
816
VALUE tmp ;
830
- VALUE klass = CLASS_OF (obj );
831
- if (klass == rb_cHash ) {
832
- generate_json_object (buffer , Vstate , state , obj );
833
- } else if (klass == rb_cArray ) {
834
- generate_json_array (buffer , Vstate , state , obj );
835
- } else if (klass == rb_cString ) {
836
- generate_json_string (buffer , Vstate , state , obj );
837
- } else if (obj == Qnil ) {
817
+ if (obj == Qnil ) {
838
818
generate_json_null (buffer , Vstate , state , obj );
839
819
} else if (obj == Qfalse ) {
840
820
generate_json_false (buffer , Vstate , state , obj );
841
821
} else if (obj == Qtrue ) {
842
822
generate_json_true (buffer , Vstate , state , obj );
843
- } else if (FIXNUM_P (obj )) {
844
- generate_json_fixnum (buffer , Vstate , state , obj );
845
- } else if (RB_TYPE_P (obj , T_BIGNUM )) {
846
- generate_json_bignum (buffer , Vstate , state , obj );
847
- } else if (klass == rb_cFloat ) {
848
- generate_json_float (buffer , Vstate , state , obj );
849
- } else if (state -> strict ) {
850
- rb_raise (eGeneratorError , "%" PRIsVALUE " not allowed in JSON" , RB_OBJ_STRING (CLASS_OF (obj )));
851
- } else if (rb_respond_to (obj , i_to_json )) {
852
- tmp = rb_funcall (obj , i_to_json , 1 , Vstate );
853
- Check_Type (tmp , T_STRING );
854
- fbuffer_append_str (buffer , tmp );
823
+ } else if (RB_SPECIAL_CONST_P (obj )) {
824
+ if (RB_FIXNUM_P (obj )) {
825
+ generate_json_fixnum (buffer , Vstate , state , obj );
826
+ } else if (RB_FLONUM_P (obj )) {
827
+ generate_json_float (buffer , Vstate , state , obj );
828
+ } else {
829
+ goto general ;
830
+ }
855
831
} else {
856
- tmp = rb_funcall (obj , i_to_s , 0 );
857
- Check_Type (tmp , T_STRING );
858
- generate_json_string (buffer , Vstate , state , tmp );
832
+ VALUE klass = RBASIC_CLASS (obj );
833
+ switch (RB_BUILTIN_TYPE (obj )) {
834
+ case T_BIGNUM :
835
+ generate_json_bignum (buffer , Vstate , state , obj );
836
+ break ;
837
+ case T_HASH :
838
+ if (klass != rb_cHash ) goto general ;
839
+ generate_json_object (buffer , Vstate , state , obj );
840
+ break ;
841
+ case T_ARRAY :
842
+ if (klass != rb_cArray ) goto general ;
843
+ generate_json_array (buffer , Vstate , state , obj );
844
+ break ;
845
+ case T_STRING :
846
+ if (klass != rb_cString ) goto general ;
847
+ generate_json_string (buffer , Vstate , state , obj );
848
+ break ;
849
+ case T_FLOAT :
850
+ if (klass != rb_cFloat ) goto general ;
851
+ generate_json_float (buffer , Vstate , state , obj );
852
+ break ;
853
+ default :
854
+ general :
855
+ if (state -> strict ) {
856
+ rb_raise (eGeneratorError , "%" PRIsVALUE " not allowed in JSON" , RB_OBJ_STRING (CLASS_OF (obj )));
857
+ } else if (rb_respond_to (obj , i_to_json )) {
858
+ tmp = rb_funcall (obj , i_to_json , 1 , Vstate );
859
+ Check_Type (tmp , T_STRING );
860
+ fbuffer_append_str (buffer , tmp );
861
+ } else {
862
+ tmp = rb_funcall (obj , i_to_s , 0 );
863
+ Check_Type (tmp , T_STRING );
864
+ generate_json_string (buffer , Vstate , state , tmp );
865
+ }
866
+ }
859
867
}
860
868
}
861
869
@@ -865,28 +873,6 @@ static FBuffer *cState_prepare_buffer(VALUE self)
865
873
GET_STATE (self );
866
874
buffer = fbuffer_alloc (state -> buffer_initial_length );
867
875
868
- if (state -> object_delim ) {
869
- fbuffer_clear (state -> object_delim );
870
- } else {
871
- state -> object_delim = fbuffer_alloc (16 );
872
- }
873
- fbuffer_append_char (state -> object_delim , ',' );
874
- if (state -> object_delim2 ) {
875
- fbuffer_clear (state -> object_delim2 );
876
- } else {
877
- state -> object_delim2 = fbuffer_alloc (16 );
878
- }
879
- if (state -> space_before ) fbuffer_append (state -> object_delim2 , state -> space_before , state -> space_before_len );
880
- fbuffer_append_char (state -> object_delim2 , ':' );
881
- if (state -> space ) fbuffer_append (state -> object_delim2 , state -> space , state -> space_len );
882
-
883
- if (state -> array_delim ) {
884
- fbuffer_clear (state -> array_delim );
885
- } else {
886
- state -> array_delim = fbuffer_alloc (16 );
887
- }
888
- fbuffer_append_char (state -> array_delim , ',' );
889
- if (state -> array_nl ) fbuffer_append (state -> array_delim , state -> array_nl , state -> array_nl_len );
890
876
return buffer ;
891
877
}
892
878
@@ -999,9 +985,6 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig)
999
985
objState -> space_before = fstrndup (origState -> space_before , origState -> space_before_len );
1000
986
objState -> object_nl = fstrndup (origState -> object_nl , origState -> object_nl_len );
1001
987
objState -> array_nl = fstrndup (origState -> array_nl , origState -> array_nl_len );
1002
- if (origState -> array_delim ) objState -> array_delim = fbuffer_dup (origState -> array_delim );
1003
- if (origState -> object_delim ) objState -> object_delim = fbuffer_dup (origState -> object_delim );
1004
- if (origState -> object_delim2 ) objState -> object_delim2 = fbuffer_dup (origState -> object_delim2 );
1005
988
return obj ;
1006
989
}
1007
990
@@ -1498,4 +1481,7 @@ void Init_generator(void)
1498
1481
i_match = rb_intern ("match" );
1499
1482
i_keys = rb_intern ("keys" );
1500
1483
i_dup = rb_intern ("dup" );
1484
+
1485
+ usascii_encindex = rb_usascii_encindex ();
1486
+ utf8_encindex = rb_utf8_encindex ();
1501
1487
}
0 commit comments