scout 5.6.7 → 5.6.8.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/CHANGELOG.markdown +4 -0
  2. data/lib/scout/version.rb +1 -1
  3. data/vendor/json_pure/.gitignore +12 -0
  4. data/vendor/json_pure/.travis.yml +20 -0
  5. data/vendor/json_pure/CHANGES +120 -0
  6. data/vendor/json_pure/COPYING-json-jruby +57 -0
  7. data/vendor/json_pure/Gemfile +11 -0
  8. data/vendor/json_pure/README-json-jruby.markdown +33 -0
  9. data/vendor/json_pure/{README → README.rdoc} +7 -7
  10. data/vendor/json_pure/Rakefile +305 -185
  11. data/vendor/json_pure/VERSION +1 -1
  12. data/vendor/json_pure/diagrams/.keep +0 -0
  13. data/vendor/json_pure/ext/json/ext/fbuffer/fbuffer.h +181 -0
  14. data/vendor/json_pure/ext/json/ext/generator/depend +1 -0
  15. data/vendor/json_pure/ext/json/ext/generator/extconf.rb +4 -6
  16. data/vendor/json_pure/ext/json/ext/generator/generator.c +463 -369
  17. data/vendor/json_pure/ext/json/ext/generator/generator.h +44 -66
  18. data/vendor/json_pure/ext/json/ext/parser/depend +1 -0
  19. data/vendor/json_pure/ext/json/ext/parser/extconf.rb +3 -5
  20. data/vendor/json_pure/ext/json/ext/parser/parser.c +580 -311
  21. data/vendor/json_pure/ext/json/ext/parser/parser.h +14 -8
  22. data/vendor/json_pure/ext/json/ext/parser/parser.rl +242 -107
  23. data/vendor/json_pure/install.rb +8 -11
  24. data/vendor/json_pure/java/src/json/ext/ByteListTranscoder.java +167 -0
  25. data/vendor/json_pure/java/src/json/ext/Generator.java +444 -0
  26. data/vendor/json_pure/java/src/json/ext/GeneratorMethods.java +232 -0
  27. data/vendor/json_pure/java/src/json/ext/GeneratorService.java +43 -0
  28. data/vendor/json_pure/java/src/json/ext/GeneratorState.java +543 -0
  29. data/vendor/json_pure/java/src/json/ext/OptionsReader.java +114 -0
  30. data/vendor/json_pure/java/src/json/ext/Parser.java +2644 -0
  31. data/vendor/json_pure/java/src/json/ext/Parser.rl +968 -0
  32. data/vendor/json_pure/java/src/json/ext/ParserService.java +35 -0
  33. data/vendor/json_pure/java/src/json/ext/RuntimeInfo.java +121 -0
  34. data/vendor/json_pure/java/src/json/ext/StringDecoder.java +167 -0
  35. data/vendor/json_pure/java/src/json/ext/StringEncoder.java +106 -0
  36. data/vendor/json_pure/java/src/json/ext/Utils.java +89 -0
  37. data/vendor/json_pure/json-java.gemspec +23 -0
  38. data/vendor/json_pure/json.gemspec +37 -0
  39. data/vendor/json_pure/json_pure.gemspec +39 -0
  40. data/vendor/json_pure/lib/json.rb +52 -0
  41. data/vendor/json_pure/lib/json/add/bigdecimal.rb +28 -0
  42. data/vendor/json_pure/lib/json/add/complex.rb +22 -0
  43. data/vendor/json_pure/lib/json/add/core.rb +9 -146
  44. data/vendor/json_pure/lib/json/add/date.rb +34 -0
  45. data/vendor/json_pure/lib/json/add/date_time.rb +50 -0
  46. data/vendor/json_pure/lib/json/add/exception.rb +31 -0
  47. data/vendor/json_pure/lib/json/add/ostruct.rb +31 -0
  48. data/vendor/json_pure/lib/json/add/range.rb +29 -0
  49. data/vendor/json_pure/lib/json/add/rational.rb +22 -0
  50. data/vendor/json_pure/lib/json/add/regexp.rb +30 -0
  51. data/vendor/json_pure/lib/json/add/struct.rb +30 -0
  52. data/vendor/json_pure/lib/json/add/symbol.rb +25 -0
  53. data/vendor/json_pure/lib/json/add/time.rb +38 -0
  54. data/vendor/json_pure/lib/json/common.rb +157 -67
  55. data/vendor/json_pure/lib/json/ext.rb +8 -2
  56. data/vendor/json_pure/lib/json/ext/.keep +0 -0
  57. data/vendor/json_pure/lib/json/generic_object.rb +70 -0
  58. data/vendor/json_pure/lib/json/pure.rb +8 -64
  59. data/vendor/json_pure/lib/json/pure/generator.rb +183 -113
  60. data/vendor/json_pure/lib/json/pure/parser.rb +118 -66
  61. data/vendor/json_pure/lib/json/version.rb +1 -1
  62. data/vendor/json_pure/tests/fixtures/fail18.json +1 -1
  63. data/vendor/json_pure/tests/setup_variant.rb +11 -0
  64. data/vendor/json_pure/tests/test_json.rb +233 -28
  65. data/vendor/json_pure/tests/test_json_addition.rb +68 -34
  66. data/vendor/json_pure/tests/test_json_encoding.rb +11 -14
  67. data/vendor/json_pure/tests/test_json_fixtures.rb +11 -10
  68. data/vendor/json_pure/tests/test_json_generate.rb +207 -7
  69. data/vendor/json_pure/tests/test_json_generic_object.rb +75 -0
  70. data/vendor/json_pure/tests/test_json_string_matching.rb +39 -0
  71. data/vendor/json_pure/tests/test_json_unicode.rb +3 -7
  72. data/vendor/json_pure/tools/fuzz.rb +1 -1
  73. data/vendor/json_pure/tools/server.rb +1 -0
  74. metadata +87 -94
  75. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log +0 -52
  76. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat +0 -1000
  77. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat +0 -1001
  78. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat +0 -900
  79. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat +0 -901
  80. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat +0 -1000
  81. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat +0 -1001
  82. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log +0 -261
  83. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat +0 -1000
  84. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat +0 -1001
  85. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat +0 -1000
  86. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat +0 -1001
  87. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat +0 -1000
  88. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat +0 -1001
  89. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log +0 -262
  90. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat +0 -1000
  91. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat +0 -1001
  92. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log +0 -82
  93. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log +0 -34
  94. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat +0 -900
  95. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat +0 -901
  96. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log +0 -81
  97. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat +0 -1000
  98. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat +0 -1001
  99. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log +0 -82
  100. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat +0 -1000
  101. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat +0 -1001
  102. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log +0 -82
  103. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat +0 -1000
  104. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat +0 -1001
  105. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log +0 -82
  106. data/vendor/json_pure/benchmarks/generator2_benchmark.rb +0 -222
  107. data/vendor/json_pure/benchmarks/generator_benchmark.rb +0 -224
  108. data/vendor/json_pure/benchmarks/ohai.json +0 -1216
  109. data/vendor/json_pure/benchmarks/ohai.ruby +0 -1
  110. data/vendor/json_pure/benchmarks/parser2_benchmark.rb +0 -251
  111. data/vendor/json_pure/benchmarks/parser_benchmark.rb +0 -259
  112. data/vendor/json_pure/bin/edit_json.rb +0 -9
  113. data/vendor/json_pure/bin/prettify_json.rb +0 -75
  114. data/vendor/json_pure/lib/json/Array.xpm +0 -21
  115. data/vendor/json_pure/lib/json/FalseClass.xpm +0 -21
  116. data/vendor/json_pure/lib/json/Hash.xpm +0 -21
  117. data/vendor/json_pure/lib/json/Key.xpm +0 -73
  118. data/vendor/json_pure/lib/json/NilClass.xpm +0 -21
  119. data/vendor/json_pure/lib/json/Numeric.xpm +0 -28
  120. data/vendor/json_pure/lib/json/String.xpm +0 -96
  121. data/vendor/json_pure/lib/json/TrueClass.xpm +0 -21
  122. data/vendor/json_pure/lib/json/add/rails.rb +0 -58
  123. data/vendor/json_pure/lib/json/editor.rb +0 -1371
  124. data/vendor/json_pure/lib/json/json.xpm +0 -1499
  125. data/vendor/json_pure/tests/test_json_rails.rb +0 -144
@@ -0,0 +1,968 @@
1
+ /*
2
+ * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
+ *
4
+ * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
+ * for details.
6
+ */
7
+ package json.ext;
8
+
9
+ import org.jruby.Ruby;
10
+ import org.jruby.RubyArray;
11
+ import org.jruby.RubyClass;
12
+ import org.jruby.RubyEncoding;
13
+ import org.jruby.RubyFloat;
14
+ import org.jruby.RubyHash;
15
+ import org.jruby.RubyInteger;
16
+ import org.jruby.RubyModule;
17
+ import org.jruby.RubyNumeric;
18
+ import org.jruby.RubyObject;
19
+ import org.jruby.RubyString;
20
+ import org.jruby.anno.JRubyMethod;
21
+ import org.jruby.exceptions.JumpException;
22
+ import org.jruby.exceptions.RaiseException;
23
+ import org.jruby.runtime.Block;
24
+ import org.jruby.runtime.ObjectAllocator;
25
+ import org.jruby.runtime.ThreadContext;
26
+ import org.jruby.runtime.Visibility;
27
+ import org.jruby.runtime.builtin.IRubyObject;
28
+ import org.jruby.util.ByteList;
29
+ import org.jruby.util.ConvertBytes;
30
+ import static org.jruby.util.ConvertDouble.DoubleConverter;
31
+
32
+ /**
33
+ * The <code>JSON::Ext::Parser</code> class.
34
+ *
35
+ * <p>This is the JSON parser implemented as a Java class. To use it as the
36
+ * standard parser, set
37
+ * <pre>JSON.parser = JSON::Ext::Parser</pre>
38
+ * This is performed for you when you <code>include "json/ext"</code>.
39
+ *
40
+ * <p>This class does not perform the actual parsing, just acts as an interface
41
+ * to Ruby code. When the {@link #parse()} method is invoked, a
42
+ * Parser.ParserSession object is instantiated, which handles the process.
43
+ *
44
+ * @author mernen
45
+ */
46
+ public class Parser extends RubyObject {
47
+ private final RuntimeInfo info;
48
+ private RubyString vSource;
49
+ private RubyString createId;
50
+ private boolean createAdditions;
51
+ private int maxNesting;
52
+ private boolean allowNaN;
53
+ private boolean symbolizeNames;
54
+ private boolean quirksMode;
55
+ private RubyClass objectClass;
56
+ private RubyClass arrayClass;
57
+ private RubyHash match_string;
58
+
59
+ private static final int DEFAULT_MAX_NESTING = 100;
60
+
61
+ private static final ByteList JSON_MINUS_INFINITY = new ByteList(ByteList.plain("-Infinity"));
62
+ // constant names in the JSON module containing those values
63
+ private static final String CONST_NAN = "NaN";
64
+ private static final String CONST_INFINITY = "Infinity";
65
+ private static final String CONST_MINUS_INFINITY = "MinusInfinity";
66
+
67
+ static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
68
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
69
+ return new Parser(runtime, klazz);
70
+ }
71
+ };
72
+
73
+ /**
74
+ * Multiple-value return for internal parser methods.
75
+ *
76
+ * <p>All the <code>parse<var>Stuff</var></code> methods return instances of
77
+ * <code>ParserResult</code> when successful, or <code>null</code> when
78
+ * there's a problem with the input data.
79
+ */
80
+ static final class ParserResult {
81
+ /**
82
+ * The result of the successful parsing. Should never be
83
+ * <code>null</code>.
84
+ */
85
+ IRubyObject result;
86
+ /**
87
+ * The point where the parser returned.
88
+ */
89
+ int p;
90
+
91
+ void update(IRubyObject result, int p) {
92
+ this.result = result;
93
+ this.p = p;
94
+ }
95
+ }
96
+
97
+ public Parser(Ruby runtime, RubyClass metaClass) {
98
+ super(runtime, metaClass);
99
+ info = RuntimeInfo.forRuntime(runtime);
100
+ }
101
+
102
+ /**
103
+ * <code>Parser.new(source, opts = {})</code>
104
+ *
105
+ * <p>Creates a new <code>JSON::Ext::Parser</code> instance for the string
106
+ * <code>source</code>.
107
+ * It will be configured by the <code>opts</code> Hash.
108
+ * <code>opts</code> can have the following keys:
109
+ *
110
+ * <dl>
111
+ * <dt><code>:max_nesting</code>
112
+ * <dd>The maximum depth of nesting allowed in the parsed data
113
+ * structures. Disable depth checking with <code>:max_nesting => false|nil|0</code>,
114
+ * it defaults to 100.
115
+ *
116
+ * <dt><code>:allow_nan</code>
117
+ * <dd>If set to <code>true</code>, allow <code>NaN</code>,
118
+ * <code>Infinity</code> and <code>-Infinity</code> in defiance of RFC 4627
119
+ * to be parsed by the Parser. This option defaults to <code>false</code>.
120
+ *
121
+ * <dt><code>:symbolize_names</code>
122
+ * <dd>If set to <code>true</code>, returns symbols for the names (keys) in
123
+ * a JSON object. Otherwise strings are returned, which is also the default.
124
+ *
125
+ * <dt><code>:quirks_mode?</code>
126
+ * <dd>If set to <code>true</code>, if the parse is in quirks_mode, false
127
+ * otherwise.
128
+ *
129
+ * <dt><code>:create_additions</code>
130
+ * <dd>If set to <code>false</code>, the Parser doesn't create additions
131
+ * even if a matchin class and <code>create_id</code> was found. This option
132
+ * defaults to <code>true</code>.
133
+ *
134
+ * <dt><code>:object_class</code>
135
+ * <dd>Defaults to Hash.
136
+ *
137
+ * <dt><code>:array_class</code>
138
+ * <dd>Defaults to Array.
139
+ *
140
+ * <dt><code>:quirks_mode</code>
141
+ * <dd>Enables quirks_mode for parser, that is for example parsing single
142
+ * JSON values instead of documents is possible.
143
+ * </dl>
144
+ */
145
+ @JRubyMethod(name = "new", required = 1, optional = 1, meta = true)
146
+ public static IRubyObject newInstance(IRubyObject clazz, IRubyObject[] args, Block block) {
147
+ Parser parser = (Parser)((RubyClass)clazz).allocate();
148
+
149
+ parser.callInit(args, block);
150
+
151
+ return parser;
152
+ }
153
+
154
+ @JRubyMethod(required = 1, optional = 1, visibility = Visibility.PRIVATE)
155
+ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
156
+ Ruby runtime = context.getRuntime();
157
+ if (this.vSource != null) {
158
+ throw runtime.newTypeError("already initialized instance");
159
+ }
160
+
161
+ OptionsReader opts = new OptionsReader(context, args.length > 1 ? args[1] : null);
162
+ this.maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
163
+ this.allowNaN = opts.getBool("allow_nan", false);
164
+ this.symbolizeNames = opts.getBool("symbolize_names", false);
165
+ this.quirksMode = opts.getBool("quirks_mode", false);
166
+ this.createId = opts.getString("create_id", getCreateId(context));
167
+ this.createAdditions = opts.getBool("create_additions", false);
168
+ this.objectClass = opts.getClass("object_class", runtime.getHash());
169
+ this.arrayClass = opts.getClass("array_class", runtime.getArray());
170
+ this.match_string = opts.getHash("match_string");
171
+
172
+ this.vSource = args[0].convertToString();
173
+ if (!quirksMode) this.vSource = convertEncoding(context, vSource);
174
+
175
+ return this;
176
+ }
177
+
178
+ /**
179
+ * Checks the given string's encoding. If a non-UTF-8 encoding is detected,
180
+ * a converted copy is returned.
181
+ * Returns the source string if no conversion is needed.
182
+ */
183
+ private RubyString convertEncoding(ThreadContext context, RubyString source) {
184
+ ByteList bl = source.getByteList();
185
+ int len = bl.length();
186
+ if (len < 2) {
187
+ throw Utils.newException(context, Utils.M_PARSER_ERROR,
188
+ "A JSON text must at least contain two octets!");
189
+ }
190
+
191
+ if (info.encodingsSupported()) {
192
+ RubyEncoding encoding = (RubyEncoding)source.encoding(context);
193
+ if (encoding != info.ascii8bit.get()) {
194
+ return (RubyString)source.encode(context, info.utf8.get());
195
+ }
196
+
197
+ String sniffedEncoding = sniffByteList(bl);
198
+ if (sniffedEncoding == null) return source; // assume UTF-8
199
+ return reinterpretEncoding(context, source, sniffedEncoding);
200
+ }
201
+
202
+ String sniffedEncoding = sniffByteList(bl);
203
+ if (sniffedEncoding == null) return source; // assume UTF-8
204
+ Ruby runtime = context.getRuntime();
205
+ return (RubyString)info.jsonModule.get().
206
+ callMethod(context, "iconv",
207
+ new IRubyObject[] {
208
+ runtime.newString("utf-8"),
209
+ runtime.newString(sniffedEncoding),
210
+ source});
211
+ }
212
+
213
+ /**
214
+ * Checks the first four bytes of the given ByteList to infer its encoding,
215
+ * using the principle demonstrated on section 3 of RFC 4627 (JSON).
216
+ */
217
+ private static String sniffByteList(ByteList bl) {
218
+ if (bl.length() < 4) return null;
219
+ if (bl.get(0) == 0 && bl.get(2) == 0) {
220
+ return bl.get(1) == 0 ? "utf-32be" : "utf-16be";
221
+ }
222
+ if (bl.get(1) == 0 && bl.get(3) == 0) {
223
+ return bl.get(2) == 0 ? "utf-32le" : "utf-16le";
224
+ }
225
+ return null;
226
+ }
227
+
228
+ /**
229
+ * Assumes the given (binary) RubyString to be in the given encoding, then
230
+ * converts it to UTF-8.
231
+ */
232
+ private RubyString reinterpretEncoding(ThreadContext context,
233
+ RubyString str, String sniffedEncoding) {
234
+ RubyEncoding actualEncoding = info.getEncoding(context, sniffedEncoding);
235
+ RubyEncoding targetEncoding = info.utf8.get();
236
+ RubyString dup = (RubyString)str.dup();
237
+ dup.force_encoding(context, actualEncoding);
238
+ return (RubyString)dup.encode_bang(context, targetEncoding);
239
+ }
240
+
241
+ /**
242
+ * <code>Parser#parse()</code>
243
+ *
244
+ * <p>Parses the current JSON text <code>source</code> and returns the
245
+ * complete data structure as a result.
246
+ */
247
+ @JRubyMethod
248
+ public IRubyObject parse(ThreadContext context) {
249
+ return new ParserSession(this, context).parse();
250
+ }
251
+
252
+ /**
253
+ * <code>Parser#source()</code>
254
+ *
255
+ * <p>Returns a copy of the current <code>source</code> string, that was
256
+ * used to construct this Parser.
257
+ */
258
+ @JRubyMethod(name = "source")
259
+ public IRubyObject source_get() {
260
+ return checkAndGetSource().dup();
261
+ }
262
+
263
+ /**
264
+ * <code>Parser#quirks_mode?()</code>
265
+ *
266
+ * <p>If set to <code>true</code>, if the parse is in quirks_mode, false
267
+ * otherwise.
268
+ */
269
+ @JRubyMethod(name = "quirks_mode?")
270
+ public IRubyObject quirks_mode_p(ThreadContext context) {
271
+ return context.getRuntime().newBoolean(quirksMode);
272
+ }
273
+
274
+ public RubyString checkAndGetSource() {
275
+ if (vSource != null) {
276
+ return vSource;
277
+ } else {
278
+ throw getRuntime().newTypeError("uninitialized instance");
279
+ }
280
+ }
281
+
282
+ /**
283
+ * Queries <code>JSON.create_id</code>. Returns <code>null</code> if it is
284
+ * set to <code>nil</code> or <code>false</code>, and a String if not.
285
+ */
286
+ private RubyString getCreateId(ThreadContext context) {
287
+ IRubyObject v = info.jsonModule.get().callMethod(context, "create_id");
288
+ return v.isTrue() ? v.convertToString() : null;
289
+ }
290
+
291
+ /**
292
+ * A string parsing session.
293
+ *
294
+ * <p>Once a ParserSession is instantiated, the source string should not
295
+ * change until the parsing is complete. The ParserSession object assumes
296
+ * the source {@link RubyString} is still associated to its original
297
+ * {@link ByteList}, which in turn must still be bound to the same
298
+ * <code>byte[]</code> value (and on the same offset).
299
+ */
300
+ // Ragel uses lots of fall-through
301
+ @SuppressWarnings("fallthrough")
302
+ private static class ParserSession {
303
+ private final Parser parser;
304
+ private final ThreadContext context;
305
+ private final ByteList byteList;
306
+ private final ByteList view;
307
+ private final byte[] data;
308
+ private final StringDecoder decoder;
309
+ private int currentNesting = 0;
310
+ private final DoubleConverter dc;
311
+
312
+ // initialization value for all state variables.
313
+ // no idea about the origins of this value, ask Flori ;)
314
+ private static final int EVIL = 0x666;
315
+
316
+ private ParserSession(Parser parser, ThreadContext context) {
317
+ this.parser = parser;
318
+ this.context = context;
319
+ this.byteList = parser.checkAndGetSource().getByteList();
320
+ this.data = byteList.unsafeBytes();
321
+ this.view = new ByteList(data, false);
322
+ this.decoder = new StringDecoder(context);
323
+ this.dc = new DoubleConverter();
324
+ }
325
+
326
+ private RaiseException unexpectedToken(int absStart, int absEnd) {
327
+ RubyString msg = getRuntime().newString("unexpected token at '")
328
+ .cat(data, absStart, absEnd - absStart)
329
+ .cat((byte)'\'');
330
+ return newException(Utils.M_PARSER_ERROR, msg);
331
+ }
332
+
333
+ private Ruby getRuntime() {
334
+ return context.getRuntime();
335
+ }
336
+
337
+ %%{
338
+ machine JSON_common;
339
+
340
+ cr = '\n';
341
+ cr_neg = [^\n];
342
+ ws = [ \t\r\n];
343
+ c_comment = '/*' ( any* - (any* '*/' any* ) ) '*/';
344
+ cpp_comment = '//' cr_neg* cr;
345
+ comment = c_comment | cpp_comment;
346
+ ignore = ws | comment;
347
+ name_separator = ':';
348
+ value_separator = ',';
349
+ Vnull = 'null';
350
+ Vfalse = 'false';
351
+ Vtrue = 'true';
352
+ VNaN = 'NaN';
353
+ VInfinity = 'Infinity';
354
+ VMinusInfinity = '-Infinity';
355
+ begin_value = [nft"\-[{NI] | digit;
356
+ begin_object = '{';
357
+ end_object = '}';
358
+ begin_array = '[';
359
+ end_array = ']';
360
+ begin_string = '"';
361
+ begin_name = begin_string;
362
+ begin_number = digit | '-';
363
+ }%%
364
+
365
+ %%{
366
+ machine JSON_value;
367
+ include JSON_common;
368
+
369
+ write data;
370
+
371
+ action parse_null {
372
+ result = getRuntime().getNil();
373
+ }
374
+ action parse_false {
375
+ result = getRuntime().getFalse();
376
+ }
377
+ action parse_true {
378
+ result = getRuntime().getTrue();
379
+ }
380
+ action parse_nan {
381
+ if (parser.allowNaN) {
382
+ result = getConstant(CONST_NAN);
383
+ } else {
384
+ throw unexpectedToken(p - 2, pe);
385
+ }
386
+ }
387
+ action parse_infinity {
388
+ if (parser.allowNaN) {
389
+ result = getConstant(CONST_INFINITY);
390
+ } else {
391
+ throw unexpectedToken(p - 7, pe);
392
+ }
393
+ }
394
+ action parse_number {
395
+ if (pe > fpc + 9 - (parser.quirksMode ? 1 : 0) &&
396
+ absSubSequence(fpc, fpc + 9).equals(JSON_MINUS_INFINITY)) {
397
+
398
+ if (parser.allowNaN) {
399
+ result = getConstant(CONST_MINUS_INFINITY);
400
+ fexec p + 10;
401
+ fhold;
402
+ fbreak;
403
+ } else {
404
+ throw unexpectedToken(p, pe);
405
+ }
406
+ }
407
+ parseFloat(res, fpc, pe);
408
+ if (res.result != null) {
409
+ result = res.result;
410
+ fexec res.p;
411
+ }
412
+ parseInteger(res, fpc, pe);
413
+ if (res.result != null) {
414
+ result = res.result;
415
+ fexec res.p;
416
+ }
417
+ fhold;
418
+ fbreak;
419
+ }
420
+ action parse_string {
421
+ parseString(res, fpc, pe);
422
+ if (res.result == null) {
423
+ fhold;
424
+ fbreak;
425
+ } else {
426
+ result = res.result;
427
+ fexec res.p;
428
+ }
429
+ }
430
+ action parse_array {
431
+ currentNesting++;
432
+ parseArray(res, fpc, pe);
433
+ currentNesting--;
434
+ if (res.result == null) {
435
+ fhold;
436
+ fbreak;
437
+ } else {
438
+ result = res.result;
439
+ fexec res.p;
440
+ }
441
+ }
442
+ action parse_object {
443
+ currentNesting++;
444
+ parseObject(res, fpc, pe);
445
+ currentNesting--;
446
+ if (res.result == null) {
447
+ fhold;
448
+ fbreak;
449
+ } else {
450
+ result = res.result;
451
+ fexec res.p;
452
+ }
453
+ }
454
+ action exit {
455
+ fhold;
456
+ fbreak;
457
+ }
458
+
459
+ main := ( Vnull @parse_null |
460
+ Vfalse @parse_false |
461
+ Vtrue @parse_true |
462
+ VNaN @parse_nan |
463
+ VInfinity @parse_infinity |
464
+ begin_number >parse_number |
465
+ begin_string >parse_string |
466
+ begin_array >parse_array |
467
+ begin_object >parse_object
468
+ ) %*exit;
469
+ }%%
470
+
471
+ void parseValue(ParserResult res, int p, int pe) {
472
+ int cs = EVIL;
473
+ IRubyObject result = null;
474
+
475
+ %% write init;
476
+ %% write exec;
477
+
478
+ if (cs >= JSON_value_first_final && result != null) {
479
+ res.update(result, p);
480
+ } else {
481
+ res.update(null, p);
482
+ }
483
+ }
484
+
485
+ %%{
486
+ machine JSON_integer;
487
+
488
+ write data;
489
+
490
+ action exit {
491
+ fhold;
492
+ fbreak;
493
+ }
494
+
495
+ main := '-'? ( '0' | [1-9][0-9]* ) ( ^[0-9]? @exit );
496
+ }%%
497
+
498
+ void parseInteger(ParserResult res, int p, int pe) {
499
+ int new_p = parseIntegerInternal(p, pe);
500
+ if (new_p == -1) {
501
+ res.update(null, p);
502
+ return;
503
+ }
504
+ RubyInteger number = createInteger(p, new_p);
505
+ res.update(number, new_p + 1);
506
+ return;
507
+ }
508
+
509
+ int parseIntegerInternal(int p, int pe) {
510
+ int cs = EVIL;
511
+
512
+ %% write init;
513
+ int memo = p;
514
+ %% write exec;
515
+
516
+ if (cs < JSON_integer_first_final) {
517
+ return -1;
518
+ }
519
+
520
+ return p;
521
+ }
522
+
523
+ RubyInteger createInteger(int p, int new_p) {
524
+ Ruby runtime = getRuntime();
525
+ ByteList num = absSubSequence(p, new_p);
526
+ return bytesToInum(runtime, num);
527
+ }
528
+
529
+ RubyInteger bytesToInum(Ruby runtime, ByteList num) {
530
+ return runtime.is1_9() ?
531
+ ConvertBytes.byteListToInum19(runtime, num, 10, true) :
532
+ ConvertBytes.byteListToInum(runtime, num, 10, true);
533
+ }
534
+
535
+ %%{
536
+ machine JSON_float;
537
+ include JSON_common;
538
+
539
+ write data;
540
+
541
+ action exit {
542
+ fhold;
543
+ fbreak;
544
+ }
545
+
546
+ main := '-'?
547
+ ( ( ( '0' | [1-9][0-9]* ) '.' [0-9]+ ( [Ee] [+\-]?[0-9]+ )? )
548
+ | ( ( '0' | [1-9][0-9]* ) ( [Ee] [+\-]? [0-9]+ ) ) )
549
+ ( ^[0-9Ee.\-]? @exit );
550
+ }%%
551
+
552
+ void parseFloat(ParserResult res, int p, int pe) {
553
+ int new_p = parseFloatInternal(p, pe);
554
+ if (new_p == -1) {
555
+ res.update(null, p);
556
+ return;
557
+ }
558
+ RubyFloat number = createFloat(p, new_p);
559
+ res.update(number, new_p + 1);
560
+ return;
561
+ }
562
+
563
+ int parseFloatInternal(int p, int pe) {
564
+ int cs = EVIL;
565
+
566
+ %% write init;
567
+ int memo = p;
568
+ %% write exec;
569
+
570
+ if (cs < JSON_float_first_final) {
571
+ return -1;
572
+ }
573
+
574
+ return p;
575
+ }
576
+
577
+ RubyFloat createFloat(int p, int new_p) {
578
+ Ruby runtime = getRuntime();
579
+ ByteList num = absSubSequence(p, new_p);
580
+ return RubyFloat.newFloat(runtime, dc.parse(num, true, runtime.is1_9()));
581
+ }
582
+
583
+ %%{
584
+ machine JSON_string;
585
+ include JSON_common;
586
+
587
+ write data;
588
+
589
+ action parse_string {
590
+ int offset = byteList.begin();
591
+ ByteList decoded = decoder.decode(byteList, memo + 1 - offset,
592
+ p - offset);
593
+ result = getRuntime().newString(decoded);
594
+ if (result == null) {
595
+ fhold;
596
+ fbreak;
597
+ } else {
598
+ fexec p + 1;
599
+ }
600
+ }
601
+
602
+ action exit {
603
+ fhold;
604
+ fbreak;
605
+ }
606
+
607
+ main := '"'
608
+ ( ( ^(["\\]|0..0x1f)
609
+ | '\\'["\\/bfnrt]
610
+ | '\\u'[0-9a-fA-F]{4}
611
+ | '\\'^(["\\/bfnrtu]|0..0x1f)
612
+ )* %parse_string
613
+ ) '"' @exit;
614
+ }%%
615
+
616
+ void parseString(ParserResult res, int p, int pe) {
617
+ int cs = EVIL;
618
+ IRubyObject result = null;
619
+
620
+ %% write init;
621
+ int memo = p;
622
+ %% write exec;
623
+
624
+ if (parser.createAdditions) {
625
+ RubyHash match_string = parser.match_string;
626
+ if (match_string != null) {
627
+ final IRubyObject[] memoArray = { result, null };
628
+ try {
629
+ match_string.visitAll(new RubyHash.Visitor() {
630
+ @Override
631
+ public void visit(IRubyObject pattern, IRubyObject klass) {
632
+ if (pattern.callMethod(context, "===", memoArray[0]).isTrue()) {
633
+ memoArray[1] = klass;
634
+ throw JumpException.SPECIAL_JUMP;
635
+ }
636
+ }
637
+ });
638
+ } catch (JumpException e) { }
639
+ if (memoArray[1] != null) {
640
+ RubyClass klass = (RubyClass) memoArray[1];
641
+ if (klass.respondsTo("json_creatable?") &&
642
+ klass.callMethod(context, "json_creatable?").isTrue()) {
643
+ result = klass.callMethod(context, "json_create", result);
644
+ }
645
+ }
646
+ }
647
+ }
648
+
649
+ if (cs >= JSON_string_first_final && result != null) {
650
+ RuntimeInfo info = RuntimeInfo.forRuntime(context.getRuntime());
651
+ if (info.encodingsSupported() && result instanceof RubyString) {
652
+ ((RubyString)result).force_encoding(context, info.utf8.get());
653
+ }
654
+ res.update(result, p + 1);
655
+ } else {
656
+ res.update(null, p + 1);
657
+ }
658
+ }
659
+
660
+ %%{
661
+ machine JSON_array;
662
+ include JSON_common;
663
+
664
+ write data;
665
+
666
+ action parse_value {
667
+ parseValue(res, fpc, pe);
668
+ if (res.result == null) {
669
+ fhold;
670
+ fbreak;
671
+ } else {
672
+ if (parser.arrayClass == getRuntime().getArray()) {
673
+ ((RubyArray)result).append(res.result);
674
+ } else {
675
+ result.callMethod(context, "<<", res.result);
676
+ }
677
+ fexec res.p;
678
+ }
679
+ }
680
+
681
+ action exit {
682
+ fhold;
683
+ fbreak;
684
+ }
685
+
686
+ next_element = value_separator ignore* begin_value >parse_value;
687
+
688
+ main := begin_array
689
+ ignore*
690
+ ( ( begin_value >parse_value
691
+ ignore* )
692
+ ( ignore*
693
+ next_element
694
+ ignore* )* )?
695
+ ignore*
696
+ end_array @exit;
697
+ }%%
698
+
699
+ void parseArray(ParserResult res, int p, int pe) {
700
+ int cs = EVIL;
701
+
702
+ if (parser.maxNesting > 0 && currentNesting > parser.maxNesting) {
703
+ throw newException(Utils.M_NESTING_ERROR,
704
+ "nesting of " + currentNesting + " is too deep");
705
+ }
706
+
707
+ IRubyObject result;
708
+ if (parser.arrayClass == getRuntime().getArray()) {
709
+ result = RubyArray.newArray(getRuntime());
710
+ } else {
711
+ result = parser.arrayClass.newInstance(context,
712
+ IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
713
+ }
714
+
715
+ %% write init;
716
+ %% write exec;
717
+
718
+ if (cs >= JSON_array_first_final) {
719
+ res.update(result, p + 1);
720
+ } else {
721
+ throw unexpectedToken(p, pe);
722
+ }
723
+ }
724
+
725
+ %%{
726
+ machine JSON_object;
727
+ include JSON_common;
728
+
729
+ write data;
730
+
731
+ action parse_value {
732
+ parseValue(res, fpc, pe);
733
+ if (res.result == null) {
734
+ fhold;
735
+ fbreak;
736
+ } else {
737
+ if (parser.objectClass == getRuntime().getHash()) {
738
+ ((RubyHash)result).op_aset(context, lastName, res.result);
739
+ } else {
740
+ result.callMethod(context, "[]=", new IRubyObject[] { lastName, res.result });
741
+ }
742
+ fexec res.p;
743
+ }
744
+ }
745
+
746
+ action parse_name {
747
+ parseString(res, fpc, pe);
748
+ if (res.result == null) {
749
+ fhold;
750
+ fbreak;
751
+ } else {
752
+ RubyString name = (RubyString)res.result;
753
+ if (parser.symbolizeNames) {
754
+ lastName = context.getRuntime().is1_9()
755
+ ? name.intern19()
756
+ : name.intern();
757
+ } else {
758
+ lastName = name;
759
+ }
760
+ fexec res.p;
761
+ }
762
+ }
763
+
764
+ action exit {
765
+ fhold;
766
+ fbreak;
767
+ }
768
+
769
+ pair = ignore* begin_name >parse_name ignore* name_separator
770
+ ignore* begin_value >parse_value;
771
+ next_pair = ignore* value_separator pair;
772
+
773
+ main := (
774
+ begin_object (pair (next_pair)*)? ignore* end_object
775
+ ) @exit;
776
+ }%%
777
+
778
+ void parseObject(ParserResult res, int p, int pe) {
779
+ int cs = EVIL;
780
+ IRubyObject lastName = null;
781
+ boolean objectDefault = true;
782
+
783
+ if (parser.maxNesting > 0 && currentNesting > parser.maxNesting) {
784
+ throw newException(Utils.M_NESTING_ERROR,
785
+ "nesting of " + currentNesting + " is too deep");
786
+ }
787
+
788
+ // this is guaranteed to be a RubyHash due to the earlier
789
+ // allocator test at OptionsReader#getClass
790
+ IRubyObject result;
791
+ if (parser.objectClass == getRuntime().getHash()) {
792
+ result = RubyHash.newHash(getRuntime());
793
+ } else {
794
+ objectDefault = false;
795
+ result = parser.objectClass.newInstance(context,
796
+ IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
797
+ }
798
+
799
+ %% write init;
800
+ %% write exec;
801
+
802
+ if (cs < JSON_object_first_final) {
803
+ res.update(null, p + 1);
804
+ return;
805
+ }
806
+
807
+ IRubyObject returnedResult = result;
808
+
809
+ // attempt to de-serialize object
810
+ if (parser.createAdditions) {
811
+ IRubyObject vKlassName;
812
+ if (objectDefault) {
813
+ vKlassName = ((RubyHash)result).op_aref(context, parser.createId);
814
+ } else {
815
+ vKlassName = result.callMethod(context, "[]", parser.createId);
816
+ }
817
+
818
+ if (!vKlassName.isNil()) {
819
+ // might throw ArgumentError, we let it propagate
820
+ IRubyObject klass = parser.info.jsonModule.get().
821
+ callMethod(context, "deep_const_get", vKlassName);
822
+ if (klass.respondsTo("json_creatable?") &&
823
+ klass.callMethod(context, "json_creatable?").isTrue()) {
824
+
825
+ returnedResult = klass.callMethod(context, "json_create", result);
826
+ }
827
+ }
828
+ }
829
+ res.update(returnedResult, p + 1);
830
+ }
831
+
832
+ %%{
833
+ machine JSON;
834
+ include JSON_common;
835
+
836
+ write data;
837
+
838
+ action parse_object {
839
+ currentNesting = 1;
840
+ parseObject(res, fpc, pe);
841
+ if (res.result == null) {
842
+ fhold;
843
+ fbreak;
844
+ } else {
845
+ result = res.result;
846
+ fexec res.p;
847
+ }
848
+ }
849
+
850
+ action parse_array {
851
+ currentNesting = 1;
852
+ parseArray(res, fpc, pe);
853
+ if (res.result == null) {
854
+ fhold;
855
+ fbreak;
856
+ } else {
857
+ result = res.result;
858
+ fexec res.p;
859
+ }
860
+ }
861
+
862
+ main := ignore*
863
+ ( begin_object >parse_object
864
+ | begin_array >parse_array )
865
+ ignore*;
866
+ }%%
867
+
868
+ public IRubyObject parseStrict() {
869
+ int cs = EVIL;
870
+ int p, pe;
871
+ IRubyObject result = null;
872
+ ParserResult res = new ParserResult();
873
+
874
+ %% write init;
875
+ p = byteList.begin();
876
+ pe = p + byteList.length();
877
+ %% write exec;
878
+
879
+ if (cs >= JSON_first_final && p == pe) {
880
+ return result;
881
+ } else {
882
+ throw unexpectedToken(p, pe);
883
+ }
884
+ }
885
+
886
+ %%{
887
+ machine JSON_quirks_mode;
888
+ include JSON_common;
889
+
890
+ write data;
891
+
892
+ action parse_value {
893
+ parseValue(res, fpc, pe);
894
+ if (res.result == null) {
895
+ fhold;
896
+ fbreak;
897
+ } else {
898
+ result = res.result;
899
+ fexec res.p;
900
+ }
901
+ }
902
+
903
+ main := ignore*
904
+ ( begin_value >parse_value)
905
+ ignore*;
906
+ }%%
907
+
908
+ public IRubyObject parseQuirksMode() {
909
+ int cs = EVIL;
910
+ int p, pe;
911
+ IRubyObject result = null;
912
+ ParserResult res = new ParserResult();
913
+
914
+ %% write init;
915
+ p = byteList.begin();
916
+ pe = p + byteList.length();
917
+ %% write exec;
918
+
919
+ if (cs >= JSON_quirks_mode_first_final && p == pe) {
920
+ return result;
921
+ } else {
922
+ throw unexpectedToken(p, pe);
923
+ }
924
+ }
925
+
926
+ public IRubyObject parse() {
927
+ if (parser.quirksMode) {
928
+ return parseQuirksMode();
929
+ } else {
930
+ return parseStrict();
931
+ }
932
+
933
+ }
934
+
935
+ /**
936
+ * Updates the "view" bytelist with the new offsets and returns it.
937
+ * @param start
938
+ * @param end
939
+ */
940
+ private ByteList absSubSequence(int absStart, int absEnd) {
941
+ view.setBegin(absStart);
942
+ view.setRealSize(absEnd - absStart);
943
+ return view;
944
+ }
945
+
946
+ /**
947
+ * Retrieves a constant directly descended from the <code>JSON</code> module.
948
+ * @param name The constant name
949
+ */
950
+ private IRubyObject getConstant(String name) {
951
+ return parser.info.jsonModule.get().getConstant(name);
952
+ }
953
+
954
+ private RaiseException newException(String className, String message) {
955
+ return Utils.newException(context, className, message);
956
+ }
957
+
958
+ private RaiseException newException(String className, RubyString message) {
959
+ return Utils.newException(context, className, message);
960
+ }
961
+
962
+ private RaiseException newException(String className,
963
+ String messageBegin, ByteList messageEnd) {
964
+ return newException(className,
965
+ getRuntime().newString(messageBegin).cat(messageEnd));
966
+ }
967
+ }
968
+ }