diff options
author | skeshari12 <skeshari@msystechnologies.com> | 2022-04-12 17:33:05 +0530 |
---|---|---|
committer | skeshari12 <skeshari@msystechnologies.com> | 2022-04-12 17:33:05 +0530 |
commit | 96dedf57cf2f92049a5884896fd2447396d0bec9 (patch) | |
tree | 4d8ba4295439e341fd4ec380bc5bf0e32db8b071 | |
parent | 0f05b88d19bf180499d4401c41918ff4a87b4d67 (diff) | |
download | ffi-yajl-96dedf57cf2f92049a5884896fd2447396d0bec9.tar.gz |
fix error
Signed-off-by: skeshari12 <skeshari@msystechnologies.com>
-rw-r--r-- | ext/dlopen/dlopen.c | 40 | ||||
-rw-r--r-- | ext/dlopen/extconf.rb | 16 | ||||
-rw-r--r-- | ext/encoder/encoder.c | 394 | ||||
-rw-r--r-- | ext/encoder/extconf.rb | 65 | ||||
-rw-r--r-- | ext/parser/extconf.rb | 65 | ||||
-rw-r--r-- | ext/parser/parser.c | 240 | ||||
-rw-r--r-- | spec/ffi_yajl/encoder_spec.rb | 1 | ||||
-rw-r--r-- | spec/ffi_yajl/map_library_name_spec.rb | 1 | ||||
-rw-r--r-- | spec/ffi_yajl/parser_spec.rb | 1 |
9 files changed, 3 insertions, 820 deletions
diff --git a/ext/dlopen/dlopen.c b/ext/dlopen/dlopen.c deleted file mode 100644 index eb81a21..0000000 --- a/ext/dlopen/dlopen.c +++ /dev/null @@ -1,40 +0,0 @@ -#include <ruby.h> - -#if defined(HAVE_DLFCN_H) -# include <dlfcn.h> -#ifndef RTLD_LAZY -#define RTLD_LAZY 0 -#endif -#ifndef RTLD_GLOBAL -#define RTLD_GLOBAL 0 -#endif -#ifndef RTLD_NOW -#define RTLD_NOW 0 -#endif -#else -# if defined(_WIN32) -# include <windows.h> -# define dlopen(name,flag) ((void*)LoadLibrary(name)) -# define dlerror() strerror(rb_w32_map_errno(GetLastError())) -# define dlsym(handle,name) ((void*)GetProcAddress((handle),(name))) -# define RTLD_LAZY -1 -# define RTLD_NOW -1 -# define RTLD_GLOBAL -1 -# endif -#endif - -static VALUE mFFI_Yajl, mDlopen, mExt; - -static VALUE mDlopen_dlopen(VALUE self, VALUE file) { - if (dlopen(RSTRING_PTR(file), RTLD_NOW|RTLD_GLOBAL) == NULL) { - rb_raise(rb_eArgError, "%s", dlerror()); - } - return Qnil; -} - -void Init_dlopen() { - mFFI_Yajl = rb_define_module("FFI_Yajl"); - mExt = rb_define_module_under(mFFI_Yajl, "Ext"); - mDlopen = rb_define_module_under(mExt, "Dlopen"); - rb_define_method(mDlopen, "dlopen", mDlopen_dlopen, 1); -} diff --git a/ext/dlopen/extconf.rb b/ext/dlopen/extconf.rb deleted file mode 100644 index 803d326..0000000 --- a/ext/dlopen/extconf.rb +++ /dev/null @@ -1,16 +0,0 @@ -# rubocop:disable Style/GlobalVars -require "mkmf" -require "rubygems" - -RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"] if ENV["CC"] - -puts $CFLAGS -puts $LDFLAGS - -have_header("dlfcn.h") - -have_library("dl", "dlopen") - -dir_config "dlopen" - -create_makefile "ffi_yajl/ext/dlopen" diff --git a/ext/encoder/encoder.c b/ext/encoder/encoder.c deleted file mode 100644 index 6f1492c..0000000 --- a/ext/encoder/encoder.c +++ /dev/null @@ -1,394 +0,0 @@ -#include <ruby.h> -#include <yajl/yajl_gen.h> - -static VALUE mFFI_Yajl, mExt, mEncoder, mEncoder2, cEncodeError; -static VALUE cDate, cTime, cDateTime, cStringIO; -static VALUE cYajl_Gen; - -/* FIXME: the json gem does a whole bunch of indirection around monkeypatching... not sure if we need to as well... */ - -static VALUE mEncoder_do_yajl_encode(VALUE self, VALUE obj, VALUE yajl_gen_opts, VALUE json_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; - VALUE state; - VALUE ret; - VALUE indent_string; - VALUE rb_yajl_gen; - - yajl_gen = yajl_gen_alloc(NULL); - - 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 = rb_hash_new(); - - rb_hash_aset(state, rb_str_new2("processing_key"), Qfalse); - - rb_hash_aset(state, rb_str_new2("json_opts"), json_opts); - - rb_yajl_gen = Data_Wrap_Struct(cYajl_Gen, NULL, NULL, yajl_gen); - - rb_funcall(obj, sym_ffi_yajl, 2, rb_yajl_gen, state); - - yajl_gen_get_buf(yajl_gen, &buf, &len); - - ret = rb_str_new2((char *)buf); - - yajl_gen_free(yajl_gen); - - return ret; -} - -int rb_cHash_ffi_yajl_callback(VALUE key, VALUE val, VALUE extra) { - ID sym_ffi_yajl = rb_intern("ffi_yajl"); - VALUE state = rb_hash_aref(extra, rb_str_new2("state")); - VALUE rb_yajl_gen = rb_hash_aref(extra, rb_str_new2("yajl_gen")); - - rb_hash_aset(state, rb_str_new2("processing_key"), Qtrue); - rb_funcall(key, sym_ffi_yajl, 2, rb_yajl_gen, state); - rb_hash_aset(state, rb_str_new2("processing_key"), Qfalse); - - rb_funcall(val, sym_ffi_yajl, 2, rb_yajl_gen, state); - - return 0; -} - -#define RB_FUNC0(call) rb_funcall(self, rb_intern(call), 0) - -/* - * wrappers around yajl_gen_* functions - */ - -/* encode a c-string as a yajl string */ -VALUE gen_cstring(VALUE rb_yajl_gen, char *cptr, int len) { - yajl_gen_status status; - struct yajl_gen_t *yajl_gen; - Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - - if ((status = yajl_gen_string(yajl_gen, (unsigned char *)cptr, len)) != yajl_gen_status_ok) { - rb_funcall(mEncoder2, rb_intern("raise_error_for_status"), 2, INT2FIX(status), rb_str_new(cptr, len)); - } - - return Qnil; -} - -/* encode a ruby-sring as a yajl string */ -VALUE gen_string(VALUE rb_yajl_gen, VALUE str) { - char *cptr = RSTRING_PTR(str); - int len = RSTRING_LEN(str); - - return gen_cstring(rb_yajl_gen, cptr, len); -} - -/* calls #to_s on an object to encode it as a yajl string */ -static VALUE gen_string_to_s(VALUE rb_yajl_gen, VALUE self) { - return gen_string(rb_yajl_gen, RB_FUNC0("to_s")); -} - -/* encode a ruby string as a yajl number (also used to embed already-rendered json from #to_json) */ -VALUE gen_number(VALUE rb_yajl_gen, VALUE str) { - yajl_gen_status status; - struct yajl_gen_t *yajl_gen; - Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - char *cptr = RSTRING_PTR(str); - int len = RSTRING_LEN(str); - - if ((status = yajl_gen_number(yajl_gen, cptr, len)) != yajl_gen_status_ok) { - rb_funcall(mEncoder2, rb_intern("raise_error_for_status"), 2, INT2FIX(status), str); - } - - return Qnil; -} - -/* encode hash open */ -VALUE gen_map_open(VALUE rb_yajl_gen) { - yajl_gen_status status; - struct yajl_gen_t *yajl_gen; - Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - - if ((status = yajl_gen_map_open(yajl_gen)) != yajl_gen_status_ok) { - rb_funcall(mEncoder2, rb_intern("raise_error_for_status"), 2, INT2FIX(status), rb_str_new2("{")); - } - - return Qnil; -} - -/* encode a hash close */ -VALUE gen_map_close(VALUE rb_yajl_gen) { - yajl_gen_status status; - struct yajl_gen_t *yajl_gen; - Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - - if ((status = yajl_gen_map_close(yajl_gen)) != yajl_gen_status_ok) { - rb_funcall(mEncoder2, rb_intern("raise_error_for_status"), 2, INT2FIX(status), rb_str_new2("}")); - } - - return Qnil; -} - -/* encode an array open */ -VALUE gen_array_open(VALUE rb_yajl_gen) { - yajl_gen_status status; - struct yajl_gen_t *yajl_gen; - Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - - if ((status = yajl_gen_array_open(yajl_gen)) != yajl_gen_status_ok) { - rb_funcall(mEncoder2, rb_intern("raise_error_for_status"), 2, INT2FIX(status), rb_str_new2("[")); - } - - return Qnil; -} - -/* encode an array close */ -VALUE gen_array_close(VALUE rb_yajl_gen) { - yajl_gen_status status; - struct yajl_gen_t *yajl_gen; - Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - - if ((status = yajl_gen_array_close(yajl_gen)) != yajl_gen_status_ok) { - rb_funcall(mEncoder2, rb_intern("raise_error_for_status"), 2, INT2FIX(status), rb_str_new2("]")); - } - - return Qnil; -} - -/* encode a json null */ -VALUE gen_null(VALUE rb_yajl_gen) { - yajl_gen_status status; - struct yajl_gen_t *yajl_gen; - Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - - if ((status = yajl_gen_null(yajl_gen)) != yajl_gen_status_ok) { - rb_funcall(mEncoder2, rb_intern("raise_error_for_status"), 2, INT2FIX(status), rb_str_new2("null")); - } - - return Qnil; -} - -/* encode a true value */ -VALUE gen_true(VALUE rb_yajl_gen) { - yajl_gen_status status; - struct yajl_gen_t *yajl_gen; - Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - - if ((status = yajl_gen_bool(yajl_gen, 1)) != yajl_gen_status_ok) { - rb_funcall(mEncoder2, rb_intern("raise_error_for_status"), 2, INT2FIX(status), rb_str_new2("true")); - } - - return Qnil; -} - -/* encode a false value */ -VALUE gen_false(VALUE rb_yajl_gen) { - yajl_gen_status status; - struct yajl_gen_t *yajl_gen; - Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - - if ((status = yajl_gen_bool(yajl_gen, 0)) != yajl_gen_status_ok) { - rb_funcall(mEncoder2, rb_intern("raise_error_for_status"), 2, INT2FIX(status), rb_str_new2("false")); - } - - return Qnil; -} - -/* - * <Object>#to_ffi_yajl() method calls - */ - -static VALUE rb_cHash_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - if ( rb_hash_aref(state, rb_str_new2("processing_key")) == Qtrue ) { - gen_string(rb_yajl_gen, rb_funcall(self, rb_intern("to_s"), 0)); - } else { - - /* FIXME: i think this got refactored from something else and it is now pointless -- - should just pass rb_yajl_gen directly instead of this 'extra' hash -- i don't - *think* this indirection is doing anything useful to mark memory against the GC */ - - VALUE extra = rb_hash_new(); - - rb_hash_aset(extra, rb_str_new2("yajl_gen"), rb_yajl_gen); - - rb_hash_aset(extra, rb_str_new2("state"), state); - - gen_map_open(rb_yajl_gen); - - rb_hash_foreach(self, rb_cHash_ffi_yajl_callback, extra); - - gen_map_close(rb_yajl_gen); - } - - return Qnil; -} - -static VALUE rb_cArray_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - if ( rb_hash_aref(state, rb_str_new2("processing_key")) == Qtrue ) { - gen_string(rb_yajl_gen, rb_funcall(self, rb_intern("to_s"), 0)); - } else { - VALUE val; - long i; - ID sym_ffi_yajl = rb_intern("ffi_yajl"); - - gen_array_open(rb_yajl_gen); - - for(i=0; i<RARRAY_LEN(self); i++) { - val = rb_ary_entry(self, i); - rb_funcall(val, sym_ffi_yajl, 2, rb_yajl_gen, state); - } - - gen_array_close(rb_yajl_gen); - } - - return Qnil; -} - -static VALUE rb_cNilClass_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - if ( rb_hash_aref(state, rb_str_new2("processing_key")) == Qtrue ) { - gen_cstring(rb_yajl_gen, "", sizeof("")-1); - } else { - gen_null(rb_yajl_gen); - } - - return Qnil; -} - -static VALUE rb_cTrueClass_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - if ( rb_hash_aref(state, rb_str_new2("processing_key")) == Qtrue ) { - gen_cstring(rb_yajl_gen, "true", sizeof("true")-1); - } else { - gen_true(rb_yajl_gen); - } - - return Qnil; -} - -static VALUE rb_cFalseClass_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - if ( rb_hash_aref(state, rb_str_new2("processing_key")) == Qtrue ) { - gen_cstring(rb_yajl_gen, "false", sizeof("false")-1); - } else { - gen_false(rb_yajl_gen); - } - - return Qnil; -} - -static VALUE rb_cFixnum_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - VALUE str = rb_funcall(self, rb_intern("to_s"), 0); - char *cptr = RSTRING_PTR(str); - - if (memcmp(cptr, "NaN", sizeof("NaN")) == 0 || memcmp(cptr, "Infinity", sizeof("Infinity")) == 0 || memcmp(cptr, "-Infinity", sizeof("-Infinity")) == 0) { - rb_raise(cEncodeError, "'%s' is an invalid number", cptr); - } - - if ( rb_hash_aref(state, rb_str_new2("processing_key")) == Qtrue ) { - gen_string(rb_yajl_gen, str); - } else { - gen_number(rb_yajl_gen, str); - } - - return Qnil; -} - -static VALUE rb_cBignum_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - return rb_cFixnum_ffi_yajl(self, rb_yajl_gen, state); -} - -static VALUE rb_cFloat_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - return rb_cFixnum_ffi_yajl(self, rb_yajl_gen, state); -} - -static VALUE rb_cString_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - return gen_string(rb_yajl_gen, self); -} - -static VALUE rb_cSymbol_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - return gen_string_to_s(rb_yajl_gen, self); -} - -static VALUE rb_cDate_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - return gen_string_to_s(rb_yajl_gen, self); -} - -static VALUE rb_cTime_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - ID sym_strftime = rb_intern("strftime"); - VALUE str = rb_funcall(self, sym_strftime, 1, rb_str_new2("%Y-%m-%d %H:%M:%S %z")); - - return gen_string(rb_yajl_gen, str); -} - -static VALUE rb_cStringIO_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - return gen_string(rb_yajl_gen, RB_FUNC0("read")); -} - -static VALUE rb_cDateTime_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - return gen_string_to_s(rb_yajl_gen, self); -} - -static VALUE rb_cObject_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { - ID sym_to_json = rb_intern("to_json"); - if ( rb_hash_aref(state, rb_str_new2("processing_key")) != Qtrue && rb_respond_to(self, sym_to_json) ) { - VALUE json_opts = rb_hash_aref(state, rb_str_new2("json_opts")); - VALUE str = rb_funcall(self, sym_to_json, 1, json_opts); - - gen_number(rb_yajl_gen, str); - } else { - gen_string_to_s(rb_yajl_gen, self); - } - - return Qnil; -} - -void Init_encoder() { - mFFI_Yajl = rb_define_module("FFI_Yajl"); - mEncoder2 = rb_define_class_under(mFFI_Yajl, "Encoder", rb_cObject); - cEncodeError = rb_define_class_under(mFFI_Yajl, "EncodeError", rb_eStandardError); - mExt = rb_define_module_under(mFFI_Yajl, "Ext"); - mEncoder = rb_define_module_under(mExt, "Encoder"); - cYajl_Gen = rb_define_class_under(mEncoder, "YajlGen", rb_cObject); - rb_define_method(mEncoder, "do_yajl_encode", mEncoder_do_yajl_encode, 3); - - /* use rb_const_get instead of rb_define_class so that we don't get superclass mismatches */ - ID sym_Date = rb_intern("Date"); - cDate = rb_const_get(rb_cObject, sym_Date); - ID sym_Time = rb_intern("Time"); - cTime = rb_const_get(rb_cObject, sym_Time); - ID sym_DateTime = rb_intern("DateTime"); - cDateTime = rb_const_get(rb_cObject, sym_DateTime); - ID sym_StringIO = rb_intern("StringIO"); - cStringIO = rb_const_get(rb_cObject, sym_StringIO); - - rb_define_method(rb_cHash, "ffi_yajl", rb_cHash_ffi_yajl, 2); - rb_define_method(rb_cArray, "ffi_yajl", rb_cArray_ffi_yajl, 2); - rb_define_method(rb_cNilClass, "ffi_yajl", rb_cNilClass_ffi_yajl, 2); - rb_define_method(rb_cTrueClass, "ffi_yajl", rb_cTrueClass_ffi_yajl, 2); - rb_define_method(rb_cFalseClass, "ffi_yajl", rb_cFalseClass_ffi_yajl, 2); -#ifdef rb_cFixnum /* ruby < 2.4 */ - rb_define_method(rb_cFixnum, "ffi_yajl", rb_cFixnum_ffi_yajl, 2); - rb_define_method(rb_cBignum, "ffi_yajl", rb_cBignum_ffi_yajl, 2); -#else - rb_define_method(rb_cInteger, "ffi_yajl", rb_cFixnum_ffi_yajl, 2); -#endif - rb_define_method(rb_cFloat, "ffi_yajl", rb_cFloat_ffi_yajl, 2); - rb_define_method(rb_cString, "ffi_yajl", rb_cString_ffi_yajl, 2); - rb_define_method(rb_cSymbol, "ffi_yajl", rb_cSymbol_ffi_yajl, 2); - rb_define_method(cDate, "ffi_yajl", rb_cDate_ffi_yajl, 2); - rb_define_method(cTime, "ffi_yajl", rb_cTime_ffi_yajl, 2); - rb_define_method(cDateTime, "ffi_yajl", rb_cDateTime_ffi_yajl, 2); - rb_define_method(cStringIO, "ffi_yajl", rb_cStringIO_ffi_yajl, 2); - rb_define_method(rb_cObject, "ffi_yajl", rb_cObject_ffi_yajl, 2); -} diff --git a/ext/encoder/extconf.rb b/ext/encoder/extconf.rb deleted file mode 100644 index 8f7d14b..0000000 --- a/ext/encoder/extconf.rb +++ /dev/null @@ -1,65 +0,0 @@ -# rubocop:disable Style/GlobalVars -require "mkmf" -require "rubygems" -require "libyajl2" - -RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"] if ENV["CC"] - -# pick up the vendored libyajl2 out of the libyajl2 gem -$CFLAGS = " -I#{Libyajl2.include_path} #{$CFLAGS}" -$LDFLAGS = " -L#{Libyajl2.opt_path} #{$LDFLAGS}" - -# remove "-Wl,--no-undefined" flag if existent to allow for loading with dlopen -$LDFLAGS.slice!("-Wl,--no-undefined") - -puts $CFLAGS -puts $LDFLAGS - -# 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 - -def windows? - !!(RUBY_PLATFORM =~ /mswin|mingw|cygwin|windows/) -end - -if windows? - # include our libyajldll.a definitions on windows in the libyajl2 gem - $libs = "#{$libs} -lyajldll" -end - -# NOTE: find_library has the side effect of adding -lyajl to the flags which we are deliberately -# avoiding doing with the libyajl2-gem (allowing it to be lazily loaded with dlopen) -if !windows? && !find_header("yajl/yajl_tree.h") - puts "libyajl2 headers not found in libyajl2-gem, searching for system libraries..." - - HEADER_DIRS = [ - "/opt/local/include", # MacPorts - "/usr/local/include", # /usr/local - RbConfig::CONFIG["includedir"], # Ruby - "/usr/include", # (default) - ].freeze - - LIB_DIRS = [ - "/opt/local/lib", # MacPorts - "/usr/local/lib", # /usr/local + Homebrew - RbConfig::CONFIG["libdir"], # Ruby - "/usr/lib", # (default) - ].freeze - - # add --with-yajl-dir, --with-yajl-include, --with-yajl-lib - dir_config("yajl", HEADER_DIRS, LIB_DIRS) - - # here we use find_library in order to deliberately link with -lyajl as a useful side-effect - unless find_header("yajl/yajl_tree.h") && find_library("yajl", "yajl_complete_parse") - abort "libyajl2 is missing. please install libyajl2" - end -end - -dir_config "encoder" - -create_makefile "ffi_yajl/ext/encoder" diff --git a/ext/parser/extconf.rb b/ext/parser/extconf.rb deleted file mode 100644 index 5611934..0000000 --- a/ext/parser/extconf.rb +++ /dev/null @@ -1,65 +0,0 @@ -# rubocop:disable Style/GlobalVars -require "mkmf" -require "rubygems" -require "libyajl2" - -RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"] if ENV["CC"] - -# pick up the vendored libyajl2 out of the libyajl2 gem -$CFLAGS = "-I#{Libyajl2.include_path} #{$CFLAGS}" -$LDFLAGS = "-L#{Libyajl2.opt_path} #{$LDFLAGS}" - -# remove "-Wl,--no-undefined" flag if existent to allow for loading with dlopen -$LDFLAGS.slice!("-Wl,--no-undefined") - -puts $CFLAGS -puts $LDFLAGS - -# 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 - -def windows? - !!(RUBY_PLATFORM =~ /mswin|mingw|cygwin|windows/) -end - -if windows? - # include our libyajldll.a definitions on windows in the libyajl2 gem - $libs = "#{$libs} -lyajldll" -end - -# NOTE: find_library has the side effect of adding -lyajl to the flags which we are deliberately -# avoiding doing with the libyajl2-gem (allowing it to be lazily loaded with dlopen) -if !windows? && !find_header("yajl/yajl_tree.h") - puts "libyajl2 headers not found in libyajl2-gem, searching for system libraries..." - - HEADER_DIRS = [ - "/opt/local/include", # MacPorts - "/usr/local/include", # /usr/local - RbConfig::CONFIG["includedir"], # Ruby - "/usr/include", # (default) - ].freeze - - LIB_DIRS = [ - "/opt/local/lib", # MacPorts - "/usr/local/lib", # /usr/local + Homebrew - RbConfig::CONFIG["libdir"], # Ruby - "/usr/lib", # (default) - ].freeze - - # add --with-yajl-dir, --with-yajl-include, --with-yajl-lib - dir_config("yajl", HEADER_DIRS, LIB_DIRS) - - # here we use find_library in order to deliberately link with -lyajl as a useful side-effect - unless find_header("yajl/yajl_tree.h") && find_library("yajl", "yajl_complete_parse") - abort "libyajl2 is missing. please install libyajl2" - end -end - -dir_config "parser" - -create_makefile "ffi_yajl/ext/parser" diff --git a/ext/parser/parser.c b/ext/parser/parser.c deleted file mode 100644 index c0b8eab..0000000 --- a/ext/parser/parser.c +++ /dev/null @@ -1,240 +0,0 @@ -#include <ruby.h> -#include <yajl/yajl_parse.h> - -#ifdef HAVE_RUBY_ENCODING_H -#include <ruby/encoding.h> -static rb_encoding *utf8Encoding; -#endif - -static VALUE mFFI_Yajl, mExt, mParser, cParseError; - -typedef struct { - VALUE self; - int symbolizeKeys; - int uniqueKeyChecking; -} CTX; - -void set_value(CTX *ctx, VALUE val) { - 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: - if ( ctx->uniqueKeyChecking ) { - ID sym_has_key = rb_intern("has_key?"); - if ( rb_funcall(last, sym_has_key, 1, key) == Qtrue ) { - rb_raise(cParseError, "repeated key: %s", RSTRING_PTR(key)); - } - } - rb_hash_aset(last, key, val); - break; - default: - rb_ary_push(stack, val); - break; - } -} - -void set_key(CTX *ctx, VALUE key) { - rb_ivar_set(ctx->self, rb_intern("key"), key); -} - -void start_object(CTX *ctx, VALUE 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) { - 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)); - } -} - -int null_callback(void *ctx) { - set_value(ctx, Qnil); - return 1; -} - -int boolean_callback(void *ctx, int boolean) { - set_value(ctx, boolean ? Qtrue : Qfalse); - return 1; -} - -int integer_callback(void *ctx, long long intVal) { - set_value(ctx, LONG2NUM(intVal)); - return 1; -} - -int double_callback(void *ctx, double doubleVal) { - set_value(ctx, rb_float_new(doubleVal)); - return 1; -} - -int number_callback(void *ctx, const char *numberVal, size_t numberLen) { - char *buf = (char *)malloc(numberLen+1); - buf[numberLen] = 0; - memcpy(buf, numberVal, numberLen); - if (memchr(buf, '.', numberLen) || - memchr(buf, 'e', numberLen) || - memchr(buf, 'E', numberLen)) { - set_value(ctx, rb_float_new(strtod(buf, NULL))); - } else { - set_value(ctx, rb_cstr2inum(buf, 10)); - } - free(buf); - return 1; -} - -int string_callback(void *ctx, const unsigned char *stringVal, size_t stringLen) { - VALUE str = rb_str_new((const char *)stringVal, stringLen); -#ifdef HAVE_RUBY_ENCODING_H - rb_encoding *default_internal_enc = rb_default_internal_encoding(); - rb_enc_associate(str, utf8Encoding); - if (default_internal_enc) { - str = rb_str_export_to_enc(str, default_internal_enc); - } -#endif - set_value(ctx,str); - return 1; -} - -int start_map_callback(void *ctx) { - start_object(ctx,rb_hash_new()); - return 1; -} - -int map_key_callback(void *ctx, const unsigned char *stringVal, size_t stringLen) { - VALUE key; -#ifdef HAVE_RUBY_ENCODING_H - rb_encoding *default_internal_enc; -#endif - - if ( ((CTX *)ctx)->symbolizeKeys ) { -#ifdef HAVE_RUBY_ENCODING_H - ID id = rb_intern3((const char *)stringVal, stringLen, utf8Encoding); - key = ID2SYM(id); -#else - VALUE str = rb_str_new((const char *)stringVal, stringLen); - key = rb_str_intern(str); -#endif - } else { - key = rb_str_new((const char *)stringVal, stringLen); -#ifdef HAVE_RUBY_ENCODING_H - default_internal_enc = rb_default_internal_encoding(); - rb_enc_associate(key, utf8Encoding); - if (default_internal_enc) { - key = rb_str_export_to_enc(key, default_internal_enc); - } -#endif - } - set_key(ctx, key); - return 1; -} - -int end_map_callback(void *ctx) { - end_object(ctx); - return 1; -} - -int start_array_callback(void *ctx) { - start_object(ctx,rb_ary_new()); - return 1; -} - -int end_array_callback(void *ctx) { - end_object(ctx); - return 1; -} - -static yajl_callbacks callbacks = { - null_callback, - boolean_callback, - integer_callback, - double_callback, - number_callback, - string_callback, - start_map_callback, - map_key_callback, - end_map_callback, - start_array_callback, - end_array_callback, -}; - -int get_opts_key(VALUE self, const char *key) { - VALUE opts = rb_iv_get(self, "@opts"); - if (TYPE(opts) != T_HASH) { - rb_raise(rb_eTypeError, "opts is not a valid hash"); - } - return rb_hash_aref(opts, ID2SYM(rb_intern(key))) == Qtrue; -} - -static VALUE mParser_do_yajl_parse(VALUE self, VALUE str, VALUE yajl_opts) { - yajl_handle hand; - yajl_status stat; - unsigned char *err; - volatile CTX ctx; - - rb_ivar_set(self, rb_intern("key"), Qnil); - rb_ivar_set(self, rb_intern("stack"), rb_ary_new()); - rb_ivar_set(self, rb_intern("key_stack"), rb_ary_new()); - - ctx.self = self; - ctx.symbolizeKeys = get_opts_key(self, "symbolize_keys"); - ctx.uniqueKeyChecking = get_opts_key(self, "unique_key_checking"); - - hand = yajl_alloc(&callbacks, NULL, (void *)&ctx); - - if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_comments"))) == Qtrue) { - yajl_config(hand, yajl_allow_comments, 1); - } - if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_dont_validate_strings"))) == Qtrue) { - yajl_config(hand, yajl_dont_validate_strings, 1); - } - if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_trailing_garbage"))) == Qtrue) { - yajl_config(hand, yajl_allow_trailing_garbage, 1); - } - if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_multiple_values"))) == Qtrue) { - yajl_config(hand, yajl_allow_multiple_values, 1); - } - if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_partial_values"))) == Qtrue) { - yajl_config(hand, yajl_allow_partial_values, 1); - } - - if ((stat = yajl_parse(hand, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str))) != yajl_status_ok) { - err = yajl_get_error(hand, 1, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str)); - goto raise; - } - if ((stat = yajl_complete_parse(hand)) != yajl_status_ok) { - err = yajl_get_error(hand, 1, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str)); - goto raise; - } - yajl_free(hand); - return rb_ary_pop(rb_ivar_get(self, rb_intern("stack"))); - -raise: - if (hand) { - yajl_free(hand); - } - rb_raise(cParseError, "%s", err); -} - -void Init_parser() { - mFFI_Yajl = rb_define_module("FFI_Yajl"); - cParseError = rb_define_class_under(mFFI_Yajl, "ParseError", rb_eStandardError); - mExt = rb_define_module_under(mFFI_Yajl, "Ext"); - mParser = rb_define_module_under(mExt, "Parser"); - rb_define_method(mParser, "do_yajl_parse", mParser_do_yajl_parse, 2); -#ifdef HAVE_RUBY_ENCODING_H - utf8Encoding = rb_utf8_encoding(); -#endif -} diff --git a/spec/ffi_yajl/encoder_spec.rb b/spec/ffi_yajl/encoder_spec.rb index 7a76c0a..d2612a5 100644 --- a/spec/ffi_yajl/encoder_spec.rb +++ b/spec/ffi_yajl/encoder_spec.rb @@ -23,6 +23,7 @@ require "spec_helper" require "date" +require "ffi_yajl/ext/dlopen" describe "FFI_Yajl::Encoder" do let(:options) { {} } diff --git a/spec/ffi_yajl/map_library_name_spec.rb b/spec/ffi_yajl/map_library_name_spec.rb index 6ec8bb6..e63fadc 100644 --- a/spec/ffi_yajl/map_library_name_spec.rb +++ b/spec/ffi_yajl/map_library_name_spec.rb @@ -21,6 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. require "spec_helper" +require "ffi_yajl/ext/dlopen" class Test extend FFI_Yajl::MapLibraryName diff --git a/spec/ffi_yajl/parser_spec.rb b/spec/ffi_yajl/parser_spec.rb index 239ae26..9ac924a 100644 --- a/spec/ffi_yajl/parser_spec.rb +++ b/spec/ffi_yajl/parser_spec.rb @@ -22,6 +22,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. require "spec_helper" +require "ffi_yajl/ext/dlopen" describe "FFI_Yajl::Parser" do shared_examples_for "correct json parsing" do |