Skip to content

Commit 996bac6

Browse files
committed
generator.c: don't start with a stack buffer in IO case
It was never intended to be initialized with a stack buffer in that case, as when dumping into an IO we want larger chunks.
1 parent 8144d4c commit 996bac6

2 files changed

Lines changed: 25 additions & 30 deletions

File tree

ext/json/ext/fbuffer/fbuffer.h

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,17 @@ static void fbuffer_append_long(FBuffer *fb, long number);
3737
static inline void fbuffer_append_char(FBuffer *fb, char newchr);
3838
static 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

97101
static 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

123122
static inline void fbuffer_inc_capa(FBuffer *fb, size_t requested)

ext/json/ext/generator/generator.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,10 +1308,8 @@ static inline VALUE cState_partial_generate(VALUE self, VALUE obj, generator_fun
13081308
GET_STATE(self);
13091309

13101310
char stack_buffer[FBUFFER_STACK_SIZE];
1311-
FBuffer buffer = {
1312-
.io = RTEST(io) ? io : Qfalse,
1313-
};
1314-
fbuffer_stack_init(&buffer, state->buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
1311+
FBuffer buffer = { 0 };
1312+
fbuffer_init(&buffer, state->buffer_initial_length, io, stack_buffer, FBUFFER_STACK_SIZE);
13151313

13161314
struct generate_json_data data = {
13171315
.buffer = &buffer,
@@ -1870,10 +1868,8 @@ static VALUE cState_m_do_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io,
18701868
configure_state(&state, Qfalse, opts);
18711869

18721870
char stack_buffer[FBUFFER_STACK_SIZE];
1873-
FBuffer buffer = {
1874-
.io = RTEST(io) ? io : Qfalse,
1875-
};
1876-
fbuffer_stack_init(&buffer, state.buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
1871+
FBuffer buffer = { 0 };
1872+
fbuffer_init(&buffer, state.buffer_initial_length, io, stack_buffer, FBUFFER_STACK_SIZE);
18771873

18781874
struct generate_json_data data = {
18791875
.buffer = &buffer,

0 commit comments

Comments
 (0)