summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2014-06-12 22:48:37 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2014-06-12 22:48:37 -0700
commit7a1f2b7c9de07c25046be344ff438048e707a3e3 (patch)
tree73dbd9f77dd40da0276aa04169c85196d5933a46 /ext
parentb6de464bacfc3aac73d84468a074d2860df8c94f (diff)
downloadffi-yajl-7a1f2b7c9de07c25046be344ff438048e707a3e3.tar.gz
fixing state context in the c extension
just pass self through the context and then access state and ruby objects through the instance variables. question? what if the self object is moved by the garbage collector?
Diffstat (limited to 'ext')
-rw-r--r--ext/ffi_yajl/ext/parser/parser.c45
1 files changed, 23 insertions, 22 deletions
diff --git a/ext/ffi_yajl/ext/parser/parser.c b/ext/ffi_yajl/ext/parser/parser.c
index faaaf8d..e806bd9 100644
--- a/ext/ffi_yajl/ext/parser/parser.c
+++ b/ext/ffi_yajl/ext/parser/parser.c
@@ -9,21 +9,20 @@ static rb_encoding *utf8Encoding;
static VALUE mFFI_Yajl, mExt, mParser, cParseError;
typedef struct {
- VALUE finished;
- VALUE stack;
- VALUE key_stack;
- VALUE key;
+ VALUE self;
} CTX;
void set_value(CTX *ctx, VALUE val) {
- long len = RARRAY_LEN(ctx->stack);
- VALUE last = rb_ary_entry(ctx->stack, len-1);
+ VALUE stack = rb_ivar_get(ctx->self, rb_intern("stack"));
+ VALUE key = rb_ivar_get(ctx->self, rb_intern("key"));
+ long len = RARRAY_LEN(stack);
+ VALUE last = rb_ary_entry(stack, len-1);
switch (TYPE(last)) {
case T_ARRAY:
rb_ary_push(last, val);
break;
case T_HASH:
- rb_hash_aset(last, ctx->key, val);
+ rb_hash_aset(last, key, val);
break;
default:
break;
@@ -31,20 +30,26 @@ void set_value(CTX *ctx, VALUE val) {
}
void set_key(CTX *ctx, VALUE key) {
- ctx->key = key;
+ rb_ivar_set(ctx->self, rb_intern("key"), key);
}
void start_object(CTX *ctx, VALUE obj) {
- rb_ary_push(ctx->key_stack, ctx->key);
- rb_ary_push(ctx->stack, obj);
+ VALUE key_stack = rb_ivar_get(ctx->self, rb_intern("key_stack"));
+ VALUE key = rb_ivar_get(ctx->self, rb_intern("key"));
+ VALUE stack = rb_ivar_get(ctx->self, rb_intern("stack"));
+
+ rb_ary_push(key_stack, key);
+ rb_ary_push(stack, obj);
}
void end_object(CTX *ctx) {
- ctx->key = rb_ary_pop(ctx->key_stack);
- if ( RARRAY_LEN(ctx->stack) > 1 ) {
- set_value(ctx, rb_ary_pop(ctx->stack));
+ VALUE key_stack = rb_ivar_get(ctx->self, rb_intern("key_stack"));
+ VALUE stack = rb_ivar_get(ctx->self, rb_intern("stack"));
+ rb_ivar_set(ctx->self, rb_intern("key"), rb_ary_pop(key_stack));
+ if ( RARRAY_LEN(stack) > 1 ) {
+ set_value(ctx, rb_ary_pop(stack));
} else {
- ctx->finished = rb_ary_pop(ctx->stack);
+ rb_ivar_set(ctx->self, rb_intern("finished"), rb_ary_pop(stack));
}
}
@@ -164,14 +169,10 @@ static VALUE mParser_do_yajl_parse(VALUE self, VALUE str, VALUE opts) {
unsigned char *err;
CTX ctx;
- /* hack to avoid garbage collection */
- rb_ivar_set(self, rb_intern("stack"), ctx.stack);
- rb_ivar_set(self, rb_intern("key_stack"), ctx.key_stack);
- rb_ivar_set(self, rb_intern("finished"), ctx.stack);
- rb_ivar_set(self, rb_intern("key"), ctx.stack);
+ rb_ivar_set(self, rb_intern("stack"), rb_ary_new());
+ rb_ivar_set(self, rb_intern("key_stack"), rb_ary_new());
- ctx.stack = rb_ary_new();
- ctx.key_stack = rb_ary_new();
+ ctx.self = self;
hand = yajl_alloc(&callbacks, NULL, &ctx);
if ((stat = yajl_parse(hand, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str))) != yajl_status_ok) {
@@ -183,7 +184,7 @@ static VALUE mParser_do_yajl_parse(VALUE self, VALUE str, VALUE opts) {
goto raise;
}
yajl_free(hand);
- return ctx.finished;
+ return rb_ivar_get(self, rb_intern("finished"));
raise:
if (hand) {