summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2014-06-14 16:50:46 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2014-06-14 16:50:46 -0700
commit8f640b6d665926c6687d6138c8f6485b43c3a857 (patch)
tree1d5046f068b8bcbb19b839b61ba5d3b357302e5a
parent4d056c20768cb8e5a8169ee5d6bf46fc82e19f19 (diff)
downloadffi-yajl-8f640b6d665926c6687d6138c8f6485b43c3a857.tar.gz
support yajl parser options
-rw-r--r--ext/ffi_yajl/ext/parser/parser.c14
-rw-r--r--lib/ffi_yajl/ffi/parser.rb12
-rw-r--r--lib/ffi_yajl/parser.rb13
-rw-r--r--spec/ffi_yajl/parser_spec.rb108
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