json-projection 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/json-projection/parser.rb +39 -32
- data/lib/json-projection/parser/fifo.rb +17 -17
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b310ebdff6509d59c9737225a97b66de49a2ced
|
4
|
+
data.tar.gz: 705ca5b363df43245d2c8a3180343acb4584707c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 818bfe7cd12ea0b9a06316822b875595ee4608fe74114a39963901aa7f584a02e20edbca77fe1e926ffae64155debd31f7185fa983f53d82974f01686c085dfc
|
7
|
+
data.tar.gz: 9a911520fc8b962704ac1a3cf87dfef0d2528b52dc3dac4b17b89407328b1278338ec68fa01f0d21cf8b9fd443d5ef669d770f1831a9fdf2d2ae2b2b569fdd38
|
@@ -34,7 +34,6 @@ module JsonProjection
|
|
34
34
|
# Use the json gem for small documents. Use this for huge documents that
|
35
35
|
# won't fit in memory.
|
36
36
|
class Parser
|
37
|
-
BUF_SIZE = 4096
|
38
37
|
CONTROL = /[\x00-\x1F]/
|
39
38
|
WS = /[ \n\t\r]/
|
40
39
|
HEX = /[0-9a-fA-F]/
|
@@ -67,19 +66,25 @@ module JsonProjection
|
|
67
66
|
# events are drawn from the parser. The parser maintains a small data cache
|
68
67
|
# of bytes read from the stream.
|
69
68
|
#
|
70
|
-
# stream
|
71
|
-
#
|
69
|
+
# stream :: IO
|
70
|
+
# IO stream to read data from.
|
71
|
+
#
|
72
|
+
# chunk_size :: Integer
|
73
|
+
# Number of bytes to read from the stream at a time.
|
72
74
|
#
|
73
75
|
# Returns nothing.
|
74
|
-
def initialize(stream)
|
76
|
+
def initialize(stream, chunk_size = 4096)
|
75
77
|
@stream = stream
|
78
|
+
@chunk_size = chunk_size
|
76
79
|
|
77
80
|
@event_buffer = Fifo.new
|
78
81
|
|
79
|
-
@
|
80
|
-
|
82
|
+
@character_buffer = Buffer.new
|
83
|
+
|
84
|
+
@characters_cursor = -1
|
85
|
+
@characters = nil
|
81
86
|
|
82
|
-
@
|
87
|
+
@stream_position = -1
|
83
88
|
@state = :start_document
|
84
89
|
@stack = []
|
85
90
|
|
@@ -93,7 +98,7 @@ module JsonProjection
|
|
93
98
|
# Returns a JsonProject::StreamEvent subclass or raises StandardError.
|
94
99
|
def next_event()
|
95
100
|
# Are there any already read events, return the oldest
|
96
|
-
|
101
|
+
event = @event_buffer.pop!
|
97
102
|
return event unless event.nil?
|
98
103
|
|
99
104
|
if @state == :end_document
|
@@ -101,30 +106,28 @@ module JsonProjection
|
|
101
106
|
end
|
102
107
|
|
103
108
|
while true do
|
104
|
-
if @
|
105
|
-
data = stream.read(
|
109
|
+
if @characters.nil? || @characters_cursor == @characters.size
|
110
|
+
data = stream.read(@chunk_size)
|
106
111
|
if data == nil # hit EOF
|
107
112
|
error("unexpected EOF")
|
108
113
|
end
|
109
114
|
|
110
|
-
@
|
115
|
+
@characters = @character_buffer.<<(data).each_char.to_a
|
116
|
+
@characters_cursor = 0
|
111
117
|
end
|
112
118
|
|
113
|
-
|
114
|
-
|
119
|
+
character = @characters[@characters_cursor]
|
120
|
+
@characters_cursor += 1
|
115
121
|
|
116
|
-
@
|
117
|
-
@pos += 1
|
122
|
+
@stream_position += 1
|
118
123
|
|
119
|
-
new_state,
|
124
|
+
new_state, new_events = handle_character(@state, character)
|
120
125
|
|
121
126
|
@state = new_state
|
122
|
-
@event_buffer
|
127
|
+
@event_buffer.prepend!(new_events)
|
123
128
|
|
124
|
-
|
125
|
-
|
126
|
-
return event
|
127
|
-
end
|
129
|
+
event = @event_buffer.pop!
|
130
|
+
return event unless event.nil?
|
128
131
|
end
|
129
132
|
end
|
130
133
|
|
@@ -151,13 +154,13 @@ module JsonProjection
|
|
151
154
|
when LEFT_BRACE
|
152
155
|
@stack.push(:object)
|
153
156
|
|
154
|
-
events = Fifo.pure(
|
157
|
+
events = Fifo.pure(StartObject.empty, StartDocument.empty)
|
155
158
|
|
156
159
|
return :start_object, events
|
157
160
|
when LEFT_BRACKET
|
158
161
|
@stack.push(:array)
|
159
162
|
|
160
|
-
events = Fifo.pure(
|
163
|
+
events = Fifo.pure(StartArray.empty, StartDocument.empty)
|
161
164
|
|
162
165
|
return :start_array, events
|
163
166
|
end
|
@@ -296,8 +299,9 @@ module JsonProjection
|
|
296
299
|
state = :end_value
|
297
300
|
|
298
301
|
state, new_events = handle_character(state, ch)
|
302
|
+
events.prepend!(new_events)
|
299
303
|
|
300
|
-
return state,
|
304
|
+
return state, events
|
301
305
|
end
|
302
306
|
|
303
307
|
when :start_float
|
@@ -324,8 +328,9 @@ module JsonProjection
|
|
324
328
|
state = :end_value
|
325
329
|
|
326
330
|
state, new_events = handle_character(state, ch)
|
331
|
+
events.prepend!(new_events)
|
327
332
|
|
328
|
-
return state,
|
333
|
+
return state, events
|
329
334
|
end
|
330
335
|
|
331
336
|
when :start_exponent
|
@@ -351,8 +356,9 @@ module JsonProjection
|
|
351
356
|
state = :end_value
|
352
357
|
|
353
358
|
state, new_events = handle_character(state, ch)
|
359
|
+
events.prepend!(new_events)
|
354
360
|
|
355
|
-
return state,
|
361
|
+
return state, events
|
356
362
|
end
|
357
363
|
|
358
364
|
when :start_int
|
@@ -373,8 +379,9 @@ module JsonProjection
|
|
373
379
|
state = :end_value
|
374
380
|
|
375
381
|
state, new_events = handle_character(state, ch)
|
382
|
+
events.prepend!(new_events)
|
376
383
|
|
377
|
-
return state,
|
384
|
+
return state, events
|
378
385
|
end
|
379
386
|
|
380
387
|
when :start_true
|
@@ -478,14 +485,14 @@ module JsonProjection
|
|
478
485
|
# a value.
|
479
486
|
def end_container(type)
|
480
487
|
state = :end_value
|
481
|
-
events = Fifo.
|
488
|
+
events = Fifo.pure
|
482
489
|
|
483
490
|
if @stack.pop == type
|
484
491
|
case type
|
485
492
|
when :object then
|
486
|
-
events
|
493
|
+
events.push!(EndObject.empty)
|
487
494
|
when :array then
|
488
|
-
events
|
495
|
+
events.push!(EndArray.empty)
|
489
496
|
end
|
490
497
|
else
|
491
498
|
error("Expected end of #{type}")
|
@@ -493,7 +500,7 @@ module JsonProjection
|
|
493
500
|
|
494
501
|
if @stack.empty?
|
495
502
|
state = :end_document
|
496
|
-
events
|
503
|
+
events.push!(EndDocument.empty)
|
497
504
|
end
|
498
505
|
|
499
506
|
return state, events
|
@@ -587,7 +594,7 @@ module JsonProjection
|
|
587
594
|
end
|
588
595
|
|
589
596
|
def error(message)
|
590
|
-
raise ParseError, "#{message}: char #{@
|
597
|
+
raise ParseError, "#{message}: char #{@stream_position}"
|
591
598
|
end
|
592
599
|
end
|
593
600
|
|
@@ -2,28 +2,23 @@ module JsonProjection
|
|
2
2
|
class Fifo
|
3
3
|
|
4
4
|
def self.empty
|
5
|
-
@empty ||= self.new
|
5
|
+
@empty ||= self.new([].freeze)
|
6
6
|
end
|
7
7
|
|
8
|
-
def self.pure(
|
9
|
-
Fifo.new(
|
8
|
+
def self.pure(*vals)
|
9
|
+
Fifo.new(vals)
|
10
10
|
end
|
11
11
|
|
12
12
|
def initialize(stack = [])
|
13
13
|
@stack = stack
|
14
14
|
end
|
15
15
|
|
16
|
-
def push(val)
|
17
|
-
|
16
|
+
def push!(val)
|
17
|
+
@stack.insert(0, val)
|
18
18
|
end
|
19
19
|
|
20
|
-
def pop
|
21
|
-
|
22
|
-
|
23
|
-
init = @stack.slice(0, @stack.size - 1)
|
24
|
-
last = @stack.last
|
25
|
-
|
26
|
-
return Fifo.new(init), last
|
20
|
+
def pop!
|
21
|
+
@stack.pop
|
27
22
|
end
|
28
23
|
|
29
24
|
def empty?
|
@@ -39,15 +34,20 @@ module JsonProjection
|
|
39
34
|
stack.hash
|
40
35
|
end
|
41
36
|
|
42
|
-
def
|
43
|
-
return
|
44
|
-
|
45
|
-
|
37
|
+
def prepend!(fifo)
|
38
|
+
return if fifo.empty?
|
39
|
+
if empty?
|
40
|
+
@stack = fifo.stack.dup
|
41
|
+
return
|
42
|
+
end
|
43
|
+
@stack = fifo.stack.concat(@stack)
|
46
44
|
end
|
47
45
|
|
48
46
|
protected
|
49
47
|
|
50
|
-
|
48
|
+
def stack
|
49
|
+
@stack
|
50
|
+
end
|
51
51
|
|
52
52
|
end
|
53
53
|
end
|