ovaltine 1.0.2 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,366 @@
1
+ require 'strscan'
2
+
3
+ module JSON
4
+
5
+ def self.parse source
6
+ Pure::Parser.new(source).parse
7
+ end
8
+
9
+ module Pure
10
+ # This class implements the JSON parser that is used to parse a JSON string
11
+ # into a Ruby data structure.
12
+ class Parser < StringScanner
13
+ STRING = /" ((?:[^\x0-\x1f"\\] |
14
+ # escaped special characters:
15
+ \\["\\\/bfnrt] |
16
+ \\u[0-9a-fA-F]{4} |
17
+ # match all but escaped special characters:
18
+ \\[\x20-\x21\x23-\x2e\x30-\x5b\x5d-\x61\x63-\x65\x67-\x6d\x6f-\x71\x73\x75-\xff])*)
19
+ "/nx
20
+ INTEGER = /(-?0|-?[1-9]\d*)/
21
+ FLOAT = /(-?
22
+ (?:0|[1-9]\d*)
23
+ (?:
24
+ \.\d+(?i:e[+-]?\d+) |
25
+ \.\d+ |
26
+ (?i:e[+-]?\d+)
27
+ )
28
+ )/x
29
+ NAN = /NaN/
30
+ INFINITY = /Infinity/
31
+ MINUS_INFINITY = /-Infinity/
32
+ OBJECT_OPEN = /\{/
33
+ OBJECT_CLOSE = /\}/
34
+ ARRAY_OPEN = /\[/
35
+ ARRAY_CLOSE = /\]/
36
+ PAIR_DELIMITER = /:/
37
+ COLLECTION_DELIMITER = /,/
38
+ TRUE = /true/
39
+ FALSE = /false/
40
+ NULL = /null/
41
+ IGNORE = %r(
42
+ (?:
43
+ //[^\n\r]*[\n\r]| # line comments
44
+ /\* # c-style comments
45
+ (?:
46
+ [^*/]| # normal chars
47
+ /[^*]| # slashes that do not start a nested comment
48
+ \*[^/]| # asterisks that do not end this comment
49
+ /(?=\*/) # single slash before this comment's end
50
+ )*
51
+ \*/ # the End of this comment
52
+ |[ \t\r\n]+ # whitespaces: space, horicontal tab, lf, cr
53
+ )+
54
+ )mx
55
+
56
+ UNPARSED = Object.new
57
+
58
+ class ParserError < Error; end
59
+
60
+ # Creates a new JSON::Pure::Parser instance for the string _source_.
61
+ #
62
+ # It will be configured by the _opts_ hash. _opts_ can have the following
63
+ # keys:
64
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
65
+ # structures. Disable depth checking with :max_nesting => false|nil|0,
66
+ # it defaults to 100.
67
+ # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
68
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
69
+ # to false.
70
+ # * *symbolize_names*: If set to true, returns symbols for the names
71
+ # (keys) in a JSON object. Otherwise strings are returned, which is also
72
+ # the default.
73
+ # * *create_additions*: If set to true, the Parser creates
74
+ # additions when if a matching class and create_id was found. This
75
+ # option defaults to false.
76
+ # * *object_class*: Defaults to Hash
77
+ # * *array_class*: Defaults to Array
78
+ # * *quirks_mode*: Enables quirks_mode for parser, that is for example
79
+ # parsing single JSON values instead of documents is possible.
80
+ def initialize(source, opts = {})
81
+ opts ||= {}
82
+ unless @quirks_mode = opts[:quirks_mode]
83
+ source = convert_encoding source
84
+ end
85
+ super source
86
+ if !opts.key?(:max_nesting) # defaults to 100
87
+ @max_nesting = 100
88
+ elsif opts[:max_nesting]
89
+ @max_nesting = opts[:max_nesting]
90
+ else
91
+ @max_nesting = 0
92
+ end
93
+ @allow_nan = !!opts[:allow_nan]
94
+ @symbolize_names = !!opts[:symbolize_names]
95
+ if opts.key?(:create_additions)
96
+ @create_additions = !!opts[:create_additions]
97
+ else
98
+ @create_additions = false
99
+ end
100
+ @create_id = @create_additions ? JSON.create_id : nil
101
+ @object_class = opts[:object_class] || Hash
102
+ @array_class = opts[:array_class] || Array
103
+ @match_string = opts[:match_string]
104
+ end
105
+
106
+ alias source string
107
+
108
+ def quirks_mode?
109
+ !!@quirks_mode
110
+ end
111
+
112
+ def reset
113
+ super
114
+ @current_nesting = 0
115
+ end
116
+
117
+ # Parses the current JSON string _source_ and returns the complete data
118
+ # structure as a result.
119
+ def parse
120
+ reset
121
+ obj = nil
122
+ if @quirks_mode
123
+ while !eos? && skip(IGNORE)
124
+ end
125
+ if eos?
126
+ raise ParserError, "source did not contain any JSON!"
127
+ else
128
+ obj = parse_value
129
+ obj == UNPARSED and raise ParserError, "source did not contain any JSON!"
130
+ end
131
+ else
132
+ until eos?
133
+ case
134
+ when scan(OBJECT_OPEN)
135
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
136
+ @current_nesting = 1
137
+ obj = parse_object
138
+ when scan(ARRAY_OPEN)
139
+ obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
140
+ @current_nesting = 1
141
+ obj = parse_array
142
+ when skip(IGNORE)
143
+ ;
144
+ else
145
+ raise ParserError, "source '#{peek(20)}' not in JSON!"
146
+ end
147
+ end
148
+ obj or raise ParserError, "source did not contain any JSON!"
149
+ end
150
+ obj
151
+ end
152
+
153
+ private
154
+
155
+ def convert_encoding(source)
156
+ if source.respond_to?(:to_str)
157
+ source = source.to_str
158
+ else
159
+ raise TypeError, "#{source.inspect} is not like a string"
160
+ end
161
+ if defined?(::Encoding)
162
+ if source.encoding == ::Encoding::ASCII_8BIT
163
+ b = source[0, 4].bytes.to_a
164
+ source =
165
+ case
166
+ when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
167
+ source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
168
+ when b.size >= 4 && b[0] == 0 && b[2] == 0
169
+ source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
170
+ when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
171
+ source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
172
+ when b.size >= 4 && b[1] == 0 && b[3] == 0
173
+ source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
174
+ else
175
+ source.dup
176
+ end
177
+ else
178
+ source = source.encode(::Encoding::UTF_8)
179
+ end
180
+ source.force_encoding(::Encoding::ASCII_8BIT)
181
+ else
182
+ b = source
183
+ source =
184
+ case
185
+ when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
186
+ JSON.iconv('utf-8', 'utf-32be', b)
187
+ when b.size >= 4 && b[0] == 0 && b[2] == 0
188
+ JSON.iconv('utf-8', 'utf-16be', b)
189
+ when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
190
+ JSON.iconv('utf-8', 'utf-32le', b)
191
+ when b.size >= 4 && b[1] == 0 && b[3] == 0
192
+ JSON.iconv('utf-8', 'utf-16le', b)
193
+ else
194
+ b
195
+ end
196
+ end
197
+ source
198
+ end
199
+
200
+ # Unescape characters in strings.
201
+ UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
202
+ UNESCAPE_MAP.update({
203
+ ?" => '"',
204
+ ?\\ => '\\',
205
+ ?/ => '/',
206
+ ?b => "\b",
207
+ ?f => "\f",
208
+ ?n => "\n",
209
+ ?r => "\r",
210
+ ?t => "\t",
211
+ ?u => nil,
212
+ })
213
+
214
+ EMPTY_8BIT_STRING = ''
215
+ if ::String.method_defined?(:encode)
216
+ EMPTY_8BIT_STRING.force_encoding Encoding::ASCII_8BIT
217
+ end
218
+
219
+ def parse_string
220
+ if scan(STRING)
221
+ return '' if self[1].empty?
222
+ string = self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
223
+ if u = UNESCAPE_MAP[$&[1]]
224
+ u
225
+ else # \uXXXX
226
+ bytes = EMPTY_8BIT_STRING.dup
227
+ i = 0
228
+ while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
229
+ bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
230
+ i += 1
231
+ end
232
+ JSON.iconv('utf-8', 'utf-16be', bytes)
233
+ end
234
+ end
235
+ if string.respond_to?(:force_encoding)
236
+ string.force_encoding(::Encoding::UTF_8)
237
+ end
238
+ if @create_additions and @match_string
239
+ for (regexp, klass) in @match_string
240
+ klass.json_creatable? or next
241
+ string =~ regexp and return klass.json_create(string)
242
+ end
243
+ end
244
+ string
245
+ else
246
+ UNPARSED
247
+ end
248
+ rescue => e
249
+ raise ParserError, "Caught #{e.class} at '#{peek(20)}': #{e}"
250
+ end
251
+
252
+ def parse_value
253
+ case
254
+ when scan(FLOAT)
255
+ Float(self[1])
256
+ when scan(INTEGER)
257
+ Integer(self[1])
258
+ when scan(TRUE)
259
+ true
260
+ when scan(FALSE)
261
+ false
262
+ when scan(NULL)
263
+ nil
264
+ when (string = parse_string) != UNPARSED
265
+ string
266
+ when scan(ARRAY_OPEN)
267
+ @current_nesting += 1
268
+ ary = parse_array
269
+ @current_nesting -= 1
270
+ ary
271
+ when scan(OBJECT_OPEN)
272
+ @current_nesting += 1
273
+ obj = parse_object
274
+ @current_nesting -= 1
275
+ obj
276
+ when @allow_nan && scan(NAN)
277
+ NaN
278
+ when @allow_nan && scan(INFINITY)
279
+ Infinity
280
+ when @allow_nan && scan(MINUS_INFINITY)
281
+ MinusInfinity
282
+ else
283
+ UNPARSED
284
+ end
285
+ end
286
+
287
+ def parse_array
288
+ raise NestingError, "nesting of #@current_nesting is too deep" if
289
+ @max_nesting.nonzero? && @current_nesting > @max_nesting
290
+ result = @array_class.new
291
+ delim = false
292
+ until eos?
293
+ case
294
+ when (value = parse_value) != UNPARSED
295
+ delim = false
296
+ result << value
297
+ skip(IGNORE)
298
+ if scan(COLLECTION_DELIMITER)
299
+ delim = true
300
+ elsif match?(ARRAY_CLOSE)
301
+ ;
302
+ else
303
+ raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!"
304
+ end
305
+ when scan(ARRAY_CLOSE)
306
+ if delim
307
+ raise ParserError, "expected next element in array at '#{peek(20)}'!"
308
+ end
309
+ break
310
+ when skip(IGNORE)
311
+ ;
312
+ else
313
+ raise ParserError, "unexpected token in array at '#{peek(20)}'!"
314
+ end
315
+ end
316
+ result
317
+ end
318
+
319
+ def parse_object
320
+ raise NestingError, "nesting of #@current_nesting is too deep" if
321
+ @max_nesting.nonzero? && @current_nesting > @max_nesting
322
+ result = @object_class.new
323
+ delim = false
324
+ until eos?
325
+ case
326
+ when (string = parse_string) != UNPARSED
327
+ skip(IGNORE)
328
+ unless scan(PAIR_DELIMITER)
329
+ raise ParserError, "expected ':' in object at '#{peek(20)}'!"
330
+ end
331
+ skip(IGNORE)
332
+ unless (value = parse_value).equal? UNPARSED
333
+ result[@symbolize_names ? string.to_sym : string] = value
334
+ delim = false
335
+ skip(IGNORE)
336
+ if scan(COLLECTION_DELIMITER)
337
+ delim = true
338
+ elsif match?(OBJECT_CLOSE)
339
+ ;
340
+ else
341
+ raise ParserError, "expected ',' or '}' in object at '#{peek(20)}'!"
342
+ end
343
+ else
344
+ raise ParserError, "expected value in object at '#{peek(20)}'!"
345
+ end
346
+ when scan(OBJECT_CLOSE)
347
+ if delim
348
+ raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
349
+ end
350
+ if @create_additions and klassname = result[@create_id]
351
+ klass = JSON.deep_const_get klassname
352
+ break unless klass and klass.json_creatable?
353
+ result = klass.json_create(result)
354
+ end
355
+ break
356
+ when skip(IGNORE)
357
+ ;
358
+ else
359
+ raise ParserError, "unexpected token in object at '#{peek(20)}'!"
360
+ end
361
+ end
362
+ result
363
+ end
364
+ end
365
+ end
366
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ovaltine
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delisa Mason
@@ -54,6 +54,7 @@ files:
54
54
  - .travis.yml
55
55
  - CHANGELOG.md
56
56
  - Gemfile
57
+ - Gemfile.lock
57
58
  - LICENSE
58
59
  - README.md
59
60
  - Rakefile
@@ -80,9 +81,18 @@ files:
80
81
  - lib/ovaltine/objc/storyboard_templates.rb
81
82
  - lib/ovaltine/storyboard.rb
82
83
  - lib/ovaltine/version.rb
84
+ - lib/ovaltine/xcode_project.rb
85
+ - lib/ovaltine/xcode_project/ext/stdlib.rb
86
+ - lib/ovaltine/xcode_project/pbxfilereference.rb
87
+ - lib/ovaltine/xcode_project/pbxgroup.rb
88
+ - lib/ovaltine/xcode_project/pbxobject.rb
83
89
  - ovaltine.gemspec
84
90
  - specs/storyboard_formatter_spec.rb
85
91
  - specs/storyboard_spec.rb
92
+ - vendor/json_pure/COPYING
93
+ - vendor/json_pure/LICENSE
94
+ - vendor/json_pure/generator.rb
95
+ - vendor/json_pure/parser.rb
86
96
  homepage: https://github.com/kattrali/ovaltine
87
97
  licenses:
88
98
  - MIT