diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2014-06-14 16:50:46 -0700 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2014-06-14 16:50:46 -0700 |
commit | 8f640b6d665926c6687d6138c8f6485b43c3a857 (patch) | |
tree | 1d5046f068b8bcbb19b839b61ba5d3b357302e5a | |
parent | 4d056c20768cb8e5a8169ee5d6bf46fc82e19f19 (diff) | |
download | ffi-yajl-8f640b6d665926c6687d6138c8f6485b43c3a857.tar.gz |
support yajl parser options
-rw-r--r-- | ext/ffi_yajl/ext/parser/parser.c | 14 | ||||
-rw-r--r-- | lib/ffi_yajl/ffi/parser.rb | 12 | ||||
-rw-r--r-- | lib/ffi_yajl/parser.rb | 13 | ||||
-rw-r--r-- | spec/ffi_yajl/parser_spec.rb | 108 |
4 files changed, 140 insertions, 7 deletions
diff --git a/ext/ffi_yajl/ext/parser/parser.c b/ext/ffi_yajl/ext/parser/parser.c index 5100e2d..e2481cd 100644 --- a/ext/ffi_yajl/ext/parser/parser.c +++ b/ext/ffi_yajl/ext/parser/parser.c @@ -186,9 +186,21 @@ static VALUE mParser_do_yajl_parse(VALUE self, VALUE str, VALUE yajl_opts) { hand = yajl_alloc(&callbacks, NULL, (void *)&ctx); - if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_comments")))) { + if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_comments"))) == Qtrue) { yajl_config(hand, yajl_allow_comments, 1); } + if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_dont_validate_strings"))) == Qtrue) { + yajl_config(hand, yajl_dont_validate_strings, 1); + } + if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_trailing_garbage"))) == Qtrue) { + yajl_config(hand, yajl_allow_trailing_garbage, 1); + } + if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_multiple_values"))) == Qtrue) { + yajl_config(hand, yajl_allow_multiple_values, 1); + } + if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_partial_values"))) == Qtrue) { + yajl_config(hand, yajl_allow_partial_values, 1); + } if ((stat = yajl_parse(hand, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str))) != yajl_status_ok) { err = yajl_get_error(hand, 1, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str)); diff --git a/lib/ffi_yajl/ffi/parser.rb b/lib/ffi_yajl/ffi/parser.rb index cc454f0..7c1dbbc 100644 --- a/lib/ffi_yajl/ffi/parser.rb +++ b/lib/ffi_yajl/ffi/parser.rb @@ -115,6 +115,18 @@ module FFI_Yajl if yajl_opts[:yajl_allow_comments] ::FFI_Yajl.yajl_config(yajl_handle, :yajl_allow_comments, :int, 1) end + if yajl_opts[:yajl_dont_validate_strings] + ::FFI_Yajl.yajl_config(yajl_handle, :yajl_dont_validate_strings, :int, 1) + end + if yajl_opts[:yajl_allow_trailing_garbage] + ::FFI_Yajl.yajl_config(yajl_handle, :yajl_allow_trailing_garbage, :int, 1) + end + if yajl_opts[:yajl_allow_multiple_values] + ::FFI_Yajl.yajl_config(yajl_handle, :yajl_allow_multiple_values, :int, 1) + end + if yajl_opts[:yajl_allow_partial_values] + ::FFI_Yajl.yajl_config(yajl_handle, :yajl_allow_partial_values, :int, 1) + end if ( stat = ::FFI_Yajl.yajl_parse(yajl_handle, str, str.bytesize) != :yajl_status_ok ) # FIXME: dup the error and call yajl_free_error? diff --git a/lib/ffi_yajl/parser.rb b/lib/ffi_yajl/parser.rb index f1b9625..0f44477 100644 --- a/lib/ffi_yajl/parser.rb +++ b/lib/ffi_yajl/parser.rb @@ -34,7 +34,18 @@ module FFI_Yajl # initialization that we can do in pure ruby yajl_opts = {} - yajl_opts[:yajl_allow_comments] = @opts[:allow_comments] + if @opts[:check_utf8] == false && @opts[:dont_validate_strings] == false + raise ArgumentError, "options check_utf8 and dont_validate_strings are both false which conflict" + end + if @opts[:check_utf8] == true && @opts[:dont_validate_strings] == true + raise ArgumentError, "options check_utf8 and dont_validate_strings are both true which conflict" + end + + yajl_opts[:yajl_allow_comments] = @opts[:allow_comments] + yajl_opts[:yajl_dont_validate_strings] = (@opts[:check_utf8] == false || @opts[:dont_validate_strings]) + yajl_opts[:yajl_allow_trailing_garbage] = @opts[:allow_trailing_garbage] + yajl_opts[:yajl_allow_multiple_values] = @opts[:allow_multiple_values] + yajl_opts[:yajl_allow_partial_values] = @opts[:allow_partial_values] # XXX: bug-compat with ruby-yajl return nil if str == "" diff --git a/spec/ffi_yajl/parser_spec.rb b/spec/ffi_yajl/parser_spec.rb index 0ce848f..4f6186e 100644 --- a/spec/ffi_yajl/parser_spec.rb +++ b/spec/ffi_yajl/parser_spec.rb @@ -35,24 +35,114 @@ describe "FFI_Yajl::Parser" do end end + context "when json has multiline comments" do + let(:json) { %Q{{"key": \n/*\n this is a multiline comment \n*/\n "value"}} } + + context "when allow_comments is false" do + let(:options) { { :allow_comments => false } } + + it "should not parse" do + expect{parser}.to raise_error(FFI_Yajl::ParseError) + end + end + + context "when allow_comments is true" do + let(:options) { { :allow_comments => true } } + + it "should parse" do + expect(parser).to eq({"key"=>"value"}) + end + end + end + + context "when json has inline comments" do + let(:json) { %Q{{"key": \n// this is an inline comment\n "value"}} } + + context "when allow_comments is false" do + let(:options) { { :allow_comments => false } } + + it "should not parse" do + expect{parser}.to raise_error(FFI_Yajl::ParseError) + end + end + + context "when allow_comments is true" do + let(:options) { { :allow_comments => true } } + + it "should parse" do + expect(parser).to eq({"key"=>"value"}) + end + end + end + context "when json is invalid UTF8" do let(:json) { "[\"#{"\201\203"}\"]" } + it "should not parse by default" do + expect{parser}.to raise_error(FFI_Yajl::ParseError) + end + + context "when :dont_validate_strings is set to true" do + let(:options) { { :dont_validate_strings => true } } + + it "should parse" do + expect(parser).to eq(["\x81\x83"]) + end + end + + context "when :dont_validate_strings is set to false" do + let(:options) { { :dont_validate_strings => false } } + + it "should not parse" do + expect{parser}.to raise_error(FFI_Yajl::ParseError) + end + end + context "when :check_utf8 is set to true" do let(:options) { { :check_utf8 => true } } it "should not parse" do - skip "implement :check_utf8" expect{parser}.to raise_error(FFI_Yajl::ParseError) end + + context "when :dont_validate_strings is set to true" do + let(:options) { { :check_utf8 => true, :dont_validate_strings => true } } + + it "should raise an ArgumentError" do + expect{parser}.to raise_error(ArgumentError) + end + end + + context "when :dont_validate_strings is set to false" do + let(:options) { { :check_utf8 => true, :dont_validate_strings => false } } + + it "should not parse" do + expect{parser}.to raise_error(FFI_Yajl::ParseError) + end + end end context "when :check_utf8 is set to false" do let(:options) { { :check_utf8 => false } } it "should parse" do - skip "implement :check_utf8" - expect(parser).to eq({}) # FIXME + expect(parser).to eq(["\x81\x83"]) + end + + context "when :dont_validate_strings is set to true" do + let(:options) { { :check_utf8 => false, :dont_validate_strings => true } } + + it "should parse" do + expect(parser).to eq(["\x81\x83"]) + end + end + + context "when :dont_validate_strings is set to false" do + let(:options) { { :check_utf8 => false, :dont_validate_strings => false } } + + it "should raise an ArgumentError" do + expect{parser}.to raise_error(ArgumentError) + end end end end @@ -194,7 +284,7 @@ describe "FFI_Yajl::Parser" do # NOTE: this fixes yajl-ruby being too permissive context "when dealing with too much or too little input" do context "when trailing braces are missing" do - let(:json) { '{{"foo": 1234}' } + let(:json) { '{"foo":{"foo": 1234}' } it "raises an exception" do expect { parser }.to raise_error(FFI_Yajl::ParseError) @@ -210,11 +300,19 @@ describe "FFI_Yajl::Parser" do end context "when an extra brace is present" do - let(:json) { '{{"foo": 1234}}}' } + let(:json) { '{"foo":{"foo": 1234}}}' } it "raises an exception" do expect { parser }.to raise_error(FFI_Yajl::ParseError) end + + context "with allow_trailing_garbage" do + let(:options) { { :allow_trailing_garbage => true } } + it "parses" do + expect(parser).to eq({"foo"=>{"foo"=>1234}}) + end + end + end context "when an extra bracket is present" do |