json 1.8.3 → 2.3.0

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.
Files changed (82) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.travis.yml +9 -11
  4. data/{CHANGES → CHANGES.md} +186 -90
  5. data/Gemfile +10 -6
  6. data/{COPYING-json-jruby → LICENSE} +5 -6
  7. data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
  8. data/{README.rdoc → README.md} +185 -134
  9. data/Rakefile +41 -40
  10. data/VERSION +1 -1
  11. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  12. data/ext/json/ext/generator/generator.c +142 -101
  13. data/ext/json/ext/generator/generator.h +7 -2
  14. data/ext/json/ext/parser/extconf.rb +3 -0
  15. data/ext/json/ext/parser/parser.c +383 -463
  16. data/ext/json/ext/parser/parser.h +4 -5
  17. data/ext/json/ext/parser/parser.rl +141 -184
  18. data/ext/json/extconf.rb +0 -1
  19. data/java/src/json/ext/ByteListTranscoder.java +1 -2
  20. data/java/src/json/ext/Generator.java +44 -22
  21. data/java/src/json/ext/GeneratorMethods.java +1 -2
  22. data/java/src/json/ext/GeneratorService.java +1 -2
  23. data/java/src/json/ext/GeneratorState.java +3 -56
  24. data/java/src/json/ext/OptionsReader.java +2 -3
  25. data/java/src/json/ext/Parser.java +132 -415
  26. data/java/src/json/ext/Parser.rl +48 -124
  27. data/java/src/json/ext/ParserService.java +1 -2
  28. data/java/src/json/ext/RuntimeInfo.java +1 -6
  29. data/java/src/json/ext/StringDecoder.java +1 -2
  30. data/java/src/json/ext/StringEncoder.java +5 -0
  31. data/java/src/json/ext/Utils.java +1 -2
  32. data/json-java.gemspec +16 -2
  33. data/json.gemspec +0 -0
  34. data/json_pure.gemspec +24 -26
  35. data/lib/json/add/bigdecimal.rb +3 -2
  36. data/lib/json/add/complex.rb +4 -3
  37. data/lib/json/add/core.rb +1 -0
  38. data/lib/json/add/date.rb +1 -1
  39. data/lib/json/add/date_time.rb +1 -1
  40. data/lib/json/add/exception.rb +1 -1
  41. data/lib/json/add/ostruct.rb +3 -3
  42. data/lib/json/add/range.rb +1 -1
  43. data/lib/json/add/rational.rb +3 -2
  44. data/lib/json/add/regexp.rb +3 -3
  45. data/lib/json/add/set.rb +29 -0
  46. data/lib/json/add/struct.rb +1 -1
  47. data/lib/json/add/symbol.rb +1 -1
  48. data/lib/json/add/time.rb +1 -1
  49. data/lib/json/common.rb +26 -54
  50. data/lib/json/ext.rb +0 -6
  51. data/lib/json/generic_object.rb +5 -4
  52. data/lib/json/pure/generator.rb +63 -126
  53. data/lib/json/pure/parser.rb +41 -81
  54. data/lib/json/pure.rb +2 -8
  55. data/lib/json/version.rb +2 -1
  56. data/lib/json.rb +1 -0
  57. data/references/rfc7159.txt +899 -0
  58. data/tests/fixtures/obsolete_fail1.json +1 -0
  59. data/tests/{test_json_addition.rb → json_addition_test.rb} +32 -25
  60. data/tests/json_common_interface_test.rb +126 -0
  61. data/tests/json_encoding_test.rb +107 -0
  62. data/tests/json_ext_parser_test.rb +15 -0
  63. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +5 -8
  64. data/tests/{test_json_generate.rb → json_generator_test.rb} +123 -39
  65. data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
  66. data/tests/json_parser_test.rb +472 -0
  67. data/tests/json_string_matching_test.rb +38 -0
  68. data/tests/{setup_variant.rb → test_helper.rb} +6 -0
  69. data/tools/diff.sh +18 -0
  70. data/tools/fuzz.rb +1 -9
  71. metadata +30 -47
  72. data/COPYING +0 -58
  73. data/GPL +0 -340
  74. data/TODO +0 -1
  75. data/data/example.json +0 -1
  76. data/data/index.html +0 -38
  77. data/data/prototype.js +0 -4184
  78. data/tests/fixtures/fail1.json +0 -1
  79. data/tests/test_json.rb +0 -553
  80. data/tests/test_json_encoding.rb +0 -65
  81. data/tests/test_json_string_matching.rb +0 -39
  82. data/tests/test_json_unicode.rb +0 -72
@@ -1,13 +1,13 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
9
8
  import org.jruby.Ruby;
10
9
  import org.jruby.RubyArray;
10
+ import org.jruby.RubyBasicObject;
11
11
  import org.jruby.RubyBignum;
12
12
  import org.jruby.RubyBoolean;
13
13
  import org.jruby.RubyClass;
@@ -16,6 +16,7 @@ import org.jruby.RubyFloat;
16
16
  import org.jruby.RubyHash;
17
17
  import org.jruby.RubyNumeric;
18
18
  import org.jruby.RubyString;
19
+ import org.jruby.runtime.ClassIndex;
19
20
  import org.jruby.runtime.ThreadContext;
20
21
  import org.jruby.runtime.builtin.IRubyObject;
21
22
  import org.jruby.util.ByteList;
@@ -58,6 +59,19 @@ public final class Generator {
58
59
  return handler.generateNew(session, object);
59
60
  }
60
61
 
62
+ // NOTE: drop this once Ruby 1.9.3 support is gone!
63
+ private static final int FIXNUM = 1;
64
+ private static final int BIGNUM = 2;
65
+ private static final int ARRAY = 3;
66
+ private static final int STRING = 4;
67
+ private static final int NIL = 5;
68
+ private static final int TRUE = 6;
69
+ private static final int FALSE = 7;
70
+ private static final int HASH = 10;
71
+ private static final int FLOAT = 11;
72
+ // hard-coded due JRuby 1.7 compatibility
73
+ // https://github.com/jruby/jruby/blob/1.7.27/core/src/main/java/org/jruby/runtime/ClassIndex.java
74
+
61
75
  /**
62
76
  * Returns the best serialization handler for the given object.
63
77
  */
@@ -66,16 +80,24 @@ public final class Generator {
66
80
  @SuppressWarnings("unchecked")
67
81
  private static <T extends IRubyObject>
68
82
  Handler<? super T> getHandlerFor(Ruby runtime, T object) {
69
- RubyClass metaClass = object.getMetaClass();
70
- if (metaClass == runtime.getString()) return (Handler)STRING_HANDLER;
71
- if (metaClass == runtime.getFixnum()) return (Handler)FIXNUM_HANDLER;
72
- if (metaClass == runtime.getHash()) return (Handler)HASH_HANDLER;
73
- if (metaClass == runtime.getArray()) return (Handler)ARRAY_HANDLER;
74
- if (object.isNil()) return (Handler)NIL_HANDLER;
75
- if (object == runtime.getTrue()) return (Handler)TRUE_HANDLER;
76
- if (object == runtime.getFalse()) return (Handler)FALSE_HANDLER;
77
- if (metaClass == runtime.getFloat()) return (Handler)FLOAT_HANDLER;
78
- if (metaClass == runtime.getBignum()) return (Handler)BIGNUM_HANDLER;
83
+ switch (((RubyBasicObject) object).getNativeTypeIndex()) {
84
+ // can not use getNativeClassIndex due 1.7 compatibility
85
+ case NIL : return (Handler) NIL_HANDLER;
86
+ case TRUE : return (Handler) TRUE_HANDLER;
87
+ case FALSE : return (Handler) FALSE_HANDLER;
88
+ case FLOAT : return (Handler) FLOAT_HANDLER;
89
+ case FIXNUM : return (Handler) FIXNUM_HANDLER;
90
+ case BIGNUM : return (Handler) BIGNUM_HANDLER;
91
+ case STRING :
92
+ if (((RubyBasicObject) object).getMetaClass() != runtime.getString()) break;
93
+ return (Handler) STRING_HANDLER;
94
+ case ARRAY :
95
+ if (((RubyBasicObject) object).getMetaClass() != runtime.getArray()) break;
96
+ return (Handler) ARRAY_HANDLER;
97
+ case HASH :
98
+ if (((RubyBasicObject) object).getMetaClass() != runtime.getHash()) break;
99
+ return (Handler) HASH_HANDLER;
100
+ }
79
101
  return GENERIC_HANDLER;
80
102
  }
81
103
 
@@ -173,9 +195,7 @@ public final class Generator {
173
195
  result = RubyString.newString(session.getRuntime(), buffer);
174
196
  ThreadContext context = session.getContext();
175
197
  RuntimeInfo info = session.getInfo();
176
- if (info.encodingsSupported()) {
177
- result.force_encoding(context, info.utf8.get());
178
- }
198
+ result.force_encoding(context, info.utf8.get());
179
199
  return result;
180
200
  }
181
201
 
@@ -382,8 +402,7 @@ public final class Generator {
382
402
  RuntimeInfo info = session.getInfo();
383
403
  RubyString src;
384
404
 
385
- if (info.encodingsSupported() &&
386
- object.encoding(session.getContext()) != info.utf8.get()) {
405
+ if (object.encoding(session.getContext()) != info.utf8.get()) {
387
406
  src = (RubyString)object.encode(session.getContext(),
388
407
  info.utf8.get());
389
408
  } else {
@@ -428,11 +447,14 @@ public final class Generator {
428
447
  new Handler<IRubyObject>() {
429
448
  @Override
430
449
  RubyString generateNew(Session session, IRubyObject object) {
431
- IRubyObject result =
432
- object.callMethod(session.getContext(), "to_json",
433
- new IRubyObject[] {session.getState()});
434
- if (result instanceof RubyString) return (RubyString)result;
435
- throw session.getRuntime().newTypeError("to_json must return a String");
450
+ if (object.respondsTo("to_json")) {
451
+ IRubyObject result = object.callMethod(session.getContext(), "to_json",
452
+ new IRubyObject[] {session.getState()});
453
+ if (result instanceof RubyString) return (RubyString)result;
454
+ throw session.getRuntime().newTypeError("to_json must return a String");
455
+ } else {
456
+ return OBJECT_HANDLER.generateNew(session, object);
457
+ }
436
458
  }
437
459
 
438
460
  @Override
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
@@ -208,45 +207,11 @@ public class GeneratorState extends RubyObject {
208
207
  @JRubyMethod
209
208
  public IRubyObject generate(ThreadContext context, IRubyObject obj) {
210
209
  RubyString result = Generator.generateJson(context, obj, this);
211
- if (!quirksMode && !objectOrArrayLiteral(result)) {
212
- throw Utils.newException(context, Utils.M_GENERATOR_ERROR,
213
- "only generation of JSON objects or arrays allowed");
214
- }
215
210
  RuntimeInfo info = RuntimeInfo.forRuntime(context.getRuntime());
216
- if (info.encodingsSupported()) {
217
- result.force_encoding(context, info.utf8.get());
218
- }
211
+ result.force_encoding(context, info.utf8.get());
219
212
  return result;
220
213
  }
221
214
 
222
- /**
223
- * Ensures the given string is in the form "[...]" or "{...}", being
224
- * possibly surrounded by white space.
225
- * The string's encoding must be ASCII-compatible.
226
- * @param value
227
- * @return
228
- */
229
- private static boolean objectOrArrayLiteral(RubyString value) {
230
- ByteList bl = value.getByteList();
231
- int len = bl.length();
232
-
233
- for (int pos = 0; pos < len - 1; pos++) {
234
- int b = bl.get(pos);
235
- if (Character.isWhitespace(b)) continue;
236
-
237
- // match the opening brace
238
- switch (b) {
239
- case '[':
240
- return matchClosingBrace(bl, pos, len, ']');
241
- case '{':
242
- return matchClosingBrace(bl, pos, len, '}');
243
- default:
244
- return false;
245
- }
246
- }
247
- return false;
248
- }
249
-
250
215
  private static boolean matchClosingBrace(ByteList bl, int pos, int len,
251
216
  int brace) {
252
217
  for (int endPos = len - 1; endPos > pos; endPos--) {
@@ -399,17 +364,6 @@ public class GeneratorState extends RubyObject {
399
364
  return context.getRuntime().newBoolean(asciiOnly);
400
365
  }
401
366
 
402
- @JRubyMethod(name="quirks_mode")
403
- public RubyBoolean quirks_mode_get(ThreadContext context) {
404
- return context.getRuntime().newBoolean(quirksMode);
405
- }
406
-
407
- @JRubyMethod(name="quirks_mode=")
408
- public IRubyObject quirks_mode_set(IRubyObject quirks_mode) {
409
- quirksMode = quirks_mode.isTrue();
410
- return quirks_mode.getRuntime().newBoolean(quirksMode);
411
- }
412
-
413
367
  @JRubyMethod(name="buffer_initial_length")
414
368
  public RubyInteger buffer_initial_length_get(ThreadContext context) {
415
369
  return context.getRuntime().newFixnum(bufferInitialLength);
@@ -422,11 +376,6 @@ public class GeneratorState extends RubyObject {
422
376
  return buffer_initial_length;
423
377
  }
424
378
 
425
- @JRubyMethod(name="quirks_mode?")
426
- public RubyBoolean quirks_mode_p(ThreadContext context) {
427
- return context.getRuntime().newBoolean(quirksMode);
428
- }
429
-
430
379
  public int getDepth() {
431
380
  return depth;
432
381
  }
@@ -445,7 +394,7 @@ public class GeneratorState extends RubyObject {
445
394
  private ByteList prepareByteList(ThreadContext context, IRubyObject value) {
446
395
  RubyString str = value.convertToString();
447
396
  RuntimeInfo info = RuntimeInfo.forRuntime(context.getRuntime());
448
- if (info.encodingsSupported() && str.encoding(context) != info.utf8.get()) {
397
+ if (str.encoding(context) != info.utf8.get()) {
449
398
  str = (RubyString)str.encode(context, info.utf8.get());
450
399
  }
451
400
  return str.getByteList().dup();
@@ -481,7 +430,6 @@ public class GeneratorState extends RubyObject {
481
430
  maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
482
431
  allowNaN = opts.getBool("allow_nan", DEFAULT_ALLOW_NAN);
483
432
  asciiOnly = opts.getBool("ascii_only", DEFAULT_ASCII_ONLY);
484
- quirksMode = opts.getBool("quirks_mode", DEFAULT_QUIRKS_MODE);
485
433
  bufferInitialLength = opts.getInt("buffer_initial_length", DEFAULT_BUFFER_INITIAL_LENGTH);
486
434
 
487
435
  depth = opts.getInt("depth", 0);
@@ -508,7 +456,6 @@ public class GeneratorState extends RubyObject {
508
456
  result.op_aset(context, runtime.newSymbol("array_nl"), array_nl_get(context));
509
457
  result.op_aset(context, runtime.newSymbol("allow_nan"), allow_nan_p(context));
510
458
  result.op_aset(context, runtime.newSymbol("ascii_only"), ascii_only_p(context));
511
- result.op_aset(context, runtime.newSymbol("quirks_mode"), quirks_mode_p(context));
512
459
  result.op_aset(context, runtime.newSymbol("max_nesting"), max_nesting_get(context));
513
460
  result.op_aset(context, runtime.newSymbol("depth"), depth_get(context));
514
461
  result.op_aset(context, runtime.newSymbol("buffer_initial_length"), buffer_initial_length_get(context));
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
@@ -85,7 +84,7 @@ final class OptionsReader {
85
84
 
86
85
  RubyString str = value.convertToString();
87
86
  RuntimeInfo info = getRuntimeInfo();
88
- if (info.encodingsSupported() && str.encoding(context) != info.utf8.get()) {
87
+ if (str.encoding(context) != info.utf8.get()) {
89
88
  str = (RubyString)str.encode(context, info.utf8.get());
90
89
  }
91
90
  return str;