summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Frank <flori@ping.de>2009-11-05 23:44:36 +0100
committerFlorian Frank <flori@ping.de>2009-11-07 14:41:20 +0100
commit15a6246ec0b32272014fce1d023ac8c933d898dd (patch)
tree3f90a24084488be6396a04b7ce2dc94743cd1e99
parentb6e068308f318f32436a2f4003d6a0d4753a829b (diff)
downloadjson-15a6246ec0b32272014fce1d023ac8c933d898dd.tar.gz
prebuild delimiters
-rw-r--r--ext/json/ext/generator/fbuffer.c18
-rw-r--r--ext/json/ext/generator/fbuffer.h7
-rw-r--r--ext/json/ext/generator/generator.c73
3 files changed, 58 insertions, 40 deletions
diff --git a/ext/json/ext/generator/fbuffer.c b/ext/json/ext/generator/fbuffer.c
index 66d4b61..0448a8d 100644
--- a/ext/json/ext/generator/fbuffer.c
+++ b/ext/json/ext/generator/fbuffer.c
@@ -1,13 +1,23 @@
-#include "ruby.h"
#include "fbuffer.h"
inline FBuffer *fbuffer_alloc()
{
FBuffer *fb = ALLOC(FBuffer);
memset((void *) fb, 0, sizeof(FBuffer));
+ fb->initial_length = FBUFFER_INITIAL_LENGTH;
return fb;
}
+inline FBuffer *fbuffer_alloc_with_length(unsigned int initial_length)
+{
+ assert(initial_length > 0);
+ FBuffer *fb = ALLOC(FBuffer);
+ memset((void *) fb, 0, sizeof(FBuffer));
+ fb->initial_length = initial_length;
+ return fb;
+}
+
+
inline void fbuffer_free(FBuffer *fb)
{
if (fb->ptr) ruby_xfree(fb->ptr);
@@ -24,8 +34,8 @@ inline void fbuffer_inc_capa(FBuffer *fb, unsigned int requested)
unsigned int required;
if (!fb->ptr) {
- fb->ptr = ALLOC_N(char, FBUFFER_INITIAL_LENGTH);
- fb->capa = FBUFFER_INITIAL_LENGTH;
+ fb->ptr = ALLOC_N(char, fb->initial_length);
+ fb->capa = fb->initial_length;
}
for (required = fb->capa; requested > required - fb->len; required <<= 1);
@@ -45,7 +55,7 @@ inline void fbuffer_append(FBuffer *fb, const char *newstr, unsigned int len)
}
}
-inline void fbuffer_append_char(FBuffer *fb, const char newchr)
+inline void fbuffer_append_char(FBuffer *fb, char newchr)
{
fbuffer_inc_capa(fb, 1);
*(fb->ptr + fb->len) = newchr;
diff --git a/ext/json/ext/generator/fbuffer.h b/ext/json/ext/generator/fbuffer.h
index 3b42721..7641470 100644
--- a/ext/json/ext/generator/fbuffer.h
+++ b/ext/json/ext/generator/fbuffer.h
@@ -1,7 +1,11 @@
#ifndef _FBUFFER_H_
#define _FBUFFER_H_
+#include <assert.h>
+#include "ruby.h"
+
typedef struct FBufferStruct {
+ unsigned int initial_length;
char *ptr;
unsigned int len;
unsigned int capa;
@@ -14,10 +18,11 @@ typedef struct FBufferStruct {
#define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb)
inline FBuffer *fbuffer_alloc();
+inline FBuffer *fbuffer_alloc_with_length(unsigned initial_length);
inline void fbuffer_free(FBuffer *fb);
inline void fbuffer_clear(FBuffer *fb);
inline void fbuffer_inc_capa(FBuffer *fb, unsigned int requested);
inline void fbuffer_append(FBuffer *fb, const char *newstr, unsigned int len);
-inline void fbuffer_append_char(FBuffer *fb, const char newchr);
+inline void fbuffer_append_char(FBuffer *fb, char newchr);
#endif
diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c
index 4d017f0..ac2eb8f 100644
--- a/ext/json/ext/generator/generator.c
+++ b/ext/json/ext/generator/generator.c
@@ -59,8 +59,9 @@ typedef struct JSON_Generator_StateStruct {
long object_nl_len;
char *array_nl;
long array_nl_len;
- FBuffer *delim;
- FBuffer *delim2;
+ FBuffer *array_delim;
+ FBuffer *object_delim;
+ FBuffer *object_delim2;
long max_nesting;
char allow_nan;
char ascii_only;
@@ -272,8 +273,9 @@ static void State_free(JSON_Generator_State *state) {
if (state->space_before) ruby_xfree(state->space_before);
if (state->object_nl) ruby_xfree(state->object_nl);
if (state->array_nl) ruby_xfree(state->array_nl);
- if (state->delim) fbuffer_free(state->delim);
- if (state->delim2) fbuffer_free(state->delim2);
+ if (state->array_delim) fbuffer_free(state->array_delim);
+ if (state->object_delim) fbuffer_free(state->object_delim);
+ if (state->object_delim2) fbuffer_free(state->object_delim2);
ruby_xfree(state);
}
@@ -382,40 +384,24 @@ void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, V
{
char *object_nl = state->object_nl;
long object_nl_len = state->object_nl_len;
- char *space = state->space;
- long space_len = state->space_len;
- char *space_before = state->space_before;
- long space_before_len = state->space_before_len;
char *indent = state->indent;
long indent_len = state->indent_len;
long max_nesting = state->max_nesting;
+ char *delim = FBUFFER_PTR(state->object_delim);
+ long delim_len = FBUFFER_LEN(state->object_delim);
+ char *delim2 = FBUFFER_PTR(state->object_delim2);
+ long delim2_len = FBUFFER_LEN(state->object_delim2);
int i, j;
- FBuffer *delim, *delim2;
- if (delim = state->delim) {
- fbuffer_clear(delim);
- } else {
- delim = state->delim = fbuffer_alloc();
- }
- if (delim2 = state->delim2) {
- fbuffer_clear(delim2);
- } else {
- delim2 = state->delim2 = fbuffer_alloc();
- }
- fbuffer_append_char(delim, ',');
depth++;
if (max_nesting != 0 && depth > max_nesting) {
fbuffer_free(buffer);
rb_raise(eNestingError, "nesting of %ld is too deep", depth);
}
- if (object_nl) fbuffer_append(delim, object_nl, object_nl_len);
- if (space_before) fbuffer_append(delim2, space_before, space_before_len);
- fbuffer_append_char(delim2, ':');
- if (space) fbuffer_append(delim2, space, space_len);
fbuffer_append_char(buffer, '{');
VALUE keys = rb_funcall(obj, rb_intern("keys"), 0);
VALUE key, key_to_s;
for(i = 0; i < RARRAY_LEN(keys); i++) {
- if (i > 0) fbuffer_append(buffer, FBUFFER_PAIR(delim));
+ if (i > 0) fbuffer_append(buffer, delim, delim_len);
if (object_nl) {
fbuffer_append(buffer, object_nl, object_nl_len);
}
@@ -428,7 +414,7 @@ void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, V
key_to_s = rb_funcall(key, i_to_s, 0);
Check_Type(key_to_s, T_STRING);
generate_json(buffer, Vstate, state, key_to_s, depth);
- fbuffer_append(buffer, FBUFFER_PAIR(delim2));
+ fbuffer_append(buffer, delim2, delim2_len);
generate_json(buffer, Vstate, state, rb_hash_aref(obj, key), depth);
}
depth--;
@@ -450,24 +436,18 @@ void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, V
char *indent = state->indent;
long indent_len = state->indent_len;
long max_nesting = state->max_nesting;
+ char *delim = FBUFFER_PTR(state->array_delim);
+ long delim_len = FBUFFER_LEN(state->array_delim);
int i, j;
- FBuffer *delim;
- if (delim = state->delim) {
- fbuffer_clear(delim);
- } else {
- delim = state->delim = fbuffer_alloc();
- }
- fbuffer_append_char(delim, ',');
depth++;
if (max_nesting != 0 && depth > max_nesting) {
fbuffer_free(buffer);
rb_raise(eNestingError, "nesting of %ld is too deep", depth);
}
- if (array_nl) fbuffer_append(delim, array_nl, array_nl_len);
fbuffer_append_char(buffer, '[');
if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len);
for(i = 0; i < RARRAY_LEN(obj); i++) {
- if (i > 0) fbuffer_append(buffer, FBUFFER_PAIR(delim));
+ if (i > 0) fbuffer_append(buffer, delim, delim_len);
if (indent) {
for (j = 0; j < depth; j++) {
fbuffer_append(buffer, indent, indent_len);
@@ -553,6 +533,29 @@ inline static VALUE cState_partial_generate(VALUE self, VALUE obj, VALUE depth)
VALUE result;
FBuffer *buffer = fbuffer_alloc();
GET_STATE(self);
+
+ if (state->object_delim) {
+ fbuffer_clear(state->object_delim);
+ } else {
+ state->object_delim = fbuffer_alloc_with_length(16);
+ }
+ fbuffer_append_char(state->object_delim, ',');
+ if (state->object_delim2) {
+ fbuffer_clear(state->object_delim2);
+ } else {
+ state->object_delim2 = fbuffer_alloc_with_length(16);
+ }
+ fbuffer_append_char(state->object_delim2, ':');
+ if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len);
+
+ if (state->array_delim) {
+ fbuffer_clear(state->array_delim);
+ } else {
+ state->array_delim = fbuffer_alloc_with_length(16);
+ }
+ fbuffer_append_char(state->array_delim, ',');
+ if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len);
+
generate_json(buffer, self, state, obj, NIL_P(depth) ? 0 : FIX2INT(depth));
result = rb_str_new(FBUFFER_PAIR(buffer));
fbuffer_free(buffer);