yajl-ffi 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|