ruby-jq 0.1.1 → 0.1.2
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 +8 -8
- data/ext/jq_core.c +32 -22
- data/ext/jq_core.h +1 -0
- data/lib/jq/parser.rb +10 -4
- data/lib/jq/version.rb +1 -1
- data/spec/jq_spec.rb +116 -0
- data/spec/spec_helper.rb +1 -0
- metadata +1 -1
    
        checksums.yaml
    CHANGED
    
    | @@ -1,15 +1,15 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            !binary "U0hBMQ==":
         | 
| 3 3 | 
             
              metadata.gz: !binary |-
         | 
| 4 | 
            -
                 | 
| 4 | 
            +
                OTUzMDNjM2E5MDlmYzBlZWNkZjYwOTJiN2M3MzcyZmZlYzNhZDQxZA==
         | 
| 5 5 | 
             
              data.tar.gz: !binary |-
         | 
| 6 | 
            -
                 | 
| 6 | 
            +
                MDUyMzQ0MjBiMjcxZjU0MWRiYWExOTA2ODljN2IwZTY1MTUyZTM2ZQ==
         | 
| 7 7 | 
             
            SHA512:
         | 
| 8 8 | 
             
              metadata.gz: !binary |-
         | 
| 9 | 
            -
                 | 
| 10 | 
            -
                 | 
| 11 | 
            -
                 | 
| 9 | 
            +
                NGVlNTM5MGRkZDg2ODI1ZjljY2JlMTI2OWQwZjE2ODczMmE4NzVhNDViOTA5
         | 
| 10 | 
            +
                MDBlMDcxMjA4NWI2MzRlYWUwYmUwZDE2OGQ5MTk5MjgyY2M5NjU2NzlhMWU2
         | 
| 11 | 
            +
                YzZhMzdhNWM2NGU3MTAxZTZlMjEyMzIyZTJjNmQxYTlkOTAzNTM=
         | 
| 12 12 | 
             
              data.tar.gz: !binary |-
         | 
| 13 | 
            -
                 | 
| 14 | 
            -
                 | 
| 15 | 
            -
                 | 
| 13 | 
            +
                ZTRhMWFjZjQxZGFjNzEzZDBmY2FmMTNiYjAzNzQ1YjQwYjMxY2RiZjU1Y2Yz
         | 
| 14 | 
            +
                YjI2YTMwMzNlMDcyNjliZmVjYzg2OGQwNDFkZTg2OWRiNWE4NjI2MDAwODcz
         | 
| 15 | 
            +
                N2QzZGYzZTYwNjNiOTJhNTAxM2Q3MzMxNTg4NWRhMzdlODM0OWI=
         | 
    
        data/ext/jq_core.c
    CHANGED
    
    | @@ -10,6 +10,7 @@ static VALUE rb_jq_alloc(VALUE klass) { | |
| 10 10 | 
             
              struct jq_container *p;
         | 
| 11 11 | 
             
              p = ALLOC(struct jq_container);
         | 
| 12 12 | 
             
              p->jq = NULL;
         | 
| 13 | 
            +
              p->parser = NULL;
         | 
| 13 14 | 
             
              p->closed = 1;
         | 
| 14 15 | 
             
              return Data_Wrap_Struct(klass, 0, rb_jq_free, p);
         | 
| 15 16 | 
             
            }
         | 
| @@ -35,6 +36,7 @@ static VALUE rb_jq_initialize(VALUE self, VALUE program) { | |
| 35 36 | 
             
              }
         | 
| 36 37 |  | 
| 37 38 | 
             
              p->jq = jq;
         | 
| 39 | 
            +
              p->parser = NULL;
         | 
| 38 40 | 
             
              p->closed = 0;
         | 
| 39 41 |  | 
| 40 42 | 
             
              return Qnil;
         | 
| @@ -46,6 +48,8 @@ static VALUE rb_jq_close(VALUE self) { | |
| 46 48 |  | 
| 47 49 | 
             
              if (!p->closed) {
         | 
| 48 50 | 
             
                jq_teardown(&p->jq);
         | 
| 51 | 
            +
                p->jq = NULL;
         | 
| 52 | 
            +
                p->parser = NULL;
         | 
| 49 53 | 
             
                p->closed = 1;
         | 
| 50 54 | 
             
              }
         | 
| 51 55 |  | 
| @@ -65,40 +69,27 @@ static void jq_process(jq_state *jq, jv value, VALUE (*proc)(), int *status) { | |
| 65 69 | 
             
              jv_free(result);
         | 
| 66 70 | 
             
            }
         | 
| 67 71 |  | 
| 68 | 
            -
            static void jq_parse(jq_state *jq,  | 
| 69 | 
            -
              struct jv_parser* parser = jv_parser_new();
         | 
| 72 | 
            +
            static void jq_parse(jq_state *jq, struct jv_parser *parser, VALUE (*proc)(), int *status, VALUE *errmsg) {
         | 
| 70 73 | 
             
              jv value;
         | 
| 71 | 
            -
              int status = 0, error = 0;
         | 
| 72 | 
            -
              VALUE errmsg;
         | 
| 73 74 |  | 
| 74 | 
            -
               | 
| 75 | 
            -
             | 
| 76 | 
            -
              while (jv_is_valid((value = jv_parser_next(parser))) && status == 0) {
         | 
| 77 | 
            -
                jq_process(jq, value, proc, &status);
         | 
| 75 | 
            +
              while (jv_is_valid((value = jv_parser_next(parser))) && *status == 0) {
         | 
| 76 | 
            +
                jq_process(jq, value, proc, status);
         | 
| 78 77 | 
             
              }
         | 
| 79 78 |  | 
| 80 79 | 
             
              if (jv_invalid_has_msg(jv_copy(value))) {
         | 
| 81 80 | 
             
                jv msg = jv_invalid_get_msg(value);
         | 
| 82 | 
            -
                 | 
| 83 | 
            -
                errmsg = rb_str_new2(jv_string_value(msg));
         | 
| 81 | 
            +
                *errmsg = rb_str_new2(jv_string_value(msg));
         | 
| 84 82 | 
             
                jv_free(msg);
         | 
| 85 83 | 
             
              } else {
         | 
| 86 84 | 
             
                jv_free(value);
         | 
| 87 85 | 
             
              }
         | 
| 88 | 
            -
             | 
| 89 | 
            -
              jv_parser_free(parser);
         | 
| 90 | 
            -
             | 
| 91 | 
            -
              if (status != 0) {
         | 
| 92 | 
            -
                rb_jump_tag(status);
         | 
| 93 | 
            -
              }
         | 
| 94 | 
            -
             | 
| 95 | 
            -
              if (error) {
         | 
| 96 | 
            -
                rb_raise(rb_eJQ_Error, "%s", RSTRING_PTR(errmsg));
         | 
| 97 | 
            -
              }
         | 
| 98 86 | 
             
            }
         | 
| 99 87 |  | 
| 100 | 
            -
            static VALUE rb_jq_update(VALUE self, VALUE buf, VALUE  | 
| 88 | 
            +
            static VALUE rb_jq_update(VALUE self, VALUE buf, VALUE v_is_partial) {
         | 
| 101 89 | 
             
              struct jq_container *p;
         | 
| 90 | 
            +
              int is_partial = v_is_partial ? 1 : 0;
         | 
| 91 | 
            +
              int status = 0;
         | 
| 92 | 
            +
              VALUE errmsg = Qnil;
         | 
| 102 93 |  | 
| 103 94 | 
             
              if (!rb_block_given_p()) {
         | 
| 104 95 | 
             
                rb_raise(rb_eArgError, "no block given");
         | 
| @@ -106,7 +97,26 @@ static VALUE rb_jq_update(VALUE self, VALUE buf, VALUE is_partial) { | |
| 106 97 |  | 
| 107 98 | 
             
              Data_Get_Struct(self, struct jq_container, p);
         | 
| 108 99 | 
             
              Check_Type(buf, T_STRING);
         | 
| 109 | 
            -
             | 
| 100 | 
            +
             | 
| 101 | 
            +
              if (!p->parser) {
         | 
| 102 | 
            +
                p->parser = jv_parser_new();
         | 
| 103 | 
            +
              }
         | 
| 104 | 
            +
             | 
| 105 | 
            +
              jv_parser_set_buf(p->parser, RSTRING_PTR(buf), RSTRING_LEN(buf), is_partial);
         | 
| 106 | 
            +
              jq_parse(p->jq, p->parser, rb_yield, &status, &errmsg);
         | 
| 107 | 
            +
             | 
| 108 | 
            +
              if (!is_partial) {
         | 
| 109 | 
            +
                jv_parser_free(p->parser);
         | 
| 110 | 
            +
                p->parser = NULL;
         | 
| 111 | 
            +
              }
         | 
| 112 | 
            +
             | 
| 113 | 
            +
              if (status != 0) {
         | 
| 114 | 
            +
                rb_jump_tag(status);
         | 
| 115 | 
            +
              }
         | 
| 116 | 
            +
             | 
| 117 | 
            +
              if (!NIL_P(errmsg)) {
         | 
| 118 | 
            +
                rb_raise(rb_eJQ_Error, "%s", RSTRING_PTR(errmsg));
         | 
| 119 | 
            +
              }
         | 
| 110 120 |  | 
| 111 121 | 
             
              return Qnil;
         | 
| 112 122 | 
             
            }
         | 
    
        data/ext/jq_core.h
    CHANGED
    
    
    
        data/lib/jq/parser.rb
    CHANGED
    
    | @@ -1,18 +1,20 @@ | |
| 1 1 | 
             
            require 'jq_core'
         | 
| 2 2 | 
             
            require 'json'
         | 
| 3 | 
            +
            require 'tempfile'
         | 
| 4 | 
            +
            require 'stringio'
         | 
| 3 5 |  | 
| 4 6 | 
             
            class JQ::Parser
         | 
| 5 7 | 
             
              BUFSIZ = 4096
         | 
| 6 8 |  | 
| 7 9 | 
             
              def initialize(src, options = {})
         | 
| 8 | 
            -
                @src =  | 
| 10 | 
            +
                @src = kind_of_io?(src) ? src : src.to_s
         | 
| 9 11 | 
             
                @options = {
         | 
| 10 12 | 
             
                  :parse_json => true,
         | 
| 11 13 | 
             
                }.merge(options)
         | 
| 12 14 | 
             
              end
         | 
| 13 15 |  | 
| 14 16 | 
             
              def search(program, &block)
         | 
| 15 | 
            -
                @src.rewind if @src | 
| 17 | 
            +
                @src.rewind if kind_of_io?(@src)
         | 
| 16 18 | 
             
                retval = nil
         | 
| 17 19 |  | 
| 18 20 | 
             
                if block
         | 
| @@ -30,9 +32,9 @@ class JQ::Parser | |
| 30 32 | 
             
                end
         | 
| 31 33 |  | 
| 32 34 | 
             
                jq(program) do |jq_core|
         | 
| 33 | 
            -
                  if @src | 
| 35 | 
            +
                  if kind_of_io?(@src)
         | 
| 34 36 | 
             
                    while buf = @src.read(BUFSIZ)
         | 
| 35 | 
            -
                      jq_core.update(buf,  | 
| 37 | 
            +
                      jq_core.update(buf, !@src.eof?, &block)
         | 
| 36 38 | 
             
                    end
         | 
| 37 39 | 
             
                  else
         | 
| 38 40 | 
             
                    jq_core.update(@src, false, &block)
         | 
| @@ -61,4 +63,8 @@ class JQ::Parser | |
| 61 63 | 
             
                  str
         | 
| 62 64 | 
             
                end
         | 
| 63 65 | 
             
              end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              def kind_of_io?(obj)
         | 
| 68 | 
            +
                [IO, Tempfile, StringIO].any? {|c| obj.kind_of?(c) }
         | 
| 69 | 
            +
              end
         | 
| 64 70 | 
             
            end
         | 
    
        data/lib/jq/version.rb
    CHANGED
    
    
    
        data/spec/jq_spec.rb
    CHANGED
    
    | @@ -92,6 +92,114 @@ describe JQ do | |
| 92 92 | 
             
                end
         | 
| 93 93 | 
             
              end
         | 
| 94 94 |  | 
| 95 | 
            +
              it 'read from file' do
         | 
| 96 | 
            +
                Tempfile.open("ruby-jq.spec.#{$$}") do |src|
         | 
| 97 | 
            +
                  src.puts(<<-EOS)
         | 
| 98 | 
            +
            {
         | 
| 99 | 
            +
                "glossary": {
         | 
| 100 | 
            +
                    "title": "example glossary",
         | 
| 101 | 
            +
                "GlossDiv": {
         | 
| 102 | 
            +
                        "title": "S",
         | 
| 103 | 
            +
                  "GlossList": {
         | 
| 104 | 
            +
                            "GlossEntry": {
         | 
| 105 | 
            +
                                "ID": "SGML",
         | 
| 106 | 
            +
                      "SortAs": "SGML",
         | 
| 107 | 
            +
                      "GlossTerm": "Standard Generalized Markup Language",
         | 
| 108 | 
            +
                      "Acronym": "SGML",
         | 
| 109 | 
            +
                      "Abbrev": "ISO 8879:1986",
         | 
| 110 | 
            +
                      "GlossDef": {
         | 
| 111 | 
            +
                                    "para": "A meta-markup language, used to create markup languages such as DocBook.",
         | 
| 112 | 
            +
                        "GlossSeeAlso": ["GML", "XML"]
         | 
| 113 | 
            +
                                },
         | 
| 114 | 
            +
                      "GlossSee": "markup"
         | 
| 115 | 
            +
                            }
         | 
| 116 | 
            +
                        }
         | 
| 117 | 
            +
                    }
         | 
| 118 | 
            +
                }
         | 
| 119 | 
            +
            }
         | 
| 120 | 
            +
                  EOS
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                  expected = {
         | 
| 123 | 
            +
                    "glossary"=>
         | 
| 124 | 
            +
                      {"GlossDiv"=>
         | 
| 125 | 
            +
                        {"GlossList"=>
         | 
| 126 | 
            +
                          {"GlossEntry"=>
         | 
| 127 | 
            +
                            {"GlossSee"=>"markup",
         | 
| 128 | 
            +
                             "GlossDef"=>
         | 
| 129 | 
            +
                              {"GlossSeeAlso"=>["GML", "XML"],
         | 
| 130 | 
            +
                               "para"=>
         | 
| 131 | 
            +
                                "A meta-markup language, used to create markup languages such as DocBook."},
         | 
| 132 | 
            +
                             "Abbrev"=>"ISO 8879:1986",
         | 
| 133 | 
            +
                             "Acronym"=>"SGML",
         | 
| 134 | 
            +
                             "GlossTerm"=>"Standard Generalized Markup Language",
         | 
| 135 | 
            +
                             "SortAs"=>"SGML",
         | 
| 136 | 
            +
                             "ID"=>"SGML"}},
         | 
| 137 | 
            +
                         "title"=>"S"},
         | 
| 138 | 
            +
                       "title"=>"example glossary"}}
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                  expect(JQ(src).search('.')).to eq([expected])
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  JQ(src).search('.') do |value|
         | 
| 143 | 
            +
                    expect(value).to eq(expected)
         | 
| 144 | 
            +
                  end
         | 
| 145 | 
            +
                end
         | 
| 146 | 
            +
              end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
              it 'read from file (> 4096)' do
         | 
| 149 | 
            +
                Tempfile.open("ruby-jq.spec.#{$$}") do |src|
         | 
| 150 | 
            +
                  src.puts('[' + (1..10).map { (<<-EOS) }.join(',') + ']')
         | 
| 151 | 
            +
            {
         | 
| 152 | 
            +
                "glossary": {
         | 
| 153 | 
            +
                    "title": "example glossary",
         | 
| 154 | 
            +
                "GlossDiv": {
         | 
| 155 | 
            +
                        "title": "S",
         | 
| 156 | 
            +
                  "GlossList": {
         | 
| 157 | 
            +
                            "GlossEntry": {
         | 
| 158 | 
            +
                                "ID": "SGML",
         | 
| 159 | 
            +
                      "SortAs": "SGML",
         | 
| 160 | 
            +
                      "GlossTerm": "Standard Generalized Markup Language",
         | 
| 161 | 
            +
                      "Acronym": "SGML",
         | 
| 162 | 
            +
                      "Abbrev": "ISO 8879:1986",
         | 
| 163 | 
            +
                      "GlossDef": {
         | 
| 164 | 
            +
                                    "para": "A meta-markup language, used to create markup languages such as DocBook.",
         | 
| 165 | 
            +
                        "GlossSeeAlso": ["GML", "XML"]
         | 
| 166 | 
            +
                                },
         | 
| 167 | 
            +
                      "GlossSee": "markup"
         | 
| 168 | 
            +
                            }
         | 
| 169 | 
            +
                        }
         | 
| 170 | 
            +
                    }
         | 
| 171 | 
            +
                }
         | 
| 172 | 
            +
            }
         | 
| 173 | 
            +
                  EOS
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                  expected = (1..10).map do
         | 
| 176 | 
            +
                    {
         | 
| 177 | 
            +
                      "glossary"=>
         | 
| 178 | 
            +
                        {"GlossDiv"=>
         | 
| 179 | 
            +
                          {"GlossList"=>
         | 
| 180 | 
            +
                            {"GlossEntry"=>
         | 
| 181 | 
            +
                              {"GlossSee"=>"markup",
         | 
| 182 | 
            +
                               "GlossDef"=>
         | 
| 183 | 
            +
                                {"GlossSeeAlso"=>["GML", "XML"],
         | 
| 184 | 
            +
                                 "para"=>
         | 
| 185 | 
            +
                                  "A meta-markup language, used to create markup languages such as DocBook."},
         | 
| 186 | 
            +
                               "Abbrev"=>"ISO 8879:1986",
         | 
| 187 | 
            +
                               "Acronym"=>"SGML",
         | 
| 188 | 
            +
                               "GlossTerm"=>"Standard Generalized Markup Language",
         | 
| 189 | 
            +
                               "SortAs"=>"SGML",
         | 
| 190 | 
            +
                               "ID"=>"SGML"}},
         | 
| 191 | 
            +
                           "title"=>"S"},
         | 
| 192 | 
            +
                         "title"=>"example glossary"}}
         | 
| 193 | 
            +
                  end
         | 
| 194 | 
            +
             | 
| 195 | 
            +
                  expect(JQ(src).search('.')).to eq([expected])
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                  JQ(src).search('.') do |value|
         | 
| 198 | 
            +
                    expect(value).to eq(expected)
         | 
| 199 | 
            +
                  end
         | 
| 200 | 
            +
                end
         | 
| 201 | 
            +
              end
         | 
| 202 | 
            +
             | 
| 95 203 | 
             
              it 'parse_json => false' do
         | 
| 96 204 | 
             
                src = <<-EOS
         | 
| 97 205 | 
             
            {
         | 
| @@ -150,4 +258,12 @@ describe JQ do | |
| 150 258 | 
             
                  JQ('{}').search('...')
         | 
| 151 259 | 
             
                }.to raise_error(JQ::Error)
         | 
| 152 260 | 
             
              end
         | 
| 261 | 
            +
             | 
| 262 | 
            +
              it 'runtime error' do
         | 
| 263 | 
            +
                expect {
         | 
| 264 | 
            +
                  JQ('{}').search('.') do |value|
         | 
| 265 | 
            +
                    raise 'runtime error'
         | 
| 266 | 
            +
                  end
         | 
| 267 | 
            +
                }.to raise_error(RuntimeError)
         | 
| 268 | 
            +
              end
         | 
| 153 269 | 
             
            end
         | 
    
        data/spec/spec_helper.rb
    CHANGED