yajl-ffi 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 +4 -4
- data/README.md +4 -4
- data/lib/yajl/ffi/builder.rb +9 -6
- data/lib/yajl/ffi/parser.rb +1 -1
- data/lib/yajl/ffi/version.rb +1 -1
- data/spec/parser_spec.rb +118 -13
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6de3c945368d22be36236e10320d4f352eb30d92
|
4
|
+
data.tar.gz: fb7fb82310439d20429da612ac5e134bfeb1e733
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42d060dadaf9bc2e0eea2e5ce7e218180b7bd6c483ae449ec4e8329d1da61bac9c85fd7c96a9ea374f49eca828fc967663f7caa0f43300bf458c4fe4a9567a4d
|
7
|
+
data.tar.gz: e0b43c9e8427a05d72f76e69e468baf69483e69fd0290571173b023a283c8f5ae7791b99fb36c6457ecd35a1be4346e5281063790a99bbe2cd6a17a539c7b8d6
|
data/README.md
CHANGED
@@ -158,10 +158,10 @@ several parsers. Here's a sample run.
|
|
158
158
|
```
|
159
159
|
$ rake benchmark
|
160
160
|
user system total real
|
161
|
-
json 0.
|
162
|
-
yajl-ruby 0.130000 0.
|
163
|
-
yajl-ffi 0.
|
164
|
-
json-stream
|
161
|
+
json 0.120000 0.010000 0.130000 ( 0.130072)
|
162
|
+
yajl-ruby 0.130000 0.000000 0.130000 ( 0.129388)
|
163
|
+
yajl-ffi 0.790000 0.010000 0.800000 ( 0.805279)
|
164
|
+
json-stream 7.500000 0.030000 7.530000 ( 7.524760)
|
165
165
|
```
|
166
166
|
|
167
167
|
Yajl::FFI is about 6x slower than the pure native parsers. JSON::Stream is a
|
data/lib/yajl/ffi/builder.rb
CHANGED
@@ -36,13 +36,15 @@ module Yajl
|
|
36
36
|
|
37
37
|
def end_object
|
38
38
|
return if @stack.size == 1
|
39
|
+
|
39
40
|
node = @stack.pop
|
41
|
+
top = @stack[-1]
|
40
42
|
|
41
|
-
case
|
43
|
+
case top
|
42
44
|
when Hash
|
43
|
-
|
45
|
+
top[@keys.pop] = node
|
44
46
|
when Array
|
45
|
-
|
47
|
+
top << node
|
46
48
|
end
|
47
49
|
end
|
48
50
|
alias :end_array :end_object
|
@@ -56,11 +58,12 @@ module Yajl
|
|
56
58
|
end
|
57
59
|
|
58
60
|
def value(value)
|
59
|
-
|
61
|
+
top = @stack[-1]
|
62
|
+
case top
|
60
63
|
when Hash
|
61
|
-
|
64
|
+
top[@keys.pop] = value
|
62
65
|
when Array
|
63
|
-
|
66
|
+
top << value
|
64
67
|
else
|
65
68
|
@stack << value
|
66
69
|
end
|
data/lib/yajl/ffi/parser.rb
CHANGED
@@ -287,7 +287,7 @@ module Yajl
|
|
287
287
|
#
|
288
288
|
# Returns a String.
|
289
289
|
def extract(pointer, length)
|
290
|
-
string = pointer.
|
290
|
+
string = pointer.get_bytes(0, length)
|
291
291
|
string.force_encoding(Encoding::UTF_8)
|
292
292
|
unless string.valid_encoding?
|
293
293
|
raise ParserError, 'Invalid UTF-8 byte sequence'
|
data/lib/yajl/ffi/version.rb
CHANGED
data/spec/parser_spec.rb
CHANGED
@@ -35,7 +35,15 @@ describe Yajl::FFI::Parser do
|
|
35
35
|
assert_equal expected, events('"test"')
|
36
36
|
end
|
37
37
|
|
38
|
-
it 'parses
|
38
|
+
it 'parses a single digit integer value document' do
|
39
|
+
expected = [:start_document, [:value, 2], :end_document]
|
40
|
+
events = events('2', subject)
|
41
|
+
assert events.empty?
|
42
|
+
subject.finish
|
43
|
+
assert_equal expected, events
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'parses a multiple digit integer value document' do
|
39
47
|
expected = [:start_document, [:value, 12], :end_document]
|
40
48
|
events = events('12', subject)
|
41
49
|
assert events.empty?
|
@@ -43,6 +51,30 @@ describe Yajl::FFI::Parser do
|
|
43
51
|
assert_equal expected, events
|
44
52
|
end
|
45
53
|
|
54
|
+
it 'parses a zero literal document' do
|
55
|
+
expected = [:start_document, [:value, 0], :end_document]
|
56
|
+
events = events('0', subject)
|
57
|
+
assert events.empty?
|
58
|
+
subject.finish
|
59
|
+
assert_equal expected, events
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'parses a negative integer document' do
|
63
|
+
expected = [:start_document, [:value, -1], :end_document]
|
64
|
+
events = events('-1', subject)
|
65
|
+
assert events.empty?
|
66
|
+
subject.finish
|
67
|
+
assert_equal expected, events
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'parses an exponent literal document' do
|
71
|
+
expected = [:start_document, [:value, 200.0], :end_document]
|
72
|
+
events = events('2e2', subject)
|
73
|
+
assert events.empty?
|
74
|
+
subject.finish
|
75
|
+
assert_equal expected, events
|
76
|
+
end
|
77
|
+
|
46
78
|
it 'parses a float value document' do
|
47
79
|
expected = [:start_document, [:value, 12.1], :end_document]
|
48
80
|
events = events('12.1', subject)
|
@@ -113,6 +145,13 @@ describe Yajl::FFI::Parser do
|
|
113
145
|
assert_equal expected, events('[fals1]')
|
114
146
|
end
|
115
147
|
|
148
|
+
it 'rejects scrambled keyword tokens' do
|
149
|
+
expected = [:start_document, :start_array, :error]
|
150
|
+
assert_equal expected, events('[ture]')
|
151
|
+
assert_equal expected, events('[fales]')
|
152
|
+
assert_equal expected, events('[nlul]')
|
153
|
+
end
|
154
|
+
|
116
155
|
it 'parses single keyword tokens' do
|
117
156
|
expected = [:start_document, :start_array, [:value, true], :end_array, :end_document]
|
118
157
|
assert_equal expected, events('[true]')
|
@@ -149,6 +188,36 @@ describe Yajl::FFI::Parser do
|
|
149
188
|
-> { subject.finish }.must_raise Yajl::FFI::ParserError
|
150
189
|
end
|
151
190
|
|
191
|
+
it 'rejects partial exponent' do
|
192
|
+
subject << '42e'
|
193
|
+
-> { subject.finish }.must_raise Yajl::FFI::ParserError
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'rejects malformed exponent' do
|
197
|
+
subject << '42e+'
|
198
|
+
-> { subject.finish }.must_raise Yajl::FFI::ParserError
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'rejects partial negative number' do
|
202
|
+
subject << '-'
|
203
|
+
-> { subject.finish }.must_raise Yajl::FFI::ParserError
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'rejects partial string literal' do
|
207
|
+
subject << '"test'
|
208
|
+
-> { subject.finish }.must_raise Yajl::FFI::ParserError
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'rejects partial object ending in literal value' do
|
212
|
+
subject << '{"test": 42'
|
213
|
+
-> { subject.finish }.must_raise Yajl::FFI::ParserError
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'rejects partial array ending in literal value' do
|
217
|
+
subject << '[42'
|
218
|
+
-> { subject.finish }.must_raise Yajl::FFI::ParserError
|
219
|
+
end
|
220
|
+
|
152
221
|
it 'does nothing on subsequent finish' do
|
153
222
|
begin
|
154
223
|
subject << 'false'
|
@@ -247,9 +316,34 @@ describe Yajl::FFI::Parser do
|
|
247
316
|
assert_equal expected, events('[12.]')
|
248
317
|
end
|
249
318
|
|
250
|
-
it 'parses positive exponent
|
251
|
-
expected = [:start_document, :start_array, [:value,
|
319
|
+
it 'parses zero with implicit positive exponent as float' do
|
320
|
+
expected = [:start_document, :start_array, [:value, 0.0], :end_array, :end_document]
|
321
|
+
events = events('[0e2]')
|
322
|
+
assert_equal expected, events
|
323
|
+
assert_kind_of Float, events[2][1]
|
324
|
+
end
|
325
|
+
|
326
|
+
it 'parses zero with explicit positive exponent as float' do
|
327
|
+
expected = [:start_document, :start_array, [:value, 0.0], :end_array, :end_document]
|
328
|
+
events = events('[0e+2]')
|
329
|
+
assert_equal expected, events
|
330
|
+
assert_kind_of Float, events[2][1]
|
331
|
+
end
|
332
|
+
|
333
|
+
it 'parses zero with negative exponent as float' do
|
334
|
+
expected = [:start_document, :start_array, [:value, 0.0], :end_array, :end_document]
|
335
|
+
events = events('[0e-2]')
|
336
|
+
assert_equal expected, events
|
337
|
+
assert_kind_of Float, events[2][1]
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'parses positive exponent integers as floats' do
|
341
|
+
expected = [:start_document, :start_array, [:value, 212.0], :end_array, :end_document]
|
342
|
+
|
343
|
+
events = events('[2.12e2]')
|
252
344
|
assert_equal expected, events('[2.12e2]')
|
345
|
+
assert_kind_of Float, events[2][1]
|
346
|
+
|
253
347
|
assert_equal expected, events('[2.12e02]')
|
254
348
|
assert_equal expected, events('[2.12e+2]')
|
255
349
|
assert_equal expected, events('[2.12e+02]')
|
@@ -452,11 +546,22 @@ describe Yajl::FFI::Parser do
|
|
452
546
|
end
|
453
547
|
|
454
548
|
describe 'parsing unicode escapes with surrogate pairs' do
|
549
|
+
it 'converts missing second pair to question mark' do
|
550
|
+
expected = [:start_document, :start_array, [:value, '?'], :end_array, :end_document]
|
551
|
+
assert_equal expected, events('["\uD834"]')
|
552
|
+
end
|
553
|
+
|
455
554
|
it 'rejects missing first pair' do
|
456
555
|
expected = [:start_document, :start_array, :error]
|
457
556
|
assert_equal expected, events('["\uDD1E"]')
|
458
557
|
end
|
459
558
|
|
559
|
+
it 'rejects double first pair' do
|
560
|
+
skip 'yajl incorrectly allows this'
|
561
|
+
expected = [:start_document, :start_array, :error]
|
562
|
+
assert_equal expected, events('["\uD834\uD834"]')
|
563
|
+
end
|
564
|
+
|
460
565
|
it 'rejects double second pair' do
|
461
566
|
expected = [:start_document, :start_array, :error]
|
462
567
|
assert_equal expected, events('["\uDD1E\uDD1E"]')
|
@@ -610,7 +715,7 @@ describe Yajl::FFI::Parser do
|
|
610
715
|
# is available. The \xC3 byte is the first byte of the é character.
|
611
716
|
it 'rejects a partial two byte utf-8 string' do
|
612
717
|
expected = [:start_document, :start_array, :error]
|
613
|
-
assert_equal expected, events(
|
718
|
+
assert_equal expected, events("[\"\xC3\"]")
|
614
719
|
end
|
615
720
|
|
616
721
|
it 'parses valid two byte utf-8 string' do
|
@@ -632,12 +737,12 @@ describe Yajl::FFI::Parser do
|
|
632
737
|
|
633
738
|
it 'rejects one byte of three byte utf-8 string' do
|
634
739
|
expected = [:start_document, :start_array, :error]
|
635
|
-
assert_equal expected, events(
|
740
|
+
assert_equal expected, events("[\"\xE2\"]")
|
636
741
|
end
|
637
742
|
|
638
743
|
it 'rejects two bytes of three byte utf-8 string' do
|
639
744
|
expected = [:start_document, :start_array, :error]
|
640
|
-
assert_equal expected, events(
|
745
|
+
assert_equal expected, events("[\"\xE2\x98\"]")
|
641
746
|
end
|
642
747
|
|
643
748
|
it 'parses full three byte utf-8 string' do
|
@@ -658,17 +763,17 @@ describe Yajl::FFI::Parser do
|
|
658
763
|
|
659
764
|
it 'rejects one byte of four byte utf-8 string' do
|
660
765
|
expected = [:start_document, :start_array, :error]
|
661
|
-
assert_equal expected, events(
|
766
|
+
assert_equal expected, events("[\"\xF0\"]")
|
662
767
|
end
|
663
768
|
|
664
769
|
it 'rejects two bytes of four byte utf-8 string' do
|
665
770
|
expected = [:start_document, :start_array, :error]
|
666
|
-
assert_equal expected, events(
|
771
|
+
assert_equal expected, events("[\"\xF0\x90\"]")
|
667
772
|
end
|
668
773
|
|
669
774
|
it 'rejects three bytes of four byte utf-8 string' do
|
670
775
|
expected = [:start_document, :start_array, :error]
|
671
|
-
assert_equal expected, events(
|
776
|
+
assert_equal expected, events("[\"\xF0\x90\x84\"]")
|
672
777
|
end
|
673
778
|
|
674
779
|
it 'parses full four byte utf-8 string' do
|
@@ -749,9 +854,9 @@ describe Yajl::FFI::Parser do
|
|
749
854
|
|
750
855
|
private
|
751
856
|
|
752
|
-
# Run a worst case, one
|
753
|
-
#
|
754
|
-
#
|
857
|
+
# Run a worst case, one byte at a time, parse against the JSON string and
|
858
|
+
# return a list of events generated by the parser. A special :error event is
|
859
|
+
# included if the parser threw an exception.
|
755
860
|
#
|
756
861
|
# json - The String to parse.
|
757
862
|
# parser - The optional Parser instance to use.
|
@@ -761,7 +866,7 @@ describe Yajl::FFI::Parser do
|
|
761
866
|
parser ||= Yajl::FFI::Parser.new
|
762
867
|
collector = Events.new(parser)
|
763
868
|
begin
|
764
|
-
json.
|
869
|
+
json.each_byte {|byte| parser << [byte].pack('C') }
|
765
870
|
rescue Yajl::FFI::ParserError
|
766
871
|
collector.error
|
767
872
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yajl-ffi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Graham
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|