ffi-yajl 2.0.0-universal-java → 2.1.0-universal-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.rb +21 -4
- 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.rb +34 -13
- data/lib/ffi_yajl/ffi/encoder.rb +30 -0
- data/lib/ffi_yajl/ffi/parser.rb +24 -0
- 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/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 +13 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 405d187ca7b5ec111ac8efbe005109f8bba785a8
|
4
|
+
data.tar.gz: f749ab5a3e388d3c069825b00cd37c30796db6d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f67c6da0c07d49a2fdb20a2bdbedd9e93eb161a81ebad06601fb9b4200ee1413a24418487fad7d8bb3b0845b72adf83f398a200bdb4d5965322a49205ed98a7
|
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.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'
|
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.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,
|
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)
|
@@ -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
|
@@ -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: universal-java
|
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.
|
103
|
+
version: '1.5'
|
104
104
|
type: :runtime
|
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:
|
@@ -121,6 +121,8 @@ files:
|
|
121
121
|
- README.md
|
122
122
|
- Rakefile
|
123
123
|
- bin/ffi-yajl-bench
|
124
|
+
- ext/ffi_yajl/ext/dlopen/dlopen.c
|
125
|
+
- ext/ffi_yajl/ext/dlopen/extconf.rb
|
124
126
|
- ext/ffi_yajl/ext/encoder/encoder.c
|
125
127
|
- ext/ffi_yajl/ext/encoder/extconf.rb
|
126
128
|
- ext/ffi_yajl/ext/parser/extconf.rb
|
@@ -152,10 +154,12 @@ files:
|
|
152
154
|
- lib/ffi_yajl/ffi.rb
|
153
155
|
- lib/ffi_yajl/ffi/encoder.rb
|
154
156
|
- lib/ffi_yajl/ffi/parser.rb
|
157
|
+
- lib/ffi_yajl/map_library_name.rb
|
155
158
|
- lib/ffi_yajl/parser.rb
|
156
159
|
- lib/ffi_yajl/platform.rb
|
157
160
|
- lib/ffi_yajl/version.rb
|
158
161
|
- spec/ffi_yajl/encoder_spec.rb
|
162
|
+
- spec/ffi_yajl/map_library_name_spec.rb
|
159
163
|
- spec/ffi_yajl/parser_spec.rb
|
160
164
|
- spec/spec_helper.rb
|
161
165
|
homepage: http://github.com/chef/ffi-yajl
|
@@ -178,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
178
182
|
version: '0'
|
179
183
|
requirements: []
|
180
184
|
rubyforge_project:
|
181
|
-
rubygems_version: 2.4.
|
185
|
+
rubygems_version: 2.4.6
|
182
186
|
signing_key:
|
183
187
|
specification_version: 4
|
184
188
|
summary: Ruby FFI wrapper around YAJL 2.x
|