From 5870d7d56915f312b57e5d7d019d8b982a734db0 Mon Sep 17 00:00:00 2001 From: Patrick Oscity Date: Thu, 19 Jun 2014 17:29:13 +0200 Subject: [PATCH 1/6] Fix typo --- ext/yajl/yajl_ext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/yajl/yajl_ext.c b/ext/yajl/yajl_ext.c index 25120100..31337ed6 100644 --- a/ext/yajl/yajl_ext.c +++ b/ext/yajl/yajl_ext.c @@ -462,7 +462,7 @@ static VALUE rb_yajl_parser_init(int argc, VALUE * argv, VALUE self) { * reading off of a socket directly. * * If a block was passed, it's called when an object has been parsed off the stream. This is especially - * usefull when parsing a stream of multiple JSON objects. + * useful when parsing a stream of multiple JSON objects. * * NOTE: you can optionally assign the +on_parse_complete+ callback, and it will be called the same way the optional * block is for this method. From 3468f09764bbfc9d78a0aa3b2016b55a9a0b76de Mon Sep 17 00:00:00 2001 From: Patrick Oscity Date: Thu, 19 Jun 2014 17:30:16 +0200 Subject: [PATCH 2/6] Fix indentation of comment --- ext/yajl/yajl_ext.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/yajl/yajl_ext.c b/ext/yajl/yajl_ext.c index 31337ed6..f8ed7a8c 100644 --- a/ext/yajl/yajl_ext.c +++ b/ext/yajl/yajl_ext.c @@ -573,16 +573,16 @@ static unsigned char * defaultIndentString = (unsigned char *)" "; * Document-method: new * * call-seq: initialize([:pretty => false[, :indent => ' '][, :terminator => "\n"]]) - * - * :pretty will enable/disable beautifying or "pretty priting" the output string. - * - * :indent is the character(s) used to indent the output string. - * - * :terminator allows you to specify a character to be used as the termination character after a full JSON string has been generated by - * the encoder. This would be especially useful when encoding in chunks (via a block or callback during the encode process), to be able to - * determine when the last chunk of the current encode is sent. - * If you specify this option to be nil, it will be ignored if encoding directly to an IO or simply returning a string. But if a block is used, - * the encoder will still pass it - I hope that makes sense ;). + * + * :pretty will enable/disable beautifying or "pretty priting" the output string. + * + * :indent is the character(s) used to indent the output string. + * + * :terminator allows you to specify a character to be used as the termination character after a full JSON string has been generated by + * the encoder. This would be especially useful when encoding in chunks (via a block or callback during the encode process), to be able to + * determine when the last chunk of the current encode is sent. + * If you specify this option to be nil, it will be ignored if encoding directly to an IO or simply returning a string. But if a block is used, + * the encoder will still pass it - I hope that makes sense ;). */ static VALUE rb_yajl_encoder_new(int argc, VALUE * argv, VALUE klass) { yajl_encoder_wrapper * wrapper; From 9ab456e1f29e6a685fb81ae91f704ff5a0238d84 Mon Sep 17 00:00:00 2001 From: Patrick Oscity Date: Thu, 19 Jun 2014 17:33:24 +0200 Subject: [PATCH 3/6] Call on_progress callback instead of calling passed block directly --- ext/yajl/yajl_ext.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/yajl/yajl_ext.c b/ext/yajl/yajl_ext.c index f8ed7a8c..7381b816 100644 --- a/ext/yajl/yajl_ext.c +++ b/ext/yajl/yajl_ext.c @@ -702,10 +702,10 @@ static VALUE rb_yajl_encoder_encode(int argc, VALUE * argv, VALUE self) { rb_io_write(io, wrapper->terminator); } return Qnil; - } else if (blk != Qnil) { - rb_funcall(blk, intern_call, 1, outBuff); + } else if (wrapper->on_progress_callback != Qnil) { + rb_funcall(wrapper->on_progress_callback, intern_call, 1, outBuff); if (wrapper->terminator != 0) { - rb_funcall(blk, intern_call, 1, wrapper->terminator); + rb_funcall(wrapper->on_progress_callback, intern_call, 1, wrapper->terminator); } return Qnil; } else { From d680c710e9f0180efbb489c5f20aa13652c0b4c1 Mon Sep 17 00:00:00 2001 From: Patrick Oscity Date: Thu, 19 Jun 2014 17:37:49 +0200 Subject: [PATCH 4/6] Allow setting on_parse_complete as block to Parser.new --- ext/yajl/yajl_ext.c | 13 ++++++++----- spec/parsing/chunked_spec.rb | 9 +++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/ext/yajl/yajl_ext.c b/ext/yajl/yajl_ext.c index 7381b816..072e91ee 100644 --- a/ext/yajl/yajl_ext.c +++ b/ext/yajl/yajl_ext.c @@ -389,22 +389,25 @@ static int yajl_found_end_array(void * ctx) { /* * Document-method: new * - * call-seq: new([:symbolize_keys => true, [:allow_comments => false[, :check_utf8 => false]]]) + * call-seq: new([:symbolize_keys => true, [:allow_comments => false[, :check_utf8 => false]]][, &callback]) * * :symbolize_keys will turn hash keys into Ruby symbols, defaults to false. * * :allow_comments will turn on/off the check for comments inside the JSON stream, defaults to true. * * :check_utf8 will validate UTF8 characters found in the JSON stream, defaults to true. + * + * If a block was passed, it's called when an object has been parsed off the stream. This is especially + * useful when parsing a stream of multiple JSON objects. */ static VALUE rb_yajl_parser_new(int argc, VALUE * argv, VALUE klass) { yajl_parser_wrapper * wrapper; yajl_parser_config cfg; - VALUE opts, obj; + VALUE opts, blk, obj; int allowComments = 1, checkUTF8 = 1, symbolizeKeys = 0; /* Scan off config vars */ - if (rb_scan_args(argc, argv, "01", &opts) == 1) { + if (rb_scan_args(argc, argv, "01&", &opts, &blk) == 1) { Check_Type(opts, T_HASH); if (rb_hash_aref(opts, sym_allow_comments) == Qfalse) { @@ -426,7 +429,7 @@ static VALUE rb_yajl_parser_new(int argc, VALUE * argv, VALUE klass) { wrapper->objectsFound = 0; wrapper->symbolizeKeys = symbolizeKeys; wrapper->builderStack = rb_ary_new(); - wrapper->parse_complete_callback = Qnil; + wrapper->parse_complete_callback = blk; rb_obj_call_init(obj, 0, 0); return obj; } @@ -434,7 +437,7 @@ static VALUE rb_yajl_parser_new(int argc, VALUE * argv, VALUE klass) { /* * Document-method: initialize * - * call-seq: new([:symbolize_keys => true, [:allow_comments => false[, :check_utf8 => false]]]) + * call-seq: new([:symbolize_keys => true, [:allow_comments => false[, :check_utf8 => false]]][, &callback]) * * :symbolize_keys will turn hash keys into Ruby symbols, defaults to false. * diff --git a/spec/parsing/chunked_spec.rb b/spec/parsing/chunked_spec.rb index 20248c9a..dd62de6c 100644 --- a/spec/parsing/chunked_spec.rb +++ b/spec/parsing/chunked_spec.rb @@ -13,6 +13,15 @@ @parser.on_parse_complete = @callback end + it "should take the callback as block parameter" do + @callback = lambda { |hash| + # no-op + } + @parser = Yajl::Parser.new(&@callback) + @callback.should_receive(:call).with(@final) + @parser << '[{"abc": 123},{"def": 456}]' + end + it "should parse a single chunk" do @callback.should_receive(:call).with(@final) @parser << '[{"abc": 123},{"def": 456}]' From f43b7c4b27156731e15741e30a8babcb0a0aa80e Mon Sep 17 00:00:00 2001 From: Patrick Oscity Date: Thu, 19 Jun 2014 17:39:08 +0200 Subject: [PATCH 5/6] Fix typo in call-seq documentation of Encoder.new --- ext/yajl/yajl_ext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/yajl/yajl_ext.c b/ext/yajl/yajl_ext.c index 072e91ee..bc587d8d 100644 --- a/ext/yajl/yajl_ext.c +++ b/ext/yajl/yajl_ext.c @@ -575,7 +575,7 @@ static unsigned char * defaultIndentString = (unsigned char *)" "; /* * Document-method: new * - * call-seq: initialize([:pretty => false[, :indent => ' '][, :terminator => "\n"]]) + * call-seq: new([:pretty => false[, :indent => ' '][, :terminator => "\n"]]) * * :pretty will enable/disable beautifying or "pretty priting" the output string. * From 0cb3512d76da9360d3dd5a44dff8ea8b02c2e825 Mon Sep 17 00:00:00 2001 From: Patrick Oscity Date: Thu, 19 Jun 2014 17:40:03 +0200 Subject: [PATCH 6/6] Allow setting on_progress_callback as block to Encoder.new --- ext/yajl/yajl_ext.c | 12 +++++++----- spec/encoding/encoding_spec.rb | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/ext/yajl/yajl_ext.c b/ext/yajl/yajl_ext.c index bc587d8d..678907ee 100644 --- a/ext/yajl/yajl_ext.c +++ b/ext/yajl/yajl_ext.c @@ -575,7 +575,7 @@ static unsigned char * defaultIndentString = (unsigned char *)" "; /* * Document-method: new * - * call-seq: new([:pretty => false[, :indent => ' '][, :terminator => "\n"]]) + * call-seq: new([:pretty => false[, :indent => ' '][, :terminator => "\n"]][, &callback]) * * :pretty will enable/disable beautifying or "pretty priting" the output string. * @@ -586,16 +586,18 @@ static unsigned char * defaultIndentString = (unsigned char *)" "; * determine when the last chunk of the current encode is sent. * If you specify this option to be nil, it will be ignored if encoding directly to an IO or simply returning a string. But if a block is used, * the encoder will still pass it - I hope that makes sense ;). + * + * If an optional block is passed, it's called when encoding is complete and passed the resulting JSON string */ static VALUE rb_yajl_encoder_new(int argc, VALUE * argv, VALUE klass) { yajl_encoder_wrapper * wrapper; yajl_gen_config cfg; - VALUE opts, obj, indent; + VALUE opts, blk, obj, indent; unsigned char *indentString = NULL, *actualIndent = NULL; int beautify = 0, htmlSafe = 0; /* Scan off config vars */ - if (rb_scan_args(argc, argv, "01", &opts) == 1) { + if (rb_scan_args(argc, argv, "01&", &opts, &blk) == 1) { Check_Type(opts, T_HASH); if (rb_hash_aref(opts, sym_pretty) == Qtrue) { @@ -624,7 +626,7 @@ static VALUE rb_yajl_encoder_new(int argc, VALUE * argv, VALUE klass) { obj = Data_Make_Struct(klass, yajl_encoder_wrapper, yajl_encoder_wrapper_mark, yajl_encoder_wrapper_free, wrapper); wrapper->indentString = actualIndent; wrapper->encoder = yajl_gen_alloc(&cfg, NULL); - wrapper->on_progress_callback = Qnil; + wrapper->on_progress_callback = blk; if (opts != Qnil && rb_funcall(opts, intern_has_key, 1, sym_terminator) == Qtrue) { wrapper->terminator = rb_hash_aref(opts, sym_terminator); #ifdef HAVE_RUBY_ENCODING_H @@ -642,7 +644,7 @@ static VALUE rb_yajl_encoder_new(int argc, VALUE * argv, VALUE klass) { /* * Document-method: initialize * - * call-seq: initialize([:pretty => false[, :indent => ' '][, :terminator => "\n"]]) + * call-seq: initialize([:pretty => false[, :indent => ' '][, :terminator => "\n"]][, &callback]) * * :pretty will enable/disable beautifying or "pretty priting" the output string. * diff --git a/spec/encoding/encoding_spec.rb b/spec/encoding/encoding_spec.rb index 818f028b..2fc1bb3c 100644 --- a/spec/encoding/encoding_spec.rb +++ b/spec/encoding/encoding_spec.rb @@ -132,6 +132,25 @@ def to_s output.should == output end + it "should encode with a callback passed via on_progress" do + callback = lambda { |str| + # no-op + } + encoder = Yajl::Encoder.new + encoder.on_progress = callback + callback.should_receive(:call).with('{}') + encoder.encode({}) + end + + it "should encode with a callback passed as block" do + callback = lambda { |str| + # no-op + } + encoder = Yajl::Encoder.new(&callback) + callback.should_receive(:call).with('{}') + encoder.encode({}) + end + it "should encode with it's class method with :pretty and a tab character indent options set, to an IO" do output = "{\n\t\"foo\": 1234\n}" obj = {:foo => 1234}