summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--ext/ffi_yajl/ext/encoder/encoder.c42
-rw-r--r--lib/ffi_yajl.rb33
-rw-r--r--lib/ffi_yajl/ffi/encoder.rb20
4 files changed, 81 insertions, 18 deletions
diff --git a/.gitignore b/.gitignore
index 377c74a..7f04a87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,8 @@
*.gem
*.rake_tasks~
*.rbc
+*.so
+*.bundle
*.swo
*.swp
*/tags
@@ -20,10 +22,10 @@ doc
doc/
erl_crash.dump
lib/bundler/man
+mkmf.log
pkg
rdoc
spec/reports
test/tmp
test/version_tmp
tmp
-mkmf.log
diff --git a/ext/ffi_yajl/ext/encoder/encoder.c b/ext/ffi_yajl/ext/encoder/encoder.c
index 0687f51..ade2199 100644
--- a/ext/ffi_yajl/ext/encoder/encoder.c
+++ b/ext/ffi_yajl/ext/encoder/encoder.c
@@ -10,18 +10,33 @@ typedef struct {
int processing_key;
} ffi_state_t;
-static VALUE mEncoder_encode(VALUE self, VALUE obj) {
+static VALUE mEncoder_do_yajl_encode(VALUE self, VALUE obj, VALUE yajl_gen_opts) {
ID sym_ffi_yajl = rb_intern("ffi_yajl");
+ VALUE sym_yajl_gen_beautify = ID2SYM(rb_intern("yajl_gen_beautify"));
+ VALUE sym_yajl_gen_validate_utf8 = ID2SYM(rb_intern("yajl_gen_validate_utf8"));
+ VALUE sym_yajl_gen_indent_string = ID2SYM(rb_intern("yajl_gen_indent_string"));
yajl_gen yajl_gen;
const unsigned char *buf;
size_t len;
ffi_state_t state;
VALUE ret;
+ VALUE indent_string;
yajl_gen = yajl_gen_alloc(NULL);
- yajl_gen_config(yajl_gen, yajl_gen_beautify, 1);
- yajl_gen_config(yajl_gen, yajl_gen_validate_utf8, 1);
+ if ( rb_hash_aref(yajl_gen_opts, sym_yajl_gen_beautify) == Qtrue ) {
+ yajl_gen_config(yajl_gen, yajl_gen_beautify, 1);
+ }
+ if ( rb_hash_aref(yajl_gen_opts, sym_yajl_gen_validate_utf8) == Qtrue ) {
+ yajl_gen_config(yajl_gen, yajl_gen_validate_utf8, 1);
+ }
+
+ indent_string = rb_hash_aref(yajl_gen_opts, sym_yajl_gen_indent_string);
+ if (indent_string != Qnil) {
+ yajl_gen_config(yajl_gen, yajl_gen_indent_string, RSTRING_PTR(indent_string));
+ } else {
+ yajl_gen_config(yajl_gen, yajl_gen_indent_string, " ");
+ }
state.processing_key = 0;
@@ -97,10 +112,11 @@ static VALUE rb_cFalseClass_ffi_yajl(VALUE self, VALUE yajl_gen, VALUE state) {
}
static VALUE rb_cFixnum_ffi_yajl(VALUE self, VALUE yajl_gen, VALUE state) {
+ ID sym_to_s = rb_intern("to_s");
VALUE str;
if ( ((ffi_state_t *)state)->processing_key ) {
- str = rb_any_to_s(self);
+ str = rb_funcall(self, sym_to_s, 0);
yajl_gen_string((struct yajl_gen_t *) yajl_gen, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str));
} else {
yajl_gen_integer((struct yajl_gen_t *) yajl_gen, NUM2INT(self));
@@ -123,8 +139,20 @@ static VALUE rb_cString_ffi_yajl(VALUE self, VALUE yajl_gen, VALUE state) {
return Qnil;
}
+// FIXME: args is a splat/varargs, does it matter? and what about the block?
+static VALUE rb_cObject_to_json(VALUE self, VALUE args) {
+ // FIXME: need to wrap quotes around this
+ VALUE str;
+ str = rb_any_to_s(self);
+ return str;
+}
+
static VALUE rb_cObject_ffi_yajl(VALUE self, VALUE yajl_gen, VALUE state) {
- rb_raise( rb_eNotImpError, "Object#ffi_yajl not implemented");
+ ID sym_to_json = rb_intern("to_json");
+ VALUE str;
+
+ str = rb_funcall(self, sym_to_json, 1, ((ffi_state_t *)state)->json_opts);
+ yajl_gen_number((struct yajl_gen_t *) yajl_gen, (char *)RSTRING_PTR(str), RSTRING_LEN(str));
return Qnil;
}
@@ -132,7 +160,7 @@ void Init_encoder() {
mFFI_Yajl = rb_define_module("FFI_Yajl");
mExt = rb_define_module_under(mFFI_Yajl, "Ext");
mEncoder = rb_define_module_under(mExt, "Encoder");
- rb_define_method(mEncoder, "encode", mEncoder_encode, 1);
+ rb_define_method(mEncoder, "do_yajl_encode", mEncoder_do_yajl_encode, 2);
rb_define_method(rb_cHash, "ffi_yajl", rb_cHash_ffi_yajl, 2);
rb_define_method(rb_cArray, "ffi_yajl", rb_cArray_ffi_yajl, 2);
@@ -143,6 +171,8 @@ void Init_encoder() {
rb_define_method(rb_cBignum, "ffi_yajl", rb_cBignum_ffi_yajl, 2);
rb_define_method(rb_cFloat, "ffi_yajl", rb_cFloat_ffi_yajl, 2);
rb_define_method(rb_cString, "ffi_yajl", rb_cString_ffi_yajl, 2);
+// FIXME: make this conditional on ActiveSupport not being defined:
+ rb_define_method(rb_cObject, "to_json", rb_cObject_to_json, 1);
rb_define_method(rb_cObject, "ffi_yajl", rb_cObject_ffi_yajl, 2);
}
diff --git a/lib/ffi_yajl.rb b/lib/ffi_yajl.rb
index 1a38079..40c26e4 100644
--- a/lib/ffi_yajl.rb
+++ b/lib/ffi_yajl.rb
@@ -5,6 +5,23 @@ module FFI_Yajl
class Encoder
attr_accessor :opts
+ def encode(obj)
+ # initialization that we can do in pure ruby
+ yajl_gen_opts = {}
+
+ yajl_gen_opts[:yajl_gen_validate_utf8] = true
+ yajl_gen_opts[:yajl_gen_beautify] = false
+ yajl_gen_opts[:yajl_gen_indent_string] = " "
+
+ if opts[:pretty]
+ yajl_gen_opts[:yajl_gen_beautify] = true
+ yajl_gen_opts[:yajl_gen_indent_string] = opts[:indent] ? opts[:indent] : " "
+ end
+
+ # call either the ext or ffi hook
+ do_yajl_encode(obj, yajl_gen_opts)
+ end
+
def self.encode(obj, *args)
new(*args).encode(obj)
end
@@ -13,12 +30,24 @@ module FFI_Yajl
@opts = opts
end
- begin
+ if ENV['FORCE_FFI_YAJL'] == "ext"
require 'ffi_yajl/ext'
include FFI_Yajl::Ext::Encoder
- rescue LoadError
+ elsif ENV['FORCE_FFI_YAJL'] == "ffi"
+ require 'ffi_yajl/ffi'
+ include FFI_Yajl::FFI::Encoder
+ elsif defined?(Yajl)
+ # on Linux yajl-ruby and non-FFI ffi_yajl conflict
require 'ffi_yajl/ffi'
include FFI_Yajl::FFI::Encoder
+ else
+ begin
+ require 'ffi_yajl/ext'
+ include FFI_Yajl::Ext::Encoder
+ rescue LoadError
+ require 'ffi_yajl/ffi'
+ include FFI_Yajl::FFI::Encoder
+ end
end
end
end
diff --git a/lib/ffi_yajl/ffi/encoder.rb b/lib/ffi_yajl/ffi/encoder.rb
index 7798f8d..42725b0 100644
--- a/lib/ffi_yajl/ffi/encoder.rb
+++ b/lib/ffi_yajl/ffi/encoder.rb
@@ -5,17 +5,18 @@ require 'ffi'
module FFI_Yajl
module FFI
module Encoder
- def encode(obj)
+ def do_yajl_encode(obj, yajl_gen_opts = {})
+
yajl_gen = FFI_Yajl.yajl_gen_alloc(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
+ if yajl_gen_opts[:yajl_gen_beautify]
+ FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_beautify, :int, 1)
+ end
+ if yajl_gen_opts[:yajl_gen_validate_utf8]
+ FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_validate_utf8, :int, 1)
+ end
+ indent = yajl_gen_opts[:yajl_gen_indent_string] || " "
FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_indent_string, :string, indent)
# setup our own state
@@ -97,7 +98,8 @@ end
class Bignum
def ffi_yajl(yajl_gen, state)
- raise NotImpelementedError
+ str = self.to_s
+ FFI_Yajl.yajl_gen_number(yajl_gen, str, str.length)
end
end