summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ffi_yajl/ffi/parser.rb60
1 files changed, 27 insertions, 33 deletions
diff --git a/lib/ffi_yajl/ffi/parser.rb b/lib/ffi_yajl/ffi/parser.rb
index 05fa11e..4df58da 100644
--- a/lib/ffi_yajl/ffi/parser.rb
+++ b/lib/ffi_yajl/ffi/parser.rb
@@ -1,12 +1,17 @@
+
+require 'ffi_yajl/ffi'
+
module FFI_Yajl
module FFI
module Parser
- class State
attr_accessor :stack, :key_stack, :key
- def initialize
- @stack = Array.new
- @key_stack = Array.new
+ def stack
+ @stack ||= Array.new
+ end
+
+ def key_stack
+ @key_stack ||= Array.new
end
def save_key
@@ -28,20 +33,18 @@ module FFI_Yajl
raise
end
end
- end
def setup_callbacks
- ctx_mapping = @ctx_mapping # get a local alias
@null_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
- ctx_mapping[ctx.get_ulong(0)].set_value(nil)
+ self.set_value(nil)
1
end
@boolean_callback = ::FFI::Function.new(:int, [:pointer, :int]) do |ctx, boolval|
- ctx_mapping[ctx.get_ulong(0)].set_value(boolval == 1 ? true : false)
+ self.set_value(boolval == 1 ? true : false)
1
end
@integer_callback = ::FFI::Function.new(:int, [:pointer, :long_long]) do |ctx, intval|
- ctx_mapping[ctx.get_ulong(0)].set_value(intval)
+ self.set_value(intval)
1
end
@number_callback = ::FFI::Function.new(:int, [:pointer, :string, :size_t ]) do |ctx, stringval, stringlen|
@@ -49,56 +52,48 @@ module FFI_Yajl
s.force_encoding('UTF-8') if defined? Encoding
# XXX: I can't think of a better way to do this right now. need to call to_f if and only if its a float.
v = ( s =~ /\./ ) ? s.to_f : s.to_i
- ctx_mapping[ctx.get_ulong(0)].set_value(v)
+ self.set_value(v)
1
end
@double_callback = ::FFI::Function.new(:int, [:pointer, :double]) do |ctx, doubleval|
- ctx_mapping[ctx.get_ulong(0)].set_value(doubleval)
+ self.set_value(doubleval)
1
end
@string_callback = ::FFI::Function.new(:int, [:pointer, :string, :size_t]) do |ctx, stringval, stringlen|
s = stringval.slice(0,stringlen)
s.force_encoding('UTF-8') if defined? Encoding
- ctx_mapping[ctx.get_ulong(0)].set_value(s)
+ self.set_value(s)
1
end
@start_map_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
- state = ctx_mapping[ctx.get_ulong(0)]
- state.save_key
- state.stack.push(Hash.new)
+ self.save_key
+ self.stack.push(Hash.new)
1
end
@map_key_callback = ::FFI::Function.new(:int, [:pointer, :string, :size_t]) do |ctx, key, keylen|
- ctx_mapping[ctx.get_ulong(0)].key = key.slice(0,keylen)
+ self.key = key.slice(0,keylen)
1
end
@end_map_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
- state = ctx_mapping[ctx.get_ulong(0)]
- state.restore_key
- state.set_value( state.stack.pop ) if state.stack.length > 1
+ self.restore_key
+ self.set_value( self.stack.pop ) if self.stack.length > 1
1
end
@start_array_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
- state = ctx_mapping[ctx.get_ulong(0)]
- state.save_key
- state.stack.push(Array.new)
+ self.save_key
+ self.stack.push(Array.new)
1
end
@end_array_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
- state = ctx_mapping[ctx.get_ulong(0)]
- state.restore_key
- ctx_mapping[ctx.get_ulong(0)].set_value( ctx_mapping[ctx.get_ulong(0)].stack.pop ) if ctx_mapping[ctx.get_ulong(0)].stack.length > 1
+ self.restore_key
+ self.set_value( self.stack.pop ) if self.stack.length > 1
1
end
end
+
def do_yajl_parse(str, opts = {})
- @ctx_mapping ||= Hash.new
setup_callbacks
- rb_ctx = ::FFI_Yajl::FFI::Parser::State.new()
- @ctx_mapping[rb_ctx.object_id] = rb_ctx
- ctx = ::FFI::MemoryPointer.new(:long)
- ctx.write_long( rb_ctx.object_id )
callback_ptr = ::FFI::MemoryPointer.new(::FFI_Yajl::YajlCallbacks)
callbacks = ::FFI_Yajl::YajlCallbacks.new(callback_ptr)
callbacks[:yajl_null] = @null_callback
@@ -112,7 +107,7 @@ module FFI_Yajl
callbacks[:yajl_end_map] = @end_map_callback
callbacks[:yajl_start_array] = @start_array_callback
callbacks[:yajl_end_array] = @end_array_callback
- yajl_handle = ::FFI_Yajl.yajl_alloc(callback_ptr, nil, ctx)
+ yajl_handle = ::FFI_Yajl.yajl_alloc(callback_ptr, nil, nil)
if ( stat = ::FFI_Yajl.yajl_parse(yajl_handle, str, str.bytesize) != :yajl_status_ok )
# FIXME: dup the error and call yajl_free_error?
error = ::FFI_Yajl.yajl_get_error(yajl_handle, 1, str, str.length)
@@ -123,10 +118,9 @@ module FFI_Yajl
error = ::FFI_Yajl.yajl_get_error(yajl_handle, 1, str, str.length)
raise ::FFI_Yajl::ParseError.new(error)
end
- rb_ctx.stack.pop
+ stack.pop
ensure
::FFI_Yajl.yajl_free(yajl_handle) if yajl_handle
- @ctx_mapping.delete(rb_ctx.object_id) if rb_ctx && rb_ctx.object_id
end
end
end