ffi-yajl 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -6
- data/Rakefile +7 -0
- data/ext/ffi_yajl/ext/dlopen/dlopen.c +40 -0
- data/ext/ffi_yajl/ext/dlopen/extconf.rb +15 -0
- data/ext/ffi_yajl/ext/encoder/encoder.c +17 -15
- data/ext/ffi_yajl/ext/parser/parser.c +9 -1
- data/lib/ffi_yajl/benchmark.rb +21 -0
- data/lib/ffi_yajl/encoder.rb +21 -0
- data/lib/ffi_yajl/ext.rb +27 -61
- data/lib/ffi_yajl/ffi/encoder.rb +30 -0
- data/lib/ffi_yajl/ffi/parser.rb +24 -0
- data/lib/ffi_yajl/ffi.rb +34 -13
- data/lib/ffi_yajl/map_library_name.rb +110 -0
- data/lib/ffi_yajl/parser.rb +23 -0
- data/lib/ffi_yajl/platform.rb +22 -0
- data/lib/ffi_yajl/version.rb +23 -1
- data/lib/ffi_yajl.rb +21 -4
- data/spec/ffi_yajl/encoder_spec.rb +26 -0
- data/spec/ffi_yajl/map_library_name_spec.rb +117 -0
- data/spec/ffi_yajl/parser_spec.rb +39 -1
- data/spec/spec_helper.rb +32 -0
- metadata +15 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 948084f681256d2d301e01415ce82e335f1bee52
|
4
|
+
data.tar.gz: f749ab5a3e388d3c069825b00cd37c30796db6d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fda05bb34154de35d5b9f2a9d3f3625267a2dd35ad3e048243a8cbf904397ae001462bbeb449e2d83d00564291a47152dff4414d36a217d7fdaf0bef5a288543
|
7
|
+
data.tar.gz: 9c47d061b3055164397a98666cf34786ff0341c0ccccb9fdb95655927150af3adbedc9d6ffcace61883cfb3f39e45102ee3fc990891cc5b4769de86f044a7f93
|
data/README.md
CHANGED
@@ -36,16 +36,30 @@ could support non-MRI rubies) and we also needed some bug fixes in
|
|
36
36
|
yajl2, but the maintainer wasn't able to devote enough time to the
|
37
37
|
project to make these updates in a timeframe that worked for us.
|
38
38
|
|
39
|
+
## Yajl Library Packaging
|
40
|
+
|
41
|
+
This library prefers to use the embedded yajl 2.x C library packaged in the
|
42
|
+
libyajl2 gem. In order to use the operating system yajl library (which must be
|
43
|
+
yajl 2.x) the environment variable `USE_SYSTEM_LIBYAJL2` can be set before
|
44
|
+
installing or bundling libyajl2. This will force the libyajl2 gem to skip
|
45
|
+
compiling its embedded library and the ffi-yajl gem will fallback to using the
|
46
|
+
system yajl library.
|
47
|
+
|
39
48
|
## Thanks
|
40
49
|
|
41
|
-
This was initially going to be a clean rewrite of an ffi ruby wrapper around
|
42
|
-
|
43
|
-
|
50
|
+
This was initially going to be a clean rewrite of an ffi ruby wrapper around
|
51
|
+
yajl2, but as it progressed more and more code was pulled in from brianmario's
|
52
|
+
existing yajl-ruby gem, particularly all the c extension code, lots of specs
|
53
|
+
and the benchmarks. And the process of writing this would have been much more
|
54
|
+
difficult without being able to draw heavily from already solved problems in
|
44
55
|
yajl-ruby.
|
45
56
|
|
46
57
|
## License
|
47
58
|
|
48
|
-
Given that this draws heavily from the yajl-ruby sources, and could be
|
49
|
-
|
50
|
-
|
59
|
+
Given that this draws heavily from the yajl-ruby sources, and could be
|
60
|
+
considered a derivative work, the MIT License from that project has been
|
61
|
+
preserved and this source code has deliberately not been dual licensed under
|
62
|
+
Chef's typical Apache License. See the
|
63
|
+
[LICENSE](https://github.com/chef/ffi-yajl/blob/master/LICENSE) file in this
|
64
|
+
project.
|
51
65
|
|
data/Rakefile
CHANGED
@@ -51,6 +51,13 @@ Rake::ExtensionTask.new do |ext|
|
|
51
51
|
ext.gem_spec = spec
|
52
52
|
end
|
53
53
|
|
54
|
+
Rake::ExtensionTask.new do |ext|
|
55
|
+
ext.name = 'dlopen'
|
56
|
+
ext.lib_dir = 'lib/ffi_yajl/ext'
|
57
|
+
ext.ext_dir = 'ext/ffi_yajl/ext/dlopen'
|
58
|
+
ext.gem_spec = spec
|
59
|
+
end
|
60
|
+
|
54
61
|
#
|
55
62
|
# test tasks
|
56
63
|
#
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#if defined(HAVE_DLFCN_H)
|
4
|
+
# include <dlfcn.h>
|
5
|
+
#ifndef RTLD_LAZY
|
6
|
+
#define RTLD_LAZY 0
|
7
|
+
#endif
|
8
|
+
#ifndef RTLD_GLOBAL
|
9
|
+
#define RTLD_GLOBAL 0
|
10
|
+
#endif
|
11
|
+
#ifndef RTLD_NOW
|
12
|
+
#define RTLD_NOW 0
|
13
|
+
#endif
|
14
|
+
#else
|
15
|
+
# if defined(_WIN32)
|
16
|
+
# include <windows.h>
|
17
|
+
# define dlopen(name,flag) ((void*)LoadLibrary(name))
|
18
|
+
# define dlerror() strerror(rb_w32_map_errno(GetLastError()))
|
19
|
+
# define dlsym(handle,name) ((void*)GetProcAddress((handle),(name)))
|
20
|
+
# define RTLD_LAZY -1
|
21
|
+
# define RTLD_NOW -1
|
22
|
+
# define RTLD_GLOBAL -1
|
23
|
+
# endif
|
24
|
+
#endif
|
25
|
+
|
26
|
+
static VALUE mFFI_Yajl, mDlopen, mExt;
|
27
|
+
|
28
|
+
static VALUE mDlopen_dlopen(VALUE self, VALUE file) {
|
29
|
+
if (dlopen(RSTRING_PTR(file), RTLD_NOW|RTLD_GLOBAL) == NULL) {
|
30
|
+
rb_raise(rb_eArgError, "%s", dlerror());
|
31
|
+
}
|
32
|
+
return Qnil;
|
33
|
+
}
|
34
|
+
|
35
|
+
void Init_dlopen() {
|
36
|
+
mFFI_Yajl = rb_define_module("FFI_Yajl");
|
37
|
+
mExt = rb_define_module_under(mFFI_Yajl, "Ext");
|
38
|
+
mDlopen = rb_define_module_under(mExt, "Dlopen");
|
39
|
+
rb_define_method(mDlopen, "dlopen", mDlopen_dlopen, 1);
|
40
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
5
|
+
|
6
|
+
puts $CFLAGS
|
7
|
+
puts $LDFLAGS
|
8
|
+
|
9
|
+
have_header("dlfcn.h")
|
10
|
+
|
11
|
+
have_library("dl", "dlopen")
|
12
|
+
|
13
|
+
dir_config 'dlopen'
|
14
|
+
|
15
|
+
create_makefile 'ffi_yajl/ext/dlopen'
|
@@ -2,7 +2,7 @@
|
|
2
2
|
#include <yajl/yajl_gen.h>
|
3
3
|
|
4
4
|
static VALUE mFFI_Yajl, mExt, mEncoder, mEncoder2, cEncodeError;
|
5
|
-
static VALUE cDate, cTime, cDateTime;
|
5
|
+
static VALUE cDate, cTime, cDateTime, cStringIO;
|
6
6
|
static VALUE cYajl_Gen;
|
7
7
|
|
8
8
|
/* FIXME: the json gem does a whole bunch of indirection around monkeypatching... not sure if we need to as well... */
|
@@ -295,11 +295,8 @@ static VALUE rb_cString_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
|
|
295
295
|
return Qnil;
|
296
296
|
}
|
297
297
|
|
298
|
-
|
299
|
-
static VALUE object_to_s_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
|
298
|
+
static VALUE string_ffi_yajl(VALUE str, VALUE rb_yajl_gen, VALUE state) {
|
300
299
|
yajl_gen_status status;
|
301
|
-
ID sym_to_s = rb_intern("to_s");
|
302
|
-
VALUE str = rb_funcall(self, sym_to_s, 0);
|
303
300
|
char *cptr = RSTRING_PTR(str);
|
304
301
|
int len = RSTRING_LEN(str);
|
305
302
|
struct yajl_gen_t *yajl_gen;
|
@@ -312,6 +309,13 @@ static VALUE object_to_s_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
|
|
312
309
|
return Qnil;
|
313
310
|
}
|
314
311
|
|
312
|
+
/* calls #to_s on an object to encode it */
|
313
|
+
static VALUE object_to_s_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
|
314
|
+
ID sym_to_s = rb_intern("to_s");
|
315
|
+
VALUE str = rb_funcall(self, sym_to_s, 0);
|
316
|
+
return string_ffi_yajl(str, rb_yajl_gen, state);
|
317
|
+
}
|
318
|
+
|
315
319
|
static VALUE rb_cSymbol_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
|
316
320
|
return object_to_s_ffi_yajl(self, rb_yajl_gen, state);
|
317
321
|
}
|
@@ -321,19 +325,15 @@ static VALUE rb_cDate_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
|
|
321
325
|
}
|
322
326
|
|
323
327
|
static VALUE rb_cTime_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
|
324
|
-
yajl_gen_status status;
|
325
328
|
ID sym_strftime = rb_intern("strftime");
|
326
329
|
VALUE str = rb_funcall(self, sym_strftime, 1, rb_str_new2("%Y-%m-%d %H:%M:%S %z"));
|
327
|
-
|
328
|
-
|
329
|
-
struct yajl_gen_t *yajl_gen;
|
330
|
-
Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen);
|
331
|
-
|
332
|
-
CHECK_STATUS(
|
333
|
-
yajl_gen_string(yajl_gen, (unsigned char *)cptr, len)
|
334
|
-
);
|
330
|
+
return string_ffi_yajl(str, rb_yajl_gen, state);
|
331
|
+
}
|
335
332
|
|
336
|
-
|
333
|
+
static VALUE rb_cStringIO_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
|
334
|
+
ID sym_read = rb_intern("read");
|
335
|
+
VALUE str = rb_funcall(self, sym_read, 0);
|
336
|
+
return string_ffi_yajl(str, rb_yajl_gen, state);
|
337
337
|
}
|
338
338
|
|
339
339
|
static VALUE rb_cDateTime_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
|
@@ -373,6 +373,7 @@ void Init_encoder() {
|
|
373
373
|
cDate = rb_define_class("Date", rb_cObject);
|
374
374
|
cTime = rb_define_class("Time", rb_cObject);
|
375
375
|
cDateTime = rb_define_class("DateTime", cDate);
|
376
|
+
cStringIO = rb_define_class("StringIO", rb_cData);
|
376
377
|
|
377
378
|
rb_define_method(rb_cHash, "ffi_yajl", rb_cHash_ffi_yajl, 2);
|
378
379
|
rb_define_method(rb_cArray, "ffi_yajl", rb_cArray_ffi_yajl, 2);
|
@@ -387,5 +388,6 @@ void Init_encoder() {
|
|
387
388
|
rb_define_method(cDate, "ffi_yajl", rb_cDate_ffi_yajl, 2);
|
388
389
|
rb_define_method(cTime, "ffi_yajl", rb_cTime_ffi_yajl, 2);
|
389
390
|
rb_define_method(cDateTime, "ffi_yajl", rb_cDateTime_ffi_yajl, 2);
|
391
|
+
rb_define_method(cStringIO, "ffi_yajl", rb_cStringIO_ffi_yajl, 2);
|
390
392
|
rb_define_method(rb_cObject, "ffi_yajl", rb_cObject_ffi_yajl, 2);
|
391
393
|
}
|
@@ -11,6 +11,7 @@ static VALUE mFFI_Yajl, mExt, mParser, cParseError;
|
|
11
11
|
typedef struct {
|
12
12
|
VALUE self;
|
13
13
|
int symbolizeKeys;
|
14
|
+
int uniqueKeyChecking;
|
14
15
|
} CTX;
|
15
16
|
|
16
17
|
void set_value(CTX *ctx, VALUE val) {
|
@@ -23,6 +24,12 @@ void set_value(CTX *ctx, VALUE val) {
|
|
23
24
|
rb_ary_push(last, val);
|
24
25
|
break;
|
25
26
|
case T_HASH:
|
27
|
+
if ( ctx->uniqueKeyChecking ) {
|
28
|
+
ID sym_has_key = rb_intern("has_key?");
|
29
|
+
if ( rb_funcall(last, sym_has_key, 1, key) == Qtrue ) {
|
30
|
+
rb_raise(cParseError, "repeated key: %s", RSTRING_PTR(key));
|
31
|
+
}
|
32
|
+
}
|
26
33
|
rb_hash_aset(last, key, val);
|
27
34
|
break;
|
28
35
|
default:
|
@@ -163,7 +170,7 @@ static yajl_callbacks callbacks = {
|
|
163
170
|
end_array_callback,
|
164
171
|
};
|
165
172
|
|
166
|
-
int get_opts_key(VALUE self, char *key) {
|
173
|
+
int get_opts_key(VALUE self, const char *key) {
|
167
174
|
VALUE opts = rb_iv_get(self, "@opts");
|
168
175
|
if (TYPE(opts) != T_HASH) {
|
169
176
|
rb_raise(rb_eTypeError, "opts is not a valid hash");
|
@@ -182,6 +189,7 @@ static VALUE mParser_do_yajl_parse(VALUE self, VALUE str, VALUE yajl_opts) {
|
|
182
189
|
|
183
190
|
ctx.self = self;
|
184
191
|
ctx.symbolizeKeys = get_opts_key(self, "symbolize_keys");
|
192
|
+
ctx.uniqueKeyChecking = get_opts_key(self, "unique_key_checking");
|
185
193
|
|
186
194
|
hand = yajl_alloc(&callbacks, NULL, (void *)&ctx);
|
187
195
|
|
data/lib/ffi_yajl/benchmark.rb
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
22
|
|
2
23
|
require 'ffi_yajl/benchmark/encode.rb'
|
3
24
|
require 'ffi_yajl/benchmark/encode_profile.rb'
|
data/lib/ffi_yajl/encoder.rb
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
22
|
|
2
23
|
module FFI_Yajl
|
3
24
|
class EncodeError < StandardError; end
|
data/lib/ffi_yajl/ext.rb
CHANGED
@@ -1,71 +1,37 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
1
23
|
require 'rubygems'
|
2
24
|
|
3
25
|
require 'ffi_yajl/encoder'
|
4
26
|
require 'ffi_yajl/parser'
|
5
|
-
require '
|
6
|
-
require '
|
7
|
-
require 'ffi_yajl/platform'
|
27
|
+
require 'ffi_yajl/ext/dlopen'
|
28
|
+
require 'ffi_yajl/map_library_name'
|
8
29
|
|
9
30
|
module FFI_Yajl
|
10
|
-
extend FFI_Yajl::
|
11
|
-
|
12
|
-
# FIXME: DRY with ffi_yajl/ffi.rb
|
13
|
-
# FIXME: extract map_library_name from FFI and stop requiring it at the top level
|
14
|
-
# so that the C-library can be installed without FFI
|
15
|
-
libname = ::FFI.map_library_name("yajl")
|
16
|
-
# awful windows patch, but there is an open issue to entirely replace FFI.map_library_name already
|
17
|
-
libname = "libyajl.so" if windows?
|
18
|
-
libpath = File.expand_path(File.join(Libyajl2.opt_path, libname))
|
19
|
-
libpath.gsub!(/dylib/, 'bundle')
|
20
|
-
libpath = ::FFI.map_library_name("yajl") unless File.exist?(libpath)
|
21
|
-
|
22
|
-
#
|
23
|
-
# FFS, what exactly was so wrong with DL.dlopen that ruby had to get rid of it???
|
24
|
-
#
|
25
|
-
|
26
|
-
def self.try_fiddle_dlopen(libpath)
|
27
|
-
require 'fiddle'
|
28
|
-
if defined?(Fiddle) && Fiddle.respond_to?(:dlopen)
|
29
|
-
::Fiddle.dlopen(libpath)
|
30
|
-
true
|
31
|
-
else
|
32
|
-
false
|
33
|
-
end
|
34
|
-
rescue LoadError
|
35
|
-
return false
|
36
|
-
end
|
31
|
+
extend FFI_Yajl::MapLibraryName
|
32
|
+
extend FFI_Yajl::Ext::Dlopen
|
37
33
|
|
38
|
-
|
39
|
-
require 'dl'
|
40
|
-
if defined?(DL) && DL.respond_to?(:dlopen)
|
41
|
-
::DL.dlopen(libpath)
|
42
|
-
true
|
43
|
-
else
|
44
|
-
false
|
45
|
-
end
|
46
|
-
rescue LoadError
|
47
|
-
return false
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.try_ffi_dlopen(libpath)
|
51
|
-
require 'ffi'
|
52
|
-
require 'rbconfig'
|
53
|
-
extend ::FFI::Library
|
54
|
-
ffi_lib 'dl'
|
55
|
-
attach_function 'dlopen', :dlopen, [:string, :int], :void
|
56
|
-
if RbConfig::CONFIG['host_os'] =~ /linux/i
|
57
|
-
dlopen libpath, 0x102 # linux: RTLD_GLOBAL | RTLD_NOW
|
58
|
-
else
|
59
|
-
dlopen libpath, 0
|
60
|
-
end
|
61
|
-
true
|
62
|
-
rescue LoadError
|
63
|
-
return false
|
64
|
-
end
|
65
|
-
|
66
|
-
unless try_fiddle_dlopen(libpath) || try_dl_dlopen(libpath) || try_ffi_dlopen(libpath)
|
67
|
-
raise "cannot find dlopen via Fiddle, DL or FFI, what am I supposed to do?"
|
68
|
-
end
|
34
|
+
dlopen_yajl_library
|
69
35
|
|
70
36
|
class Parser
|
71
37
|
require 'ffi_yajl/ext/parser'
|
data/lib/ffi_yajl/ffi/encoder.rb
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
22
|
|
2
23
|
require 'ffi_yajl/ffi'
|
3
24
|
|
@@ -206,6 +227,15 @@ class String
|
|
206
227
|
end
|
207
228
|
end
|
208
229
|
|
230
|
+
class StringIO
|
231
|
+
def ffi_yajl(yajl_gen, state)
|
232
|
+
str = self.read
|
233
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
234
|
+
FFI_Yajl::Encoder.raise_error_for_status(status)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
209
239
|
class Date
|
210
240
|
def ffi_yajl(yajl_gen, state)
|
211
241
|
str = self.to_s
|
data/lib/ffi_yajl/ffi/parser.rb
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
22
|
|
2
23
|
require 'ffi_yajl/ffi'
|
3
24
|
|
@@ -9,6 +30,9 @@ module FFI_Yajl
|
|
9
30
|
case stack.last
|
10
31
|
when Hash
|
11
32
|
raise FFI_Yajl::ParseError.new("internal error: missing key in parse") if key.nil?
|
33
|
+
if @opts[:unique_key_checking] && stack.last.has_key?(key)
|
34
|
+
raise FFI_Yajl::ParseError.new("repeated key: #{key}")
|
35
|
+
end
|
12
36
|
stack.last[key] = val
|
13
37
|
when Array
|
14
38
|
stack.last.push(val)
|
data/lib/ffi_yajl/ffi.rb
CHANGED
@@ -1,23 +1,44 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
1
23
|
require 'rubygems'
|
2
24
|
|
3
25
|
require 'libyajl2'
|
4
|
-
|
26
|
+
begin
|
27
|
+
require 'ffi'
|
28
|
+
rescue LoadError
|
29
|
+
$stderr.puts "FATAL: to use the ffi extension instead of the compiled C extension, the ffi gem must be installed"
|
30
|
+
$stderr.puts " (it is optional, so you must include it in your bundle manually)"
|
31
|
+
exit 1
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'ffi_yajl/map_library_name'
|
5
35
|
|
6
36
|
module FFI_Yajl
|
7
37
|
extend ::FFI::Library
|
8
38
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
libpath = File.expand_path(File.join(Libyajl2.opt_path, libname))
|
13
|
-
libpath.gsub!(/dylib/, 'bundle')
|
14
|
-
|
15
|
-
if File.file?(libpath)
|
16
|
-
# use our vendored version of libyajl2 if we find it installed
|
17
|
-
ffi_lib libpath
|
18
|
-
else
|
19
|
-
ffi_lib 'yajl'
|
20
|
-
end
|
39
|
+
extend FFI_Yajl::MapLibraryName
|
40
|
+
|
41
|
+
ffi_open_yajl_library
|
21
42
|
|
22
43
|
class YajlCallbacks < ::FFI::Struct
|
23
44
|
layout :yajl_null, :pointer,
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'libyajl2'
|
24
|
+
|
25
|
+
# Mixin for use in finding the right yajl library on the system. The 'caller'
|
26
|
+
# needs to also mixin either the FFI module or the DLopen module. Those are
|
27
|
+
# deliberately not mixed in to avoid loading the dlopen module in the ffi
|
28
|
+
# codepath (which fails on jruby which does not have that C extension).
|
29
|
+
|
30
|
+
module FFI_Yajl
|
31
|
+
module MapLibraryName
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Stub for tests to override the host_os
|
36
|
+
#
|
37
|
+
# @api private
|
38
|
+
# @return Array<String> lower case ruby host_os string
|
39
|
+
def host_os
|
40
|
+
RbConfig::CONFIG['host_os'].downcase
|
41
|
+
end
|
42
|
+
|
43
|
+
# Array of yajl library names on the platform. Some platforms like Windows
|
44
|
+
# and Mac may have different names/extensions.
|
45
|
+
#
|
46
|
+
# @api private
|
47
|
+
# @return Array<String> Array of yajl library names for platform
|
48
|
+
def library_names
|
49
|
+
case host_os
|
50
|
+
when /mingw|mswin/
|
51
|
+
[ "libyajl.so", "yajl.dll" ]
|
52
|
+
when /cygwin/
|
53
|
+
[ "libyajl.so", "cygyajl.dll" ]
|
54
|
+
when /darwin/
|
55
|
+
[ "libyajl.bundle", "libyajl.dylib" ]
|
56
|
+
else
|
57
|
+
[ "libyajl.so" ]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Array of yajl library names prepended with the libyajl2 path to use to
|
62
|
+
# load those directly and bypass the system libyajl by default. Since
|
63
|
+
# these are full paths, this API checks to ensure that the file exists on
|
64
|
+
# the filesystem. May return an empty array.
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
# @return Array<String> Array of full paths to libyajl2 gem libraries
|
68
|
+
def expanded_library_names
|
69
|
+
library_names.map do |libname|
|
70
|
+
pathname = File.expand_path(File.join(Libyajl2.opt_path, libname))
|
71
|
+
pathname if File.file?(pathname)
|
72
|
+
end.compact
|
73
|
+
end
|
74
|
+
|
75
|
+
# Iterate across the expanded library names in the libyajl2-gem and then
|
76
|
+
# attempt to load the system libraries. Uses the native dlopen extension
|
77
|
+
# that ships in this gem.
|
78
|
+
#
|
79
|
+
# @api private
|
80
|
+
def dlopen_yajl_library
|
81
|
+
found = false
|
82
|
+
( expanded_library_names + library_names ).each do |libname|
|
83
|
+
begin
|
84
|
+
dlopen(libname)
|
85
|
+
found = true
|
86
|
+
break
|
87
|
+
rescue ArgumentError
|
88
|
+
end
|
89
|
+
end
|
90
|
+
raise "cannot find yajl library for platform" unless found
|
91
|
+
end
|
92
|
+
|
93
|
+
# Iterate across the expanded library names in the libyajl2-gem and attempt
|
94
|
+
# to load them. If they are missing just use `ffi_lib 'yajl'` to accept
|
95
|
+
# the FFI default algorithm to find the library.
|
96
|
+
#
|
97
|
+
# @api private
|
98
|
+
def ffi_open_yajl_library
|
99
|
+
found = false
|
100
|
+
expanded_library_names.each do |libname|
|
101
|
+
begin
|
102
|
+
ffi_lib libname
|
103
|
+
found = true
|
104
|
+
rescue LoadError
|
105
|
+
end
|
106
|
+
end
|
107
|
+
ffi_lib 'yajl' unless found
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/lib/ffi_yajl/parser.rb
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
22
|
|
2
23
|
module FFI_Yajl
|
3
24
|
class ParseError < StandardError; end
|
@@ -54,6 +75,8 @@ module FFI_Yajl
|
|
54
75
|
yajl_opts[:yajl_allow_multiple_values] = @opts[:allow_multiple_values]
|
55
76
|
yajl_opts[:yajl_allow_partial_values] = @opts[:allow_partial_values]
|
56
77
|
|
78
|
+
yajl_opts[:unique_key_checking] = @opts[:unique_key_checking]
|
79
|
+
|
57
80
|
# XXX: bug-compat with ruby-yajl
|
58
81
|
return nil if str == ""
|
59
82
|
|
data/lib/ffi_yajl/platform.rb
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
1
23
|
module FFI_Yajl
|
2
24
|
module Platform
|
3
25
|
def windows?
|
data/lib/ffi_yajl/version.rb
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
1
23
|
module FFI_Yajl
|
2
|
-
VERSION = "2.
|
24
|
+
VERSION = "2.1.0"
|
3
25
|
end
|
data/lib/ffi_yajl.rb
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
22
|
|
2
23
|
#
|
3
24
|
# Precedence:
|
@@ -19,10 +40,6 @@ elsif ENV['FORCE_FFI_YAJL'] == "ffi"
|
|
19
40
|
require 'ffi_yajl/ffi'
|
20
41
|
elsif RUBY_PLATFORM == "java"
|
21
42
|
require 'ffi_yajl/ffi'
|
22
|
-
elsif defined?(Yajl)
|
23
|
-
warn "the ffi-yajl and yajl-ruby gems have incompatible C libyajl libs and should not be loaded in the same Ruby VM"
|
24
|
-
warn "falling back to ffi which might work (or might not, no promises)"
|
25
|
-
require 'ffi_yajl/ffi'
|
26
43
|
else
|
27
44
|
begin
|
28
45
|
require 'ffi_yajl/ext'
|
@@ -1,4 +1,25 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
+
# Copyright (c) 2015 Lamont Granquist
|
3
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
2
23
|
|
3
24
|
require 'spec_helper'
|
4
25
|
require 'date'
|
@@ -110,6 +131,11 @@ describe "FFI_Yajl::Encoder" do
|
|
110
131
|
expect(encoder.encode(ruby)).to eq( %q{"2001-02-03"} )
|
111
132
|
end
|
112
133
|
|
134
|
+
it "can encode StringIOs" do
|
135
|
+
ruby = { "foo" => StringIO.new('THING') }
|
136
|
+
expect(encoder.encode(ruby)).to eq("{\"foo\":\"THING\"}")
|
137
|
+
end
|
138
|
+
|
113
139
|
context "when encoding Time objects in UTC timezone" do
|
114
140
|
before do
|
115
141
|
@saved_tz = ENV['TZ']
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'spec_helper'
|
24
|
+
|
25
|
+
class Test
|
26
|
+
extend FFI_Yajl::MapLibraryName
|
27
|
+
end
|
28
|
+
|
29
|
+
host_os_library_name_mapping = {
|
30
|
+
"mingw" => [ "libyajl.so", "yajl.dll" ],
|
31
|
+
"mswin" => [ "libyajl.so", "yajl.dll" ],
|
32
|
+
"cygwin" => [ "libyajl.so", "cygyajl.dll" ],
|
33
|
+
"darwin" => [ "libyajl.bundle", "libyajl.dylib" ],
|
34
|
+
"solaris2" => [ "libyajl.so" ],
|
35
|
+
"linux" => [ "libyajl.so" ],
|
36
|
+
"aix" => [ "libyajl.so" ],
|
37
|
+
"hpux" => [ "libyajl.so" ],
|
38
|
+
"netbsd" => [ "libyajl.so" ],
|
39
|
+
"openbsd" => [ "libyajl.so" ],
|
40
|
+
"freebsd" => [ "libyajl.so" ],
|
41
|
+
}
|
42
|
+
|
43
|
+
describe "FFI_Yajl::MapLibraryName" do
|
44
|
+
let(:libyajl2_opt_path) { "/libyajl2/lib" }
|
45
|
+
before do
|
46
|
+
allow(Libyajl2).to receive(:opt_path).and_return(libyajl2_opt_path)
|
47
|
+
end
|
48
|
+
|
49
|
+
host_os_library_name_mapping.each do |host_os, library_names|
|
50
|
+
|
51
|
+
context "#library_names" do
|
52
|
+
it "maps #{host_os} correctly" do
|
53
|
+
allow(Test).to receive(:host_os).and_return(host_os)
|
54
|
+
expect(Test.send(:library_names)).to eq(library_names)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "#expanded_library_names" do
|
59
|
+
it "maps #{host_os} correctly" do
|
60
|
+
allow(Test).to receive(:host_os).and_return(host_os)
|
61
|
+
expanded_library_names = []
|
62
|
+
library_names.each do |library_name|
|
63
|
+
path = File.expand_path(File.join(libyajl2_opt_path, library_name))
|
64
|
+
expanded_library_names.push(path)
|
65
|
+
expect(File).to receive(:file?).with(path).and_return(true)
|
66
|
+
end
|
67
|
+
expect(Test.send(:expanded_library_names)).to eq(expanded_library_names)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "#dlopen_yajl_library" do
|
72
|
+
it "should call dlopen against an expanded library name if it finds it on #{host_os}" do
|
73
|
+
allow(Test).to receive(:host_os).and_return(host_os)
|
74
|
+
library_names.each do |library_name|
|
75
|
+
path = File.expand_path(File.join(libyajl2_opt_path, library_name))
|
76
|
+
allow(File).to receive(:file?).with(path).and_return(true)
|
77
|
+
allow(Test).to receive(:dlopen).with(path).and_return(nil)
|
78
|
+
end
|
79
|
+
Test.send(:dlopen_yajl_library)
|
80
|
+
end
|
81
|
+
it "if dlopen calls all raise it should still use the short names on #{host_os}" do
|
82
|
+
allow(Test).to receive(:host_os).and_return(host_os)
|
83
|
+
library_names.each do |library_name|
|
84
|
+
path = File.expand_path(File.join(libyajl2_opt_path, library_name))
|
85
|
+
allow(File).to receive(:file?).with(path).and_return(true)
|
86
|
+
allow(Test).to receive(:dlopen).with(path).and_raise(ArgumentError)
|
87
|
+
end
|
88
|
+
allow(Test).to receive(:dlopen).with(library_names.first).and_return(nil)
|
89
|
+
Test.send(:dlopen_yajl_library)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "ffi_open_yajl_library" do
|
94
|
+
it "should call ffi_lib against an expanded library name if it finds it on #{host_os}" do
|
95
|
+
allow(Test).to receive(:host_os).and_return(host_os)
|
96
|
+
library_names.each do |library_name|
|
97
|
+
path = File.expand_path(File.join(libyajl2_opt_path, library_name))
|
98
|
+
allow(File).to receive(:file?).with(path).and_return(true)
|
99
|
+
allow(Test).to receive(:ffi_lib).with(path).and_return(nil)
|
100
|
+
end
|
101
|
+
Test.send(:ffi_open_yajl_library)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "if dlopen calls all raise it should still use 'yajl' on #{host_os}" do
|
105
|
+
allow(Test).to receive(:host_os).and_return(host_os)
|
106
|
+
library_names.each do |library_name|
|
107
|
+
path = File.expand_path(File.join(libyajl2_opt_path, library_name))
|
108
|
+
allow(File).to receive(:file?).with(path).and_return(true)
|
109
|
+
allow(Test).to receive(:ffi_lib).with(path).and_raise(LoadError)
|
110
|
+
end
|
111
|
+
allow(Test).to receive(:ffi_lib).with('yajl').and_return(nil)
|
112
|
+
Test.send(:ffi_open_yajl_library)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
@@ -1,4 +1,25 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
+
# Copyright (c) 2015 Lamont Granquist
|
3
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
2
23
|
|
3
24
|
require 'spec_helper'
|
4
25
|
|
@@ -453,7 +474,9 @@ describe "FFI_Yajl::Parser" do
|
|
453
474
|
end
|
454
475
|
end
|
455
476
|
|
456
|
-
|
477
|
+
# NOTE: parsing floats with 8 million digits on windows has some kind of huge
|
478
|
+
# perf issues likely in ruby and/or the underlying windows libs
|
479
|
+
context "when parsing big floats", :ruby_gte_193 => true, :unix_only => true do
|
457
480
|
let(:json) { '[0.' + '1' * 2**23 + ']' }
|
458
481
|
|
459
482
|
it "parses" do
|
@@ -469,6 +492,21 @@ describe "FFI_Yajl::Parser" do
|
|
469
492
|
expect{ parser }.not_to raise_error
|
470
493
|
end
|
471
494
|
end
|
495
|
+
|
496
|
+
context "should ignore repeated keys by default" do
|
497
|
+
let(:json) { '{"foo":"bar","foo":"baz"}' }
|
498
|
+
it "should replace the first hash key with the second" do
|
499
|
+
expect(parser).to eql( "foo" => "baz" )
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
context "should raise an exception for repeated keys" do
|
504
|
+
let(:json) { '{"foo":"bar","foo":"baz"}' }
|
505
|
+
let(:options) { { :unique_key_checking => true } }
|
506
|
+
it "should raise" do
|
507
|
+
expect{ parser }.to raise_error(FFI_Yajl::ParseError)
|
508
|
+
end
|
509
|
+
end
|
472
510
|
end
|
473
511
|
|
474
512
|
context "when options are set to empty hash" do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,40 @@
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
1
23
|
$: << File.expand_path(File.join(File.dirname( __FILE__ ), "../lib"))
|
2
24
|
|
25
|
+
# load yajl-ruby into the same process (tests that both c-libs can be
|
26
|
+
# linked in the same process). this should work, see:
|
27
|
+
# http://stackoverflow.com/questions/3232822/linking-with-multiple-versions-of-a-library
|
28
|
+
begin
|
29
|
+
require 'yajl'
|
30
|
+
rescue LoadError
|
31
|
+
# yajl can't be installed on jruby
|
32
|
+
end
|
33
|
+
|
3
34
|
require 'ffi_yajl'
|
4
35
|
|
5
36
|
RSpec.configure do |c|
|
37
|
+
c.filter_run_excluding :unix_only => true unless RUBY_PLATFORM !~ /mswin|mingw|windows/
|
6
38
|
c.filter_run_excluding :ruby_gte_19 => true unless RUBY_VERSION.to_f >= 1.9
|
7
39
|
c.filter_run_excluding :ruby_gte_193 => true unless RUBY_VERSION.to_f >= 2.0 || RUBY_VERSION =~ /^1\.9\.3/
|
8
40
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ffi-yajl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lamont Granquist
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -81,33 +81,33 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.16'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: libyajl2
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '1.
|
89
|
+
version: '1.2'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '1.
|
96
|
+
version: '1.2'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: ffi
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '1.
|
104
|
-
type: :
|
103
|
+
version: '1.5'
|
104
|
+
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '1.
|
110
|
+
version: '1.5'
|
111
111
|
description: Ruby FFI wrapper around YAJL 2.x
|
112
112
|
email: lamont@getchef.com
|
113
113
|
executables:
|
@@ -115,6 +115,7 @@ executables:
|
|
115
115
|
extensions:
|
116
116
|
- ext/ffi_yajl/ext/encoder/extconf.rb
|
117
117
|
- ext/ffi_yajl/ext/parser/extconf.rb
|
118
|
+
- ext/ffi_yajl/ext/dlopen/extconf.rb
|
118
119
|
extra_rdoc_files:
|
119
120
|
- README.md
|
120
121
|
- LICENSE
|
@@ -123,6 +124,8 @@ files:
|
|
123
124
|
- README.md
|
124
125
|
- Rakefile
|
125
126
|
- bin/ffi-yajl-bench
|
127
|
+
- ext/ffi_yajl/ext/dlopen/dlopen.c
|
128
|
+
- ext/ffi_yajl/ext/dlopen/extconf.rb
|
126
129
|
- ext/ffi_yajl/ext/encoder/encoder.c
|
127
130
|
- ext/ffi_yajl/ext/encoder/extconf.rb
|
128
131
|
- ext/ffi_yajl/ext/parser/extconf.rb
|
@@ -154,10 +157,12 @@ files:
|
|
154
157
|
- lib/ffi_yajl/ffi.rb
|
155
158
|
- lib/ffi_yajl/ffi/encoder.rb
|
156
159
|
- lib/ffi_yajl/ffi/parser.rb
|
160
|
+
- lib/ffi_yajl/map_library_name.rb
|
157
161
|
- lib/ffi_yajl/parser.rb
|
158
162
|
- lib/ffi_yajl/platform.rb
|
159
163
|
- lib/ffi_yajl/version.rb
|
160
164
|
- spec/ffi_yajl/encoder_spec.rb
|
165
|
+
- spec/ffi_yajl/map_library_name_spec.rb
|
161
166
|
- spec/ffi_yajl/parser_spec.rb
|
162
167
|
- spec/spec_helper.rb
|
163
168
|
homepage: http://github.com/chef/ffi-yajl
|
@@ -180,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
185
|
version: '0'
|
181
186
|
requirements: []
|
182
187
|
rubyforge_project:
|
183
|
-
rubygems_version: 2.4.
|
188
|
+
rubygems_version: 2.4.6
|
184
189
|
signing_key:
|
185
190
|
specification_version: 4
|
186
191
|
summary: Ruby FFI wrapper around YAJL 2.x
|