diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2013-11-18 15:18:19 -0800 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2013-11-18 15:18:19 -0800 |
commit | 5ebcb3c42654f50db90127cfbfc4a4ea0a5ec039 (patch) | |
tree | bedc0164dd2a05d8b41d5058b188755c7c90d65b | |
parent | 1a872d2dbd17b3ce7c95f5d010ac31b0c026abac (diff) | |
download | ffi-yajl-5ebcb3c42654f50db90127cfbfc4a4ea0a5ec039.tar.gz |
moving things around to support ext encoding
-rw-r--r-- | ext/encoder/encoder.c | 6 | ||||
-rw-r--r-- | ext/encoder/extconf.rb | 16 | ||||
-rw-r--r-- | ext/libyajl2/extconf.rb | 3 | ||||
-rw-r--r-- | ffi-yajl.gemspec | 2 | ||||
-rw-r--r-- | lib/ffi_yajl.rb | 48 | ||||
-rw-r--r-- | lib/ffi_yajl/encoder.rb | 7 | ||||
-rw-r--r-- | lib/ffi_yajl/ext.rb | 1 | ||||
-rw-r--r-- | lib/ffi_yajl/ffi.rb | 1 | ||||
-rw-r--r-- | lib/ffi_yajl/ffi/encoder.rb (renamed from lib/ffi_yajl/encoder/ffi.rb) | 101 |
9 files changed, 114 insertions, 71 deletions
diff --git a/ext/encoder/encoder.c b/ext/encoder/encoder.c new file mode 100644 index 0000000..d664647 --- /dev/null +++ b/ext/encoder/encoder.c @@ -0,0 +1,6 @@ + +void Init_encoder() { + mJSON_Yajl = rb_define_module("JSON_Yajl"); + mEncoder +} + diff --git a/ext/encoder/extconf.rb b/ext/encoder/extconf.rb new file mode 100644 index 0000000..bc3013b --- /dev/null +++ b/ext/encoder/extconf.rb @@ -0,0 +1,16 @@ +require 'mkmf' + +# the customer is always right, ruby is always compiled to be stupid +$CFLAGS = ENV['CFLAGS'] if ENV['CFLAGS'] +$LDFLAGS = ENV['LDFLAGS'] if ENV['LDFLAGS'] +RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC'] + +# except if you're doing an unoptimized gcc install we're going to help you out a bit +if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc|clang/ + $CFLAGS << " -O3" unless $CFLAGS[/-O\d/] + # how many people realize that -Wall is a compiler-specific flag??? + # apparently not many based on reading lots of shitty extconf.rb's out there + $CFLAGS << " -Wall" +end + +create_makefile 'encoder' diff --git a/ext/libyajl2/extconf.rb b/ext/libyajl2/extconf.rb index 48c3207..e8fa60f 100644 --- a/ext/libyajl2/extconf.rb +++ b/ext/libyajl2/extconf.rb @@ -13,6 +13,9 @@ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx' # except if you're doing an unoptimized gcc install we're going to help you out a bit if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc|clang/ $CFLAGS << " -O3" unless $CFLAGS[/-O\d/] + # how many people realize that -Wall is a compiler-specific flag??? + # apparently not many based on reading lots of shitty extconf.rb's out there + $CFLAGS << " -Wall" end # yajl_complete_parse is only in >= 2.0 diff --git a/ffi-yajl.gemspec b/ffi-yajl.gemspec index cc5240c..652505e 100644 --- a/ffi-yajl.gemspec +++ b/ffi-yajl.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |s| s.email = "lamont@scriptkiddie.org" s.homepage = "http://github.com/lamont-granquist/ffi-yajl" - s.extensions = %w(ext/libyajl2/extconf.rb) + s.extensions = %w(ext/libyajl2/extconf.rb ext/encoder/extconf.rb) s.add_development_dependency "rake" s.add_development_dependency "rspec", "~> 2.14" diff --git a/lib/ffi_yajl.rb b/lib/ffi_yajl.rb index d6fadc0..a6f5aa4 100644 --- a/lib/ffi_yajl.rb +++ b/lib/ffi_yajl.rb @@ -1,12 +1,26 @@ require 'rubygems' require 'ffi' -require 'ffi_yajl/encoder' +begin + require 'ffi_yajl/ext' + module FFI_Yajl + class Encoder + include FFI_Yajl::Ext::Encoder + end + end +rescue LoadError + require 'ffi_yajl/ffi' + module FFI_Yajl + class Encoder + include FFI_Yajl::FFI::Encoder + end + end +end module FFI_Yajl - extend FFI::Library + extend ::FFI::Library - libname = FFI.map_library_name("yajl") + libname = ::FFI.map_library_name("yajl") libpath = File.join(File.dirname(__FILE__), libname) if File.file?(libpath) @@ -16,7 +30,7 @@ module FFI_Yajl ffi_lib 'yajl' end - class YajlCallbacks < FFI::Struct + class YajlCallbacks < ::FFI::Struct layout :yajl_null, :pointer, :yajl_boolean, :pointer, :yajl_integer, :pointer, @@ -144,53 +158,53 @@ module FFI_Yajl end end - NullCallback = FFI::Function.new(:int, [:pointer]) do |ctx| + NullCallback = ::FFI::Function.new(:int, [:pointer]) do |ctx| @@CTX_MAPPING[ctx.get_ulong(0)].set_value(nil) 1 end - BooleanCallback = FFI::Function.new(:int, [:pointer, :int]) do |ctx, boolval| + BooleanCallback = ::FFI::Function.new(:int, [:pointer, :int]) do |ctx, boolval| @@CTX_MAPPING[ctx.get_ulong(0)].set_value(boolval == 1 ? true : false) 1 end - IntegerCallback = FFI::Function.new(:int, [:pointer, :long_long]) do |ctx, intval| + IntegerCallback = ::FFI::Function.new(:int, [:pointer, :long_long]) do |ctx, intval| @@CTX_MAPPING[ctx.get_ulong(0)].set_value(intval) 1 end - DoubleCallback = FFI::Function.new(:int, [:pointer, :double]) do |ctx, doubleval| + DoubleCallback = ::FFI::Function.new(:int, [:pointer, :double]) do |ctx, doubleval| @@CTX_MAPPING[ctx.get_ulong(0)].set_value(doubleval) 1 end - NumberCallback = FFI::Function.new(:int, [:pointer, :pointer, :size_t]) do |ctx, numberval, numberlen| + NumberCallback = ::FFI::Function.new(:int, [:pointer, :pointer, :size_t]) do |ctx, numberval, numberlen| raise "NumberCallback: not implemented" 1 end - StringCallback = FFI::Function.new(:int, [:pointer, :string, :size_t]) do |ctx, stringval, stringlen| + StringCallback = ::FFI::Function.new(:int, [:pointer, :string, :size_t]) do |ctx, stringval, stringlen| @@CTX_MAPPING[ctx.get_ulong(0)].set_value(stringval.slice(0,stringlen)) 1 end - StartMapCallback = FFI::Function.new(:int, [:pointer]) do |ctx| + StartMapCallback = ::FFI::Function.new(:int, [:pointer]) do |ctx| state = @@CTX_MAPPING[ctx.get_ulong(0)] state.save_key state.stack.push(Hash.new) 1 end - MapKeyCallback = FFI::Function.new(:int, [:pointer, :string, :size_t]) do |ctx, key, keylen| + MapKeyCallback = ::FFI::Function.new(:int, [:pointer, :string, :size_t]) do |ctx, key, keylen| @@CTX_MAPPING[ctx.get_ulong(0)].key = key.slice(0,keylen) 1 end - EndMapCallback = FFI::Function.new(:int, [:pointer]) do |ctx| + EndMapCallback = ::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 1 end - StartArrayCallback = FFI::Function.new(:int, [:pointer]) do |ctx| + StartArrayCallback = ::FFI::Function.new(:int, [:pointer]) do |ctx| state = @@CTX_MAPPING[ctx.get_ulong(0)] state.save_key state.stack.push(Array.new) 1 end - EndArrayCallback = FFI::Function.new(:int, [:pointer]) do |ctx| + EndArrayCallback = ::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 @@ -201,9 +215,9 @@ module FFI_Yajl @@CTX_MAPPING ||= Hash.new rb_ctx = FFI_Yajl::Parser::State.new() @@CTX_MAPPING[rb_ctx.object_id] = rb_ctx - ctx = FFI::MemoryPointer.new(:long) + ctx = ::FFI::MemoryPointer.new(:long) ctx.write_long( rb_ctx.object_id ) - callback_ptr = FFI::MemoryPointer.new(FFI_Yajl::YajlCallbacks) + callback_ptr = ::FFI::MemoryPointer.new(FFI_Yajl::YajlCallbacks) callbacks = FFI_Yajl::YajlCallbacks.new(callback_ptr) callbacks[:yajl_null] = NullCallback callbacks[:yajl_boolean] = BooleanCallback diff --git a/lib/ffi_yajl/encoder.rb b/lib/ffi_yajl/encoder.rb deleted file mode 100644 index 897a045..0000000 --- a/lib/ffi_yajl/encoder.rb +++ /dev/null @@ -1,7 +0,0 @@ - -begin - require 'ffi_yajl/encoder/ext' -rescue LoadError - require 'ffi_yajl/encoder/ffi' -end - diff --git a/lib/ffi_yajl/ext.rb b/lib/ffi_yajl/ext.rb new file mode 100644 index 0000000..ee78b46 --- /dev/null +++ b/lib/ffi_yajl/ext.rb @@ -0,0 +1 @@ +require 'ffi_yajl/ext/encoder' diff --git a/lib/ffi_yajl/ffi.rb b/lib/ffi_yajl/ffi.rb new file mode 100644 index 0000000..0581d4a --- /dev/null +++ b/lib/ffi_yajl/ffi.rb @@ -0,0 +1 @@ +require 'ffi_yajl/ffi/encoder' diff --git a/lib/ffi_yajl/encoder/ffi.rb b/lib/ffi_yajl/ffi/encoder.rb index 2e79577..178d4db 100644 --- a/lib/ffi_yajl/encoder/ffi.rb +++ b/lib/ffi_yajl/ffi/encoder.rb @@ -1,55 +1,64 @@ -module FFI_Yajl - class Encoder - attr_accessor :opts - - def self.encode(obj, *args) - new(*args).encode(obj) - end - - def initialize(opts = {}) - @opts = opts - end +require 'ffi' +# FIXME: should require the lower level ffi stuff here instead of having this included higher up - def encode(obj) - yajl_gen = FFI_Yajl.yajl_gen_alloc(nil, nil) - - # configure the yajl encoder - FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_beautify, :int, 1) if opts[:pretty] - FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_validate_utf8, :int, 1) - indent = if opts[:pretty] - opts[:indent] ? opts[:indent] : " " - else - " " - end - FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_indent_string, :string, indent) - - # setup our own state - state = { - :json_opts => opts, - :processing_key => false, - } - - # do the encoding - obj.ffi_yajl(yajl_gen, state) - - # get back our encoded JSON - string_ptr = FFI::MemoryPointer.new(:string) - length_ptr = FFI::MemoryPointer.new(:int) - FFI_Yajl.yajl_gen_get_buf(yajl_gen, string_ptr, length_ptr) - length = length_ptr.read_int - string = string_ptr.get_pointer(0).read_string - - return string - ensure - # free up the yajl encoder - FFI_Yajl.yajl_gen_free(yajl_gen) +module FFI_Yajl + module FFI + module Encoder + module ClassMethods + def encode(obj, *args) + new(*args).encode(obj) + end + end + + def self.included(base) + base.extend ClassMethods + end + + attr_accessor :opts + + def initialize(opts = {}) + @opts = opts + end + + def encode(obj) + yajl_gen = FFI_Yajl.yajl_gen_alloc(nil, nil) + + # configure the yajl encoder + FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_beautify, :int, 1) if opts[:pretty] + FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_validate_utf8, :int, 1) + indent = if opts[:pretty] + opts[:indent] ? opts[:indent] : " " + else + " " + end + FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_indent_string, :string, indent) + + # setup our own state + state = { + :json_opts => opts, + :processing_key => false, + } + + # do the encoding + obj.ffi_yajl(yajl_gen, state) + + # get back our encoded JSON + string_ptr = ::FFI::MemoryPointer.new(:string) + length_ptr = ::FFI::MemoryPointer.new(:int) + FFI_Yajl.yajl_gen_get_buf(yajl_gen, string_ptr, length_ptr) + length = length_ptr.read_int + string = string_ptr.get_pointer(0).read_string + + return string + ensure + # free up the yajl encoder + FFI_Yajl.yajl_gen_free(yajl_gen) + end end end - end - class Hash def ffi_yajl(yajl_gen, state) FFI_Yajl.yajl_gen_map_open(yajl_gen) |