oj 3.11.5 → 3.16.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1421 -0
  3. data/README.md +19 -5
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +20 -6
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +10 -9
  9. data/ext/oj/circarray.c +8 -6
  10. data/ext/oj/circarray.h +2 -2
  11. data/ext/oj/code.c +19 -33
  12. data/ext/oj/code.h +2 -2
  13. data/ext/oj/compat.c +27 -77
  14. data/ext/oj/custom.c +86 -179
  15. data/ext/oj/debug.c +126 -0
  16. data/ext/oj/dump.c +256 -249
  17. data/ext/oj/dump.h +26 -12
  18. data/ext/oj/dump_compat.c +565 -642
  19. data/ext/oj/dump_leaf.c +17 -63
  20. data/ext/oj/dump_object.c +65 -187
  21. data/ext/oj/dump_strict.c +27 -51
  22. data/ext/oj/encoder.c +43 -0
  23. data/ext/oj/err.c +2 -13
  24. data/ext/oj/err.h +24 -8
  25. data/ext/oj/extconf.rb +21 -6
  26. data/ext/oj/fast.c +149 -149
  27. data/ext/oj/intern.c +313 -0
  28. data/ext/oj/intern.h +22 -0
  29. data/ext/oj/mem.c +318 -0
  30. data/ext/oj/mem.h +53 -0
  31. data/ext/oj/mimic_json.c +121 -106
  32. data/ext/oj/object.c +85 -162
  33. data/ext/oj/odd.c +89 -67
  34. data/ext/oj/odd.h +15 -15
  35. data/ext/oj/oj.c +542 -411
  36. data/ext/oj/oj.h +99 -73
  37. data/ext/oj/parse.c +175 -187
  38. data/ext/oj/parse.h +26 -24
  39. data/ext/oj/parser.c +1600 -0
  40. data/ext/oj/parser.h +101 -0
  41. data/ext/oj/rails.c +112 -159
  42. data/ext/oj/rails.h +1 -1
  43. data/ext/oj/reader.c +11 -14
  44. data/ext/oj/reader.h +4 -2
  45. data/ext/oj/resolve.c +5 -24
  46. data/ext/oj/rxclass.c +7 -6
  47. data/ext/oj/rxclass.h +1 -1
  48. data/ext/oj/saj.c +22 -33
  49. data/ext/oj/saj2.c +584 -0
  50. data/ext/oj/saj2.h +23 -0
  51. data/ext/oj/scp.c +5 -28
  52. data/ext/oj/sparse.c +28 -72
  53. data/ext/oj/stream_writer.c +50 -40
  54. data/ext/oj/strict.c +56 -61
  55. data/ext/oj/string_writer.c +72 -39
  56. data/ext/oj/trace.h +31 -4
  57. data/ext/oj/usual.c +1218 -0
  58. data/ext/oj/usual.h +69 -0
  59. data/ext/oj/util.h +1 -1
  60. data/ext/oj/val_stack.c +14 -3
  61. data/ext/oj/val_stack.h +8 -7
  62. data/ext/oj/validate.c +46 -0
  63. data/ext/oj/wab.c +63 -88
  64. data/lib/oj/active_support_helper.rb +1 -3
  65. data/lib/oj/bag.rb +7 -1
  66. data/lib/oj/easy_hash.rb +4 -5
  67. data/lib/oj/error.rb +1 -2
  68. data/lib/oj/json.rb +162 -150
  69. data/lib/oj/mimic.rb +9 -7
  70. data/lib/oj/saj.rb +20 -6
  71. data/lib/oj/schandler.rb +5 -4
  72. data/lib/oj/state.rb +12 -8
  73. data/lib/oj/version.rb +1 -2
  74. data/lib/oj.rb +2 -0
  75. data/pages/Compatibility.md +1 -1
  76. data/pages/InstallOptions.md +20 -0
  77. data/pages/JsonGem.md +15 -0
  78. data/pages/Modes.md +8 -3
  79. data/pages/Options.md +43 -5
  80. data/pages/Parser.md +309 -0
  81. data/pages/Rails.md +14 -2
  82. data/test/_test_active.rb +8 -9
  83. data/test/_test_active_mimic.rb +7 -8
  84. data/test/_test_mimic_rails.rb +17 -20
  85. data/test/activerecord/result_test.rb +5 -6
  86. data/test/activesupport6/encoding_test.rb +63 -28
  87. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  88. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  89. data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
  90. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  91. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  92. data/test/files.rb +15 -15
  93. data/test/foo.rb +16 -45
  94. data/test/helper.rb +11 -8
  95. data/test/isolated/shared.rb +3 -2
  96. data/test/json_gem/json_addition_test.rb +2 -2
  97. data/test/json_gem/json_common_interface_test.rb +8 -6
  98. data/test/json_gem/json_encoding_test.rb +0 -0
  99. data/test/json_gem/json_ext_parser_test.rb +1 -0
  100. data/test/json_gem/json_fixtures_test.rb +3 -2
  101. data/test/json_gem/json_generator_test.rb +56 -38
  102. data/test/json_gem/json_generic_object_test.rb +11 -11
  103. data/test/json_gem/json_parser_test.rb +54 -47
  104. data/test/json_gem/json_string_matching_test.rb +9 -9
  105. data/test/json_gem/test_helper.rb +7 -3
  106. data/test/mem.rb +34 -0
  107. data/test/perf.rb +22 -27
  108. data/test/perf_compat.rb +31 -33
  109. data/test/perf_dump.rb +50 -0
  110. data/test/perf_fast.rb +80 -82
  111. data/test/perf_file.rb +27 -29
  112. data/test/perf_object.rb +65 -69
  113. data/test/perf_once.rb +59 -0
  114. data/test/perf_parser.rb +183 -0
  115. data/test/perf_saj.rb +46 -54
  116. data/test/perf_scp.rb +58 -69
  117. data/test/perf_simple.rb +41 -39
  118. data/test/perf_strict.rb +74 -82
  119. data/test/perf_wab.rb +67 -69
  120. data/test/prec.rb +5 -5
  121. data/test/sample/change.rb +0 -1
  122. data/test/sample/dir.rb +0 -1
  123. data/test/sample/doc.rb +0 -1
  124. data/test/sample/file.rb +0 -1
  125. data/test/sample/group.rb +0 -1
  126. data/test/sample/hasprops.rb +0 -1
  127. data/test/sample/layer.rb +0 -1
  128. data/test/sample/rect.rb +0 -1
  129. data/test/sample/shape.rb +0 -1
  130. data/test/sample/text.rb +0 -1
  131. data/test/sample.rb +16 -16
  132. data/test/sample_json.rb +8 -8
  133. data/test/test_compat.rb +95 -43
  134. data/test/test_custom.rb +73 -51
  135. data/test/test_debian.rb +7 -10
  136. data/test/test_fast.rb +135 -79
  137. data/test/test_file.rb +41 -30
  138. data/test/test_gc.rb +16 -5
  139. data/test/test_generate.rb +5 -5
  140. data/test/test_hash.rb +5 -5
  141. data/test/test_integer_range.rb +9 -9
  142. data/test/test_null.rb +20 -20
  143. data/test/test_object.rb +99 -96
  144. data/test/test_parser.rb +11 -0
  145. data/test/test_parser_debug.rb +27 -0
  146. data/test/test_parser_saj.rb +337 -0
  147. data/test/test_parser_usual.rb +251 -0
  148. data/test/test_rails.rb +2 -2
  149. data/test/test_saj.rb +10 -8
  150. data/test/test_scp.rb +37 -39
  151. data/test/test_strict.rb +40 -32
  152. data/test/test_various.rb +165 -84
  153. data/test/test_wab.rb +48 -44
  154. data/test/test_writer.rb +47 -47
  155. data/test/tests.rb +13 -5
  156. data/test/tests_mimic.rb +12 -3
  157. data/test/tests_mimic_addition.rb +12 -3
  158. metadata +74 -128
  159. data/ext/oj/hash.c +0 -131
  160. data/ext/oj/hash.h +0 -19
  161. data/ext/oj/hash_test.c +0 -491
  162. data/test/activesupport4/decoding_test.rb +0 -108
  163. data/test/activesupport4/encoding_test.rb +0 -531
  164. data/test/activesupport4/test_helper.rb +0 -41
  165. data/test/activesupport5/test_helper.rb +0 -72
  166. data/test/bar.rb +0 -35
  167. data/test/baz.rb +0 -16
  168. data/test/zoo.rb +0 -13
data/ext/oj/usual.h ADDED
@@ -0,0 +1,69 @@
1
+ // Copyright (c) 2022, Peter Ohler, All rights reserved.
2
+
3
+ #include <ruby.h>
4
+ #include <stdbool.h>
5
+ #include <stdint.h>
6
+
7
+ struct _cache;
8
+ struct _ojParser;
9
+
10
+ // Used to mark the start of each Hash, Array, or Object. The members point at
11
+ // positions of the start in the value stack and if not an Array into the key
12
+ // stack.
13
+ typedef struct _col {
14
+ long vi; // value stack index
15
+ long ki; // key stack index if an hash else -1 for an array
16
+ } *Col;
17
+
18
+ typedef union _key {
19
+ struct {
20
+ int16_t len;
21
+ char buf[30];
22
+ };
23
+ struct {
24
+ int16_t xlen; // should be the same as len
25
+ char *key;
26
+ };
27
+ } *Key;
28
+
29
+ #define MISS_AUTO 'A'
30
+ #define MISS_RAISE 'R'
31
+ #define MISS_IGNORE 'I'
32
+
33
+ typedef struct _usual {
34
+ VALUE *vhead;
35
+ VALUE *vtail;
36
+ VALUE *vend;
37
+
38
+ Col chead;
39
+ Col ctail;
40
+ Col cend;
41
+
42
+ Key khead;
43
+ Key ktail;
44
+ Key kend;
45
+
46
+ VALUE (*get_key)(struct _ojParser *p, Key kp);
47
+ struct _cache *key_cache; // same as str_cache or sym_cache
48
+ struct _cache *str_cache;
49
+ struct _cache *sym_cache;
50
+ struct _cache *class_cache;
51
+ struct _cache *attr_cache;
52
+
53
+ VALUE array_class;
54
+ VALUE hash_class;
55
+
56
+ char *create_id;
57
+ uint8_t create_id_len;
58
+ uint8_t cache_str;
59
+ uint8_t cache_xrate;
60
+ uint8_t miss_class;
61
+ bool cache_keys;
62
+ bool ignore_json_create;
63
+ bool raise_on_empty;
64
+ } *Usual;
65
+
66
+ // Initialize the parser with the usual delegate. If the usual delegate is
67
+ // wrapped then this function is called first and then the parser functions
68
+ // can be replaced.
69
+ extern void oj_init_usual(struct _ojParser *p, Usual d);
data/ext/oj/util.h CHANGED
@@ -13,7 +13,7 @@ typedef struct _timeInfo {
13
13
  int day;
14
14
  int mon;
15
15
  int year;
16
- } * TimeInfo;
16
+ }* TimeInfo;
17
17
 
18
18
  extern void sec_as_time(int64_t secs, TimeInfo ti);
19
19
 
data/ext/oj/val_stack.c CHANGED
@@ -8,11 +8,11 @@
8
8
  #include "odd.h"
9
9
  #include "oj.h"
10
10
 
11
- static void mark(void *ptr) {
11
+ static void stack_mark(void *ptr) {
12
12
  ValStack stack = (ValStack)ptr;
13
13
  Val v;
14
14
 
15
- if (0 == ptr) {
15
+ if (NULL == ptr) {
16
16
  return;
17
17
  }
18
18
  #ifdef HAVE_PTHREAD_MUTEX_INIT
@@ -46,6 +46,17 @@ static void mark(void *ptr) {
46
46
  #endif
47
47
  }
48
48
 
49
+ static const rb_data_type_t oj_stack_type = {
50
+ "Oj/stack",
51
+ {
52
+ stack_mark,
53
+ NULL,
54
+ NULL,
55
+ },
56
+ 0,
57
+ 0,
58
+ };
59
+
49
60
  VALUE
50
61
  oj_stack_init(ValStack stack) {
51
62
  #ifdef HAVE_PTHREAD_MUTEX_INIT
@@ -70,7 +81,7 @@ oj_stack_init(ValStack stack) {
70
81
  stack->head->clen = 0;
71
82
  stack->head->next = NEXT_NONE;
72
83
 
73
- return Data_Wrap_Struct(oj_cstack_class, mark, 0, stack);
84
+ return TypedData_Wrap_Struct(oj_cstack_class, &oj_stack_type, stack);
74
85
  }
75
86
 
76
87
  const char *oj_stack_next_string(ValNext n) {
data/ext/oj/val_stack.h CHANGED
@@ -6,6 +6,7 @@
6
6
 
7
7
  #include <stdint.h>
8
8
 
9
+ #include "mem.h"
9
10
  #include "odd.h"
10
11
  #include "ruby.h"
11
12
  #ifdef HAVE_PTHREAD_MUTEX_INIT
@@ -28,10 +29,10 @@ typedef enum {
28
29
 
29
30
  typedef struct _val {
30
31
  volatile VALUE val;
31
- const char * key;
32
+ const char *key;
32
33
  char karray[32];
33
34
  volatile VALUE key_val;
34
- const char * classname;
35
+ const char *classname;
35
36
  VALUE clas;
36
37
  OddArgs odd_args;
37
38
  uint16_t klen;
@@ -39,7 +40,7 @@ typedef struct _val {
39
40
  char next; // ValNext
40
41
  char k1; // first original character in the key
41
42
  char kalloc;
42
- } * Val;
43
+ } *Val;
43
44
 
44
45
  typedef struct _valStack {
45
46
  struct _val base[STACK_INC];
@@ -52,7 +53,7 @@ typedef struct _valStack {
52
53
  VALUE mutex;
53
54
  #endif
54
55
 
55
- } * ValStack;
56
+ } *ValStack;
56
57
 
57
58
  extern VALUE oj_stack_init(ValStack stack);
58
59
 
@@ -62,7 +63,7 @@ inline static int stack_empty(ValStack stack) {
62
63
 
63
64
  inline static void stack_cleanup(ValStack stack) {
64
65
  if (stack->base != stack->head) {
65
- xfree(stack->head);
66
+ OJ_R_FREE(stack->head);
66
67
  stack->head = NULL;
67
68
  }
68
69
  }
@@ -76,10 +77,10 @@ inline static void stack_push(ValStack stack, VALUE val, ValNext next) {
76
77
  // A realloc can trigger a GC so make sure it happens outside the lock
77
78
  // but lock before changing pointers.
78
79
  if (stack->base == stack->head) {
79
- head = ALLOC_N(struct _val, len + STACK_INC);
80
+ head = OJ_R_ALLOC_N(struct _val, len + STACK_INC);
80
81
  memcpy(head, stack->base, sizeof(struct _val) * len);
81
82
  } else {
82
- REALLOC_N(head, struct _val, len + STACK_INC);
83
+ OJ_R_REALLOC_N(head, struct _val, len + STACK_INC);
83
84
  }
84
85
  #ifdef HAVE_PTHREAD_MUTEX_INIT
85
86
  pthread_mutex_lock(&stack->mutex);
data/ext/oj/validate.c ADDED
@@ -0,0 +1,46 @@
1
+ // Copyright (c) 2021, Peter Ohler, All rights reserved.
2
+
3
+ #include "parser.h"
4
+
5
+ static void noop(ojParser p) {
6
+ }
7
+
8
+ static VALUE option(ojParser p, const char *key, VALUE value) {
9
+ rb_raise(rb_eArgError, "%s is not an option for the validate delegate", key);
10
+ return Qnil;
11
+ }
12
+
13
+ static VALUE result(ojParser p) {
14
+ return Qnil;
15
+ }
16
+
17
+ static void dfree(ojParser p) {
18
+ }
19
+
20
+ static void mark(ojParser p) {
21
+ }
22
+
23
+ void oj_set_parser_validator(ojParser p) {
24
+ Funcs end = p->funcs + 3;
25
+ Funcs f;
26
+ p->ctx = NULL;
27
+
28
+ for (f = p->funcs; f < end; f++) {
29
+ f->add_null = noop;
30
+ f->add_true = noop;
31
+ f->add_false = noop;
32
+ f->add_int = noop;
33
+ f->add_float = noop;
34
+ f->add_big = noop;
35
+ f->add_str = noop;
36
+ f->open_array = noop;
37
+ f->close_array = noop;
38
+ f->open_object = noop;
39
+ f->close_object = noop;
40
+ }
41
+ p->option = option;
42
+ p->result = result;
43
+ p->free = dfree;
44
+ p->mark = mark;
45
+ p->start = noop;
46
+ }
data/ext/oj/wab.c CHANGED
@@ -10,6 +10,7 @@
10
10
  #include "dump.h"
11
11
  #include "encode.h"
12
12
  #include "err.h"
13
+ #include "intern.h"
13
14
  #include "oj.h"
14
15
  #include "parse.h"
15
16
  #include "trace.h"
@@ -34,7 +35,7 @@ static VALUE uri_http_clas = Qundef;
34
35
 
35
36
  ///// dump functions /////
36
37
 
37
- static VALUE resolve_wab_uuid_class() {
38
+ static VALUE resolve_wab_uuid_class(void) {
38
39
  if (Qundef == wab_uuid_clas) {
39
40
  volatile VALUE wab_module;
40
41
 
@@ -49,7 +50,7 @@ static VALUE resolve_wab_uuid_class() {
49
50
  return wab_uuid_clas;
50
51
  }
51
52
 
52
- static VALUE resolve_uri_class() {
53
+ static VALUE resolve_uri_class(void) {
53
54
  if (Qundef == uri_clas) {
54
55
  uri_clas = Qnil;
55
56
  if (rb_const_defined_at(rb_cObject, rb_intern("URI"))) {
@@ -59,7 +60,7 @@ static VALUE resolve_uri_class() {
59
60
  return uri_clas;
60
61
  }
61
62
 
62
- static VALUE resolve_uri_http_class() {
63
+ static VALUE resolve_uri_http_class(void) {
63
64
  if (Qundef == uri_http_clas) {
64
65
  volatile VALUE uri_module;
65
66
 
@@ -75,15 +76,13 @@ static VALUE resolve_uri_http_class() {
75
76
  }
76
77
 
77
78
  static void raise_wab(VALUE obj) {
78
- rb_raise(rb_eTypeError,
79
- "Failed to dump %s Object to JSON in wab mode.\n",
80
- rb_class2name(rb_obj_class(obj)));
79
+ rb_raise(rb_eTypeError, "Failed to dump %s Object to JSON in wab mode.\n", rb_class2name(rb_obj_class(obj)));
81
80
  }
82
81
 
83
82
  // Removed dependencies on math due to problems with CentOS 5.4.
84
83
  static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
85
84
  char buf[64];
86
- char * b;
85
+ char *b;
87
86
  double d = rb_num2dbl(obj);
88
87
  int cnt = 0;
89
88
 
@@ -123,11 +122,11 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
123
122
  *out->cur++ = ']';
124
123
  } else {
125
124
  size = d2 * out->indent + 2;
125
+ assure_size(out, size * cnt);
126
126
  cnt--;
127
127
  for (i = 0; i <= cnt; i++) {
128
- assure_size(out, size);
129
128
  fill_indent(out, d2);
130
- oj_dump_wab_val(rb_ary_entry(a, i), d2, out);
129
+ oj_dump_wab_val(RARRAY_AREF(a, i), d2, out);
131
130
  if (i < cnt) {
132
131
  *out->cur++ = ',';
133
132
  }
@@ -193,20 +192,15 @@ static void dump_time(VALUE obj, Out out) {
193
192
  time_t sec;
194
193
  long long nsec;
195
194
 
196
- #ifdef HAVE_RB_TIME_TIMESPEC
197
195
  if (16 <= sizeof(struct timespec)) {
198
196
  struct timespec ts = rb_time_timespec(obj);
199
197
 
200
198
  sec = ts.tv_sec;
201
199
  nsec = ts.tv_nsec;
202
200
  } else {
203
- sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
204
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
201
+ sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
202
+ nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
205
203
  }
206
- #else
207
- sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
208
- nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
209
- #endif
210
204
 
211
205
  assure_size(out, 36);
212
206
  // 2012-01-05T23:58:07.123456000Z
@@ -230,13 +224,13 @@ static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
230
224
  if (rb_cTime == clas) {
231
225
  dump_time(obj, out);
232
226
  } else if (oj_bigdecimal_class == clas) {
233
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
227
+ volatile VALUE rstr = oj_safe_string_convert(obj);
234
228
 
235
- oj_dump_raw(rb_string_value_ptr((VALUE *)&rstr), (int)RSTRING_LEN(rstr), out);
229
+ oj_dump_raw(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), out);
236
230
  } else if (resolve_wab_uuid_class() == clas) {
237
- oj_dump_str(rb_funcall(obj, oj_to_s_id, 0), depth, out, false);
231
+ oj_dump_str(oj_safe_string_convert(obj), depth, out, false);
238
232
  } else if (resolve_uri_http_class() == clas) {
239
- oj_dump_str(rb_funcall(obj, oj_to_s_id, 0), depth, out, false);
233
+ oj_dump_str(oj_safe_string_convert(obj), depth, out, false);
240
234
  } else {
241
235
  raise_wab(obj);
242
236
  }
@@ -270,9 +264,7 @@ static DumpFunc wab_funcs[] = {
270
264
  void oj_dump_wab_val(VALUE obj, int depth, Out out) {
271
265
  int type = rb_type(obj);
272
266
 
273
- if (Yes == out->opts->trace) {
274
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
275
- }
267
+ TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
276
268
  if (MAX_DEPTH < depth) {
277
269
  rb_raise(rb_eNoMemError, "Too deeply nested.\n");
278
270
  }
@@ -281,9 +273,7 @@ void oj_dump_wab_val(VALUE obj, int depth, Out out) {
281
273
 
282
274
  if (NULL != f) {
283
275
  f(obj, depth, out, false);
284
- if (Yes == out->opts->trace) {
285
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
286
- }
276
+ TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
287
277
  return;
288
278
  }
289
279
  }
@@ -292,16 +282,35 @@ void oj_dump_wab_val(VALUE obj, int depth, Out out) {
292
282
 
293
283
  ///// load functions /////
294
284
 
295
- static void hash_end(ParseInfo pi) {
296
- if (Yes == pi->options.trace) {
297
- oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
285
+ static VALUE calc_hash_key(ParseInfo pi, Val parent) {
286
+ volatile VALUE rkey = parent->key_val;
287
+
288
+ if (Qundef != rkey) {
289
+ rkey = oj_encode(rkey);
290
+ rkey = rb_str_intern(rkey);
291
+
292
+ return rkey;
298
293
  }
294
+ if (Yes == pi->options.cache_keys) {
295
+ rkey = oj_sym_intern(parent->key, parent->klen);
296
+ } else {
297
+ #if HAVE_RB_ENC_INTERNED_STR
298
+ rkey = rb_enc_interned_str(parent->key, parent->klen, oj_utf8_encoding);
299
+ #else
300
+ rkey = rb_utf8_str_new(parent->key, parent->klen);
301
+ rkey = rb_str_intern(rkey);
302
+ OBJ_FREEZE(rkey);
303
+ #endif
304
+ }
305
+ return rkey;
306
+ }
307
+
308
+ static void hash_end(ParseInfo pi) {
309
+ TRACE_PARSE_HASH_END(pi->options.trace, pi);
299
310
  }
300
311
 
301
312
  static void array_end(ParseInfo pi) {
302
- if (Yes == pi->options.trace) {
303
- oj_trace_parse_array_end(pi, __FILE__, __LINE__);
304
- }
313
+ TRACE_PARSE_ARRAY_END(pi->options.trace, pi);
305
314
  }
306
315
 
307
316
  static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
@@ -309,9 +318,7 @@ static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
309
318
  }
310
319
 
311
320
  static void add_value(ParseInfo pi, VALUE val) {
312
- if (Yes == pi->options.trace) {
313
- oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
314
- }
321
+ TRACE_PARSE_CALL(pi->options.trace, "add_value", pi, val);
315
322
  pi->stack.head->val = val;
316
323
  }
317
324
 
@@ -432,36 +439,34 @@ static VALUE protect_uri(VALUE rstr) {
432
439
  return rb_funcall(resolve_uri_class(), oj_parse_id, 1, rstr);
433
440
  }
434
441
 
435
- static VALUE cstr_to_rstr(const char *str, size_t len) {
442
+ static VALUE cstr_to_rstr(ParseInfo pi, const char *str, size_t len) {
436
443
  volatile VALUE v = Qnil;
437
444
 
438
- if (30 == len && '-' == str[4] && '-' == str[7] && 'T' == str[10] && ':' == str[13] &&
439
- ':' == str[16] && '.' == str[19] && 'Z' == str[29]) {
445
+ if (30 == len && '-' == str[4] && '-' == str[7] && 'T' == str[10] && ':' == str[13] && ':' == str[16] &&
446
+ '.' == str[19] && 'Z' == str[29]) {
440
447
  if (Qnil != (v = time_parse(str, (int)len))) {
441
448
  return v;
442
449
  }
443
450
  }
444
- if (36 == len && '-' == str[8] && '-' == str[13] && '-' == str[18] && '-' == str[23] &&
445
- uuid_check(str, (int)len) && Qnil != resolve_wab_uuid_class()) {
451
+ if (36 == len && '-' == str[8] && '-' == str[13] && '-' == str[18] && '-' == str[23] && uuid_check(str, (int)len) &&
452
+ Qnil != resolve_wab_uuid_class()) {
446
453
  return rb_funcall(wab_uuid_clas, oj_new_id, 1, rb_str_new(str, len));
447
454
  }
448
- v = rb_str_new(str, len);
449
455
  if (7 < len && 0 == strncasecmp("http://", str, 7)) {
450
- int err = 0;
456
+ int err = 0;
457
+ v = rb_str_new(str, len);
451
458
  volatile VALUE uri = rb_protect(protect_uri, v, &err);
452
459
 
453
460
  if (0 == err) {
454
461
  return uri;
455
462
  }
456
463
  }
457
- return oj_encode(v);
464
+ return oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
458
465
  }
459
466
 
460
467
  static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
461
- pi->stack.head->val = cstr_to_rstr(str, len);
462
- if (Yes == pi->options.trace) {
463
- oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
464
- }
468
+ pi->stack.head->val = cstr_to_rstr(pi, str, len);
469
+ TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, pi->stack.head->val);
465
470
  }
466
471
 
467
472
  static void add_num(ParseInfo pi, NumInfo ni) {
@@ -469,40 +474,22 @@ static void add_num(ParseInfo pi, NumInfo ni) {
469
474
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
470
475
  }
471
476
  pi->stack.head->val = oj_num_as_value(ni);
472
- if (Yes == pi->options.trace) {
473
- oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
474
- }
477
+ TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, pi->stack.head->val);
475
478
  }
476
479
 
477
480
  static VALUE start_hash(ParseInfo pi) {
478
- if (Yes == pi->options.trace) {
479
- oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
480
- }
481
+ TRACE_PARSE_IN(pi->options.trace, "start_hash", pi);
481
482
  if (Qnil != pi->options.hash_class) {
482
483
  return rb_class_new_instance(0, NULL, pi->options.hash_class);
483
484
  }
484
485
  return rb_hash_new();
485
486
  }
486
487
 
487
- static VALUE calc_hash_key(ParseInfo pi, Val parent) {
488
- volatile VALUE rkey = parent->key_val;
489
-
490
- if (Qundef == rkey) {
491
- rkey = rb_str_new(parent->key, parent->klen);
492
- }
493
- rkey = oj_encode(rkey);
494
- rkey = rb_str_intern(rkey);
495
-
496
- return rkey;
497
- }
498
-
499
488
  static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
500
- volatile VALUE rval = cstr_to_rstr(str, len);
489
+ volatile VALUE rval = cstr_to_rstr(pi, str, len);
501
490
 
502
491
  rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
503
- if (Yes == pi->options.trace) {
504
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
505
- }
492
+ TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rval);
506
493
  }
507
494
 
508
495
  static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
@@ -513,32 +500,24 @@ static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
513
500
  }
514
501
  rval = oj_num_as_value(ni);
515
502
  rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
516
- if (Yes == pi->options.trace) {
517
- oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
518
- }
503
+ TRACE_PARSE_CALL(pi->options.trace, "set_number", pi, rval);
519
504
  }
520
505
 
521
506
  static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
522
507
  rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
523
- if (Yes == pi->options.trace) {
524
- oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
525
- }
508
+ TRACE_PARSE_CALL(pi->options.trace, "set_value", pi, value);
526
509
  }
527
510
 
528
511
  static VALUE start_array(ParseInfo pi) {
529
- if (Yes == pi->options.trace) {
530
- oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
531
- }
512
+ TRACE_PARSE_IN(pi->options.trace, "start_array", pi);
532
513
  return rb_ary_new();
533
514
  }
534
515
 
535
516
  static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
536
- volatile VALUE rval = cstr_to_rstr(str, len);
517
+ volatile VALUE rval = cstr_to_rstr(pi, str, len);
537
518
 
538
519
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
539
- if (Yes == pi->options.trace) {
540
- oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, rval);
541
- }
520
+ TRACE_PARSE_CALL(pi->options.trace, "set_value", pi, rval);
542
521
  }
543
522
 
544
523
  static void array_append_num(ParseInfo pi, NumInfo ni) {
@@ -549,16 +528,12 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
549
528
  }
550
529
  rval = oj_num_as_value(ni);
551
530
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
552
- if (Yes == pi->options.trace) {
553
- oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
554
- }
531
+ TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, rval);
555
532
  }
556
533
 
557
534
  static void array_append_value(ParseInfo pi, VALUE value) {
558
535
  rb_ary_push(stack_peek(&pi->stack)->val, value);
559
- if (Yes == pi->options.trace) {
560
- oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
561
- }
536
+ TRACE_PARSE_CALL(pi->options.trace, "append_value", pi, value);
562
537
  }
563
538
 
564
539
  void oj_set_wab_callbacks(ParseInfo pi) {
@@ -1,16 +1,14 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  require 'active_support/time'
3
4
 
4
5
  module Oj
5
-
6
6
  # Exists only to handle the ActiveSupport::TimeWithZone.
7
7
  class ActiveSupportHelper
8
-
9
8
  def self.createTimeWithZone(utc, zone)
10
9
  ActiveSupport::TimeWithZone.new(utc - utc.gmt_offset, ActiveSupport::TimeZone[zone])
11
10
  end
12
11
  end
13
-
14
12
  end
15
13
 
16
14
  Oj.register_odd(ActiveSupport::TimeWithZone, Oj::ActiveSupportHelper, :createTimeWithZone, :utc, 'time_zone.name')
data/lib/oj/bag.rb CHANGED
@@ -15,7 +15,7 @@ module Oj
15
15
  # @example Oj::Bag.new(:@x => 42, :@y => 57)
16
16
  # @param [Hash] args instance variable symbols and their values
17
17
  def initialize(args = {})
18
- args.each do |k,v|
18
+ args.each do |k, v|
19
19
  self.instance_variable_set(k, v)
20
20
  end
21
21
  end
@@ -26,6 +26,7 @@ module Oj
26
26
  # variable reader, otherwise false.
27
27
  def respond_to?(m)
28
28
  return true if super
29
+
29
30
  instance_variables.include?(:"@#{m}")
30
31
  end
31
32
 
@@ -37,8 +38,10 @@ module Oj
37
38
  # @raise [NoMethodError] if the instance variable is not defined.
38
39
  def method_missing(m, *args, &block)
39
40
  raise ArgumentError.new("wrong number of arguments (#{args.size} for 0) to method #{m}") unless args.nil? or args.empty?
41
+
40
42
  at_m = :"@#{m}"
41
43
  raise NoMethodError.new("undefined method #{m}", m) unless instance_variable_defined?(at_m)
44
+
42
45
  instance_variable_get(at_m)
43
46
  end
44
47
 
@@ -47,9 +50,11 @@ module Oj
47
50
  # @return [Boolean] true if each variable and value are the same, otherwise false.
48
51
  def eql?(other)
49
52
  return false if (other.nil? or self.class != other.class)
53
+
50
54
  ova = other.instance_variables
51
55
  iv = instance_variables
52
56
  return false if ova.size != iv.size
57
+
53
58
  iv.all? { |vid| instance_variable_get(vid) != other.instance_variable_get(vid) }
54
59
  end
55
60
  alias == eql?
@@ -65,6 +70,7 @@ module Oj
65
70
  classname = classname.to_s unless classname.is_a?(String)
66
71
  tokens = classname.split('::').map(&:to_sym)
67
72
  raise NameError.new("Invalid classname '#{classname}") if tokens.empty?
73
+
68
74
  m = Object
69
75
  tokens[0..-2].each do |sym|
70
76
  if m.const_defined?(sym)
data/lib/oj/easy_hash.rb CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  module Oj
3
2
 
4
3
  # A Hash subclass that normalizes the hash keys to allow lookup by the
@@ -6,10 +5,6 @@ module Oj
6
5
  # that match the keys.
7
6
  class EasyHash < Hash
8
7
 
9
- # Initializes the instance to an empty Hash.
10
- def initialize()
11
- end
12
-
13
8
  # Replaces the Object.respond_to?() method.
14
9
  # @param [Symbol] m method symbol
15
10
  # @param [Boolean] include_all whether to include private and protected methods in the search
@@ -19,12 +14,14 @@ module Oj
19
14
  return true if super
20
15
  return true if has_key?(m)
21
16
  return true if has_key?(m.to_s)
17
+
22
18
  has_key?(m.to_sym)
23
19
  end
24
20
 
25
21
  def [](key)
26
22
  return fetch(key, nil) if has_key?(key)
27
23
  return fetch(key.to_s, nil) if has_key?(key.to_s)
24
+
28
25
  fetch(key.to_sym, nil)
29
26
  end
30
27
 
@@ -36,9 +33,11 @@ module Oj
36
33
  def method_missing(m, *args, &block)
37
34
  if m.to_s.end_with?('=')
38
35
  raise ArgumentError.new("wrong number of arguments (#{args.size} for 1 with #{m}) to method #{m}") if args.nil? or 1 != args.length
36
+
39
37
  m = m[0..-2]
40
38
  return store(m.to_s, args[0]) if has_key?(m.to_s)
41
39
  return store(m.to_sym, args[0]) if has_key?(m.to_sym)
40
+
42
41
  return store(m, args[0])
43
42
  else
44
43
  raise ArgumentError.new("wrong number of arguments (#{args.size} for 0 with #{m}) to method #{m}") unless args.nil? or args.empty?
data/lib/oj/error.rb CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  module Oj
3
2
 
4
3
  # Inherit Error class from StandardError.
@@ -16,7 +15,7 @@ module Oj
16
15
  # An Exception that is raised if a file fails to load.
17
16
  LoadError = Class.new(Error)
18
17
 
19
- # An Exception that is raised if there is a conflict with mimicing JSON
18
+ # An Exception that is raised if there is a conflict with mimicking JSON
20
19
  MimicError = Class.new(Error)
21
20
 
22
21
  end # Oj