ovaltine 1.0.2 → 1.0.4

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.
@@ -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