@@ -37,13 +37,17 @@ static void fbuffer_append_long(FBuffer *fb, long number);
3737static inline void fbuffer_append_char (FBuffer * fb , char newchr );
3838static VALUE fbuffer_finalize (FBuffer * fb );
3939
40- static void fbuffer_stack_init (FBuffer * fb , size_t initial_length , char * stack_buffer , size_t stack_buffer_size )
40+ static void fbuffer_init (FBuffer * fb , size_t initial_length , VALUE io , char * stack_buffer , size_t stack_buffer_size )
4141{
42- fb -> initial_length = (initial_length > 0 ) ? initial_length : FBUFFER_INITIAL_LENGTH_DEFAULT ;
43- if (stack_buffer ) {
42+ if (RTEST (io )) {
43+ JSON_ASSERT (fb -> type == FBUFFER_HEAP_ALLOCATED );
44+ fb -> io = io ;
45+ fb -> initial_length = (initial_length > 0 ) ? initial_length : FBUFFER_IO_BUFFER_SIZE ;
46+ } else {
4447 fb -> type = FBUFFER_STACK_ALLOCATED ;
4548 fb -> ptr = stack_buffer ;
4649 fb -> capa = stack_buffer_size ;
50+ fb -> initial_length = (initial_length > 0 ) ? initial_length : FBUFFER_INITIAL_LENGTH_DEFAULT ;
4751 }
4852#if JSON_DEBUG
4953 fb -> requested = 0 ;
@@ -79,45 +83,40 @@ static void fbuffer_flush(FBuffer *fb)
7983 fbuffer_clear (fb );
8084}
8185
82- static void fbuffer_realloc (FBuffer * fb , size_t required )
86+ static void fbuffer_realloc (FBuffer * fb , size_t new_capa )
8387{
84- if (required > fb -> capa ) {
88+ if (new_capa > fb -> capa ) {
8589 if (fb -> type == FBUFFER_STACK_ALLOCATED ) {
8690 const char * old_buffer = fb -> ptr ;
87- fb -> ptr = ALLOC_N (char , required );
91+ fb -> ptr = ALLOC_N (char , new_capa );
8892 fb -> type = FBUFFER_HEAP_ALLOCATED ;
8993 MEMCPY (fb -> ptr , old_buffer , char , fb -> len );
9094 } else {
91- JSON_SIZED_REALLOC_N (fb -> ptr , char , required , fb -> capa );
95+ JSON_SIZED_REALLOC_N (fb -> ptr , char , new_capa , fb -> capa );
9296 }
93- fb -> capa = required ;
97+ fb -> capa = new_capa ;
9498 }
9599}
96100
97101static void fbuffer_do_inc_capa (FBuffer * fb , size_t requested )
98102{
99103 if (RB_UNLIKELY (fb -> io )) {
100- if (fb -> capa < FBUFFER_IO_BUFFER_SIZE ) {
101- fbuffer_realloc (fb , FBUFFER_IO_BUFFER_SIZE );
102- } else {
104+ if (fb -> capa != 0 ) {
103105 fbuffer_flush (fb );
104- }
105-
106- if (RB_LIKELY (requested < fb -> capa )) {
107- return ;
106+ if (RB_LIKELY (requested < fb -> capa )) {
107+ return ;
108+ }
108109 }
109110 }
110111
111- size_t required ;
112+ size_t new_capa = fb -> capa ? fb -> capa : fb -> initial_length ;
113+ size_t needed_capa = requested + fb -> len ;
112114
113- if (RB_UNLIKELY (!fb -> ptr )) {
114- fb -> ptr = ALLOC_N (char , fb -> initial_length );
115- fb -> capa = fb -> initial_length ;
115+ while (new_capa < needed_capa ) {
116+ new_capa *= 2 ;
116117 }
117118
118- for (required = fb -> capa ; requested > required - fb -> len ; required <<= 1 );
119-
120- fbuffer_realloc (fb , required );
119+ fbuffer_realloc (fb , new_capa );
121120}
122121
123122static inline void fbuffer_inc_capa (FBuffer * fb , size_t requested )
0 commit comments