diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cdc4837..f601c331 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 3.16.5 - 2024-07-07 + +- Fixed Oj::Parser so that block procedures work correctly. + ## 3.16.4 - 2024-06-08 - Fixed Oj::Parse EOF issue on larger stream input. diff --git a/ext/oj/usual.c b/ext/oj/usual.c index e6160f9a..d6296e0b 100644 --- a/ext/oj/usual.c +++ b/ext/oj/usual.c @@ -289,9 +289,14 @@ static void close_object(ojParser p) { } rb_hash_bulk_insert(d->vtail - head, head, obj); d->ktail = d->khead + c->ki; + d->vtail = head; head--; *head = obj; + if (1 == d->vtail - d->vhead && rb_block_given_p()) { + d->vtail = d->vhead; + rb_yield(obj); + } } static void close_object_class(ojParser p) { @@ -572,7 +577,18 @@ static VALUE result(ojParser p) { Usual d = (Usual)p->ctx; if (d->vhead < d->vtail) { - return *d->vhead; + long cnt = d->vtail - d->vhead; + volatile VALUE ary; + volatile VALUE *vp; + + if (1 == cnt) { + return *d->vhead; + } + ary = rb_ary_new(); + for (vp = d->vhead; vp < d->vtail; vp++) { + rb_ary_push(ary, *vp); + } + return ary; } if (d->raise_on_empty) { rb_raise(oj_parse_error_class, "empty string"); diff --git a/lib/oj/version.rb b/lib/oj/version.rb index 15bf90ba..4ffbcdec 100644 --- a/lib/oj/version.rb +++ b/lib/oj/version.rb @@ -1,4 +1,4 @@ module Oj # Current version of the module. - VERSION = '3.16.4' + VERSION = '3.16.5' end diff --git a/test/test_parser_usual.rb b/test/test_parser_usual.rb index f9b620c2..e327e049 100755 --- a/test/test_parser_usual.rb +++ b/test/test_parser_usual.rb @@ -114,6 +114,30 @@ def test_decimal assert_equal(Float, doc.class) end + def test_multi_parse + p = Oj::Parser.new(:usual) + out = [] + p.parse('{"a":1}{"b":{"x":2}} {"c":3}') { |j| out.push(j) } + assert_equal([{'a'=>1}, {'b'=>{'x'=>2}},{'c'=>3}], out) + end + + def test_multi_load + p = Oj::Parser.new(:usual) + out = [] + r, w = IO.pipe + thread = Thread.new do + ['{"a":1}', '{"b":{"x"', ':2}}{"c":', '3}'].each { |seg| + w.write(seg) + sleep(0.1) + } + w.close + end + p.load(r) { |j| out.push(j) } + r.close + thread.join + assert_equal([{'a'=>1}, {'b'=>{'x'=>2}},{'c'=>3}], out) + end + def test_omit_null p = Oj::Parser.new(:usual) p.omit_null = true