oj 3.7.4 → 3.11.2

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -4
  3. data/ext/oj/buf.h +6 -34
  4. data/ext/oj/cache8.c +3 -3
  5. data/ext/oj/cache8.h +5 -33
  6. data/ext/oj/circarray.c +5 -9
  7. data/ext/oj/circarray.h +5 -8
  8. data/ext/oj/code.c +3 -6
  9. data/ext/oj/code.h +7 -10
  10. data/ext/oj/compat.c +11 -14
  11. data/ext/oj/custom.c +108 -75
  12. data/ext/oj/dump.c +132 -92
  13. data/ext/oj/dump.h +6 -7
  14. data/ext/oj/dump_compat.c +37 -34
  15. data/ext/oj/dump_leaf.c +3 -6
  16. data/ext/oj/dump_object.c +23 -17
  17. data/ext/oj/dump_strict.c +7 -9
  18. data/ext/oj/encode.h +6 -32
  19. data/ext/oj/err.c +2 -5
  20. data/ext/oj/err.h +6 -34
  21. data/ext/oj/extconf.rb +6 -0
  22. data/ext/oj/fast.c +39 -56
  23. data/ext/oj/hash.c +11 -39
  24. data/ext/oj/hash.h +5 -33
  25. data/ext/oj/hash_test.c +3 -31
  26. data/ext/oj/mimic_json.c +65 -44
  27. data/ext/oj/object.c +38 -69
  28. data/ext/oj/odd.c +18 -17
  29. data/ext/oj/odd.h +6 -9
  30. data/ext/oj/oj.c +139 -93
  31. data/ext/oj/oj.h +43 -35
  32. data/ext/oj/parse.c +164 -60
  33. data/ext/oj/parse.h +30 -31
  34. data/ext/oj/rails.c +119 -83
  35. data/ext/oj/rails.h +4 -7
  36. data/ext/oj/reader.c +5 -8
  37. data/ext/oj/reader.h +7 -10
  38. data/ext/oj/resolve.c +4 -7
  39. data/ext/oj/resolve.h +4 -7
  40. data/ext/oj/rxclass.c +8 -11
  41. data/ext/oj/rxclass.h +8 -11
  42. data/ext/oj/saj.c +9 -12
  43. data/ext/oj/scp.c +4 -7
  44. data/ext/oj/sparse.c +67 -33
  45. data/ext/oj/stream_writer.c +16 -15
  46. data/ext/oj/strict.c +9 -12
  47. data/ext/oj/string_writer.c +27 -8
  48. data/ext/oj/trace.c +5 -8
  49. data/ext/oj/trace.h +9 -12
  50. data/ext/oj/util.c +136 -0
  51. data/ext/oj/util.h +19 -0
  52. data/ext/oj/val_stack.c +28 -36
  53. data/ext/oj/val_stack.h +19 -50
  54. data/ext/oj/wab.c +29 -29
  55. data/lib/oj.rb +0 -8
  56. data/lib/oj/json.rb +1 -1
  57. data/lib/oj/mimic.rb +46 -2
  58. data/lib/oj/version.rb +2 -2
  59. data/pages/Modes.md +47 -45
  60. data/pages/Options.md +43 -10
  61. data/pages/Rails.md +60 -21
  62. data/pages/Security.md +1 -1
  63. data/test/activesupport5/abstract_unit.rb +45 -0
  64. data/test/activesupport5/decoding_test.rb +68 -60
  65. data/test/activesupport5/encoding_test.rb +111 -96
  66. data/test/activesupport5/encoding_test_cases.rb +33 -25
  67. data/test/activesupport5/test_helper.rb +43 -21
  68. data/test/activesupport5/time_zone_test_helpers.rb +18 -3
  69. data/test/activesupport6/abstract_unit.rb +44 -0
  70. data/test/activesupport6/decoding_test.rb +133 -0
  71. data/test/activesupport6/encoding_test.rb +507 -0
  72. data/test/activesupport6/encoding_test_cases.rb +98 -0
  73. data/test/activesupport6/test_common.rb +17 -0
  74. data/test/activesupport6/test_helper.rb +163 -0
  75. data/test/activesupport6/time_zone_test_helpers.rb +39 -0
  76. data/test/bar.rb +24 -6
  77. data/test/baz.rb +16 -0
  78. data/test/foo.rb +26 -57
  79. data/test/helper.rb +10 -0
  80. data/test/json_gem/json_common_interface_test.rb +8 -3
  81. data/test/json_gem/json_generator_test.rb +15 -3
  82. data/test/json_gem/test_helper.rb +8 -0
  83. data/test/prec.rb +23 -0
  84. data/test/sample_json.rb +1 -1
  85. data/test/test_compat.rb +21 -10
  86. data/test/test_custom.rb +135 -8
  87. data/test/test_integer_range.rb +1 -2
  88. data/test/test_object.rb +35 -2
  89. data/test/test_rails.rb +35 -0
  90. data/test/test_strict.rb +24 -1
  91. data/test/test_various.rb +52 -63
  92. data/test/test_writer.rb +19 -2
  93. data/test/tests.rb +1 -0
  94. data/test/zoo.rb +13 -0
  95. metadata +100 -75
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 63afe8de8789be3dcae927133f970ce4c1ebcf2a95e559fd74d001002f21a976
4
- data.tar.gz: 241ad4cdb767fbaa9b39eb3772748db8217d0a3bf9545300ff63d16722abf826
3
+ metadata.gz: 9deb076071bb73df196bc549faa4fc56d42eb8417b70c6a6d050ec086b04a89a
4
+ data.tar.gz: 0d6f76b98e0e44d639a32b48959ac8aec6316e9b7726190056adc1022b8dac00
5
5
  SHA512:
6
- metadata.gz: c8b9183590f1ca6673d53c5e885afa958164ea0b7ad1e6ade77d5527ecad0d56ea2e9738daa85707c1f2d5fedb7c23779bc4b932a4345ca9f63e8e6520e579b5
7
- data.tar.gz: 3a51f9db59bdf848f16eed3ddc24ebe1c9d96d408fd0ec11f513c335c85deb79cf2c6b2c7f587f2acc9f9fa77510f51094331fba1150993b6d396b8f4774336e
6
+ metadata.gz: 0f856c84593191e1eddb72f85187c68c961f248d7e6ecac817f8fbfbba5d6bfbcf46a2691d6eacd307f51ed91a8a8bf637d97f76ab428d11e72b8760c59a35cc
7
+ data.tar.gz: 18498cc7854a8aace3beaab7d603361acd43545c8dbb8e73dddccee0ebe96aff9d47ca6635b9a7198e37288aa62366f1d81364a4e4be88117866543c773c40ee
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # [![{}j](http://www.ohler.com/dev/images/oj_comet_64.svg)](http://www.ohler.com/oj) gem
2
2
 
3
- [![Build Status](https://img.shields.io/travis/ohler55/oj/master.svg)](http://travis-ci.org/ohler55/oj?branch=master) [![AppVeyor](https://img.shields.io/appveyor/ci/ohler55/oj/master.svg)](https://ci.appveyor.com/project/ohler55/oj) ![Gem](https://img.shields.io/gem/v/oj.svg) ![Gem](https://img.shields.io/gem/dt/oj.svg) [![SemVer compatibility](https://api.dependabot.com/badges/compatibility_score?dependency-name=oj&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver) [![TideLift](https://tidelift.com/badges/github/ohler55/oj)](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
3
+ [![Build Status](https://img.shields.io/travis/ohler55/oj/master.svg?logo=travis)](http://travis-ci.org/ohler55/oj?branch=master) ![Gem](https://img.shields.io/gem/v/oj.svg) ![Gem](https://img.shields.io/gem/dt/oj.svg) [![SemVer compatibility](https://api.dependabot.com/badges/compatibility_score?dependency-name=oj&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver) [![TideLift](https://tidelift.com/badges/github/ohler55/oj)](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
4
4
 
5
5
  A *fast* JSON parser and Object marshaller as a Ruby gem.
6
6
 
@@ -42,7 +42,7 @@ gem 'oj'
42
42
 
43
43
  ## Support
44
44
 
45
- [Get supported Oj with a Tidelift Subscription.](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
45
+ [Get supported Oj with a Tidelift Subscription.](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme) Security updates are [supported](https://tidelift.com/security).
46
46
 
47
47
  ## Further Reading
48
48
 
@@ -65,7 +65,7 @@ See [{file:CHANGELOG.md}](CHANGELOG.md)
65
65
 
66
66
  ## Links
67
67
 
68
- - *Documentation*: http://www.ohler.com/oj/doc, http://rubydoc.info/gems/oj
68
+ - *Documentation*: http://www.ohler.com/oj/doc, http://rubydoc.info/gems/oj
69
69
 
70
70
  - *GitHub* *repo*: https://github.com/ohler55/oj
71
71
 
@@ -93,4 +93,12 @@ Follow [@peterohler on Twitter](http://twitter.com/peterohler) for announcements
93
93
 
94
94
  - *OjC, a C JSON parser*: https://www.ohler.com/ojc also at https://github.com/ohler55/ojc
95
95
 
96
- - *Piper Push Cache, push JSON to browsers*: http://www.piperpushcache.com
96
+ - *Agoo, a high performance Ruby web server supporting GraphQL on GitHub*: https://github.com/ohler55/agoo
97
+
98
+ - *Agoo-C, a high performance C web server supporting GraphQL on GitHub*: https://github.com/ohler55/agoo-c
99
+
100
+ #### Contributing
101
+
102
+ + Provide a Pull Request off the `develop` branch.
103
+ + Report a bug
104
+ + Suggest an idea
data/ext/oj/buf.h CHANGED
@@ -1,39 +1,11 @@
1
- /* buf.h
2
- * Copyright (c) 2011, Peter Ohler
3
- * All rights reserved.
4
- *
5
- * Redistribution and use in source and binary forms, with or without
6
- * modification, are permitted provided that the following conditions are met:
7
- *
8
- * - Redistributions of source code must retain the above copyright notice, this
9
- * list of conditions and the following disclaimer.
10
- *
11
- * - Redistributions in binary form must reproduce the above copyright notice,
12
- * this list of conditions and the following disclaimer in the documentation
13
- * and/or other materials provided with the distribution.
14
- *
15
- * - Neither the name of Peter Ohler nor the names of its contributors may be
16
- * used to endorse or promote products derived from this software without
17
- * specific prior written permission.
18
- *
19
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
- */
1
+ // Copyright (c) 2011 Peter Ohler. All rights reserved.
30
2
 
31
- #ifndef __OJ_BUF_H__
32
- #define __OJ_BUF_H__
3
+ #ifndef OJ_BUF_H
4
+ #define OJ_BUF_H
33
5
 
34
6
  #include "ruby.h"
35
7
 
36
- typedef struct _Buf {
8
+ typedef struct _buf {
37
9
  char *head;
38
10
  char *end;
39
11
  char *tail;
@@ -78,7 +50,7 @@ buf_append_string(Buf buf, const char *s, size_t slen) {
78
50
  memcpy(buf->tail, s, slen);
79
51
  buf->tail += slen;
80
52
  }
81
-
53
+
82
54
  inline static void
83
55
  buf_append(Buf buf, char c) {
84
56
  if (buf->end <= buf->tail) {
@@ -100,4 +72,4 @@ buf_append(Buf buf, char c) {
100
72
  //*buf->tail = '\0'; // for debugging
101
73
  }
102
74
 
103
- #endif /* __OJ_BUF_H__ */
75
+ #endif /* OJ_BUF_H */
data/ext/oj/cache8.c CHANGED
@@ -14,11 +14,11 @@
14
14
  #define DEPTH 16
15
15
 
16
16
  typedef union {
17
- struct _Cache8 *child;
17
+ struct _cache8 *child;
18
18
  slot_t value;
19
19
  } Bucket;
20
20
 
21
- struct _Cache8 {
21
+ struct _cache8 {
22
22
  Bucket buckets[SLOT_CNT];
23
23
  };
24
24
 
@@ -30,7 +30,7 @@ oj_cache8_new(Cache8 *cache) {
30
30
  Bucket *b;
31
31
  int i;
32
32
 
33
- *cache = ALLOC(struct _Cache8);
33
+ *cache = ALLOC(struct _cache8);
34
34
  for (i = SLOT_CNT, b = (*cache)->buckets; 0 < i; i--, b++) {
35
35
  b->value = 0;
36
36
  }
data/ext/oj/cache8.h CHANGED
@@ -1,40 +1,12 @@
1
- /* cache8.h
2
- * Copyright (c) 2011, Peter Ohler
3
- * All rights reserved.
4
- *
5
- * Redistribution and use in source and binary forms, with or without
6
- * modification, are permitted provided that the following conditions are met:
7
- *
8
- * - Redistributions of source code must retain the above copyright notice, this
9
- * list of conditions and the following disclaimer.
10
- *
11
- * - Redistributions in binary form must reproduce the above copyright notice,
12
- * this list of conditions and the following disclaimer in the documentation
13
- * and/or other materials provided with the distribution.
14
- *
15
- * - Neither the name of Peter Ohler nor the names of its contributors may be
16
- * used to endorse or promote products derived from this software without
17
- * specific prior written permission.
18
- *
19
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
- */
1
+ // Copyright (c) 2011 Peter Ohler. All rights reserved.
30
2
 
31
- #ifndef __OJ_CACHE8_H__
32
- #define __OJ_CACHE8_H__
3
+ #ifndef OJ_CACHE8_H
4
+ #define OJ_CACHE8_H
33
5
 
34
6
  #include "ruby.h"
35
7
  #include "stdint.h"
36
8
 
37
- typedef struct _Cache8 *Cache8;
9
+ typedef struct _cache8 *Cache8;
38
10
  typedef uint64_t slot_t;
39
11
  typedef uint64_t sid_t;
40
12
 
@@ -45,4 +17,4 @@ extern slot_t oj_cache8_get(Cache8 cache, sid_t key, slot_t **slot);
45
17
 
46
18
  extern void oj_cache8_print(Cache8 cache);
47
19
 
48
- #endif /* __OJ_CACHE8_H__ */
20
+ #endif /* OJ_CACHE8_H */
data/ext/oj/circarray.c CHANGED
@@ -1,21 +1,18 @@
1
- /* circarray.c
2
- * Copyright (c) 2012, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include "circarray.h"
7
4
 
8
5
  CircArray
9
6
  oj_circ_array_new() {
10
7
  CircArray ca;
11
-
12
- if (0 == (ca = ALLOC(struct _CircArray))) {
8
+
9
+ if (0 == (ca = ALLOC(struct _circArray))) {
13
10
  rb_raise(rb_eNoMemError, "not enough memory\n");
14
11
  }
15
12
  ca->objs = ca->obj_array;
16
13
  ca->size = sizeof(ca->obj_array) / sizeof(VALUE);
17
14
  ca->cnt = 0;
18
-
15
+
19
16
  return ca;
20
17
  }
21
18
 
@@ -40,7 +37,7 @@ oj_circ_array_set(CircArray ca, VALUE obj, unsigned long id) {
40
37
  rb_raise(rb_eNoMemError, "not enough memory\n");
41
38
  }
42
39
  memcpy(ca->objs, ca->obj_array, sizeof(VALUE) * ca->cnt);
43
- } else {
40
+ } else {
44
41
  REALLOC_N(ca->objs, VALUE, cnt);
45
42
  }
46
43
  ca->size = cnt;
@@ -65,4 +62,3 @@ oj_circ_array_get(CircArray ca, unsigned long id) {
65
62
  }
66
63
  return obj;
67
64
  }
68
-
data/ext/oj/circarray.h CHANGED
@@ -1,14 +1,11 @@
1
- /* circarray.h
2
- * Copyright (c) 2012, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
5
2
 
6
- #ifndef __OJ_CIRCARRAY_H__
7
- #define __OJ_CIRCARRAY_H__
3
+ #ifndef OJ_CIRCARRAY_H
4
+ #define OJ_CIRCARRAY_H
8
5
 
9
6
  #include "ruby.h"
10
7
 
11
- typedef struct _CircArray {
8
+ typedef struct _circArray {
12
9
  VALUE obj_array[1024];
13
10
  VALUE *objs;
14
11
  unsigned long size; // allocated size or initial array size
@@ -20,4 +17,4 @@ extern void oj_circ_array_free(CircArray ca);
20
17
  extern void oj_circ_array_set(CircArray ca, VALUE obj, unsigned long id);
21
18
  extern VALUE oj_circ_array_get(CircArray ca, unsigned long id);
22
19
 
23
- #endif /* __OJ_CIRCARRAY_H__ */
20
+ #endif /* OJ_CIRCARRAY_H */
data/ext/oj/code.c CHANGED
@@ -1,7 +1,4 @@
1
- /* code.c
2
- * Copyright (c) 2017, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2017 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include "code.h"
7
4
  #include "dump.h"
@@ -140,7 +137,7 @@ oj_code_attrs(VALUE obj, Attr attrs, int depth, Out out, bool with_class) {
140
137
  size_t len = strlen(classname);
141
138
  size_t size = d2 * out->indent + 10 + len + out->opts->create_id_len + sep_len;
142
139
  bool no_comma = true;
143
-
140
+
144
141
  assure_size(out, size);
145
142
  *out->cur++ = '{';
146
143
 
@@ -201,7 +198,7 @@ oj_code_attrs(VALUE obj, Attr attrs, int depth, Out out, bool with_class) {
201
198
  char *b = buf + sizeof(buf) - 1;
202
199
  int neg = 0;
203
200
  long num = attrs->num;
204
-
201
+
205
202
  if (0 > num) {
206
203
  neg = 1;
207
204
  num = -num;
data/ext/oj/code.h CHANGED
@@ -1,10 +1,7 @@
1
- /* code.h
2
- * Copyright (c) 2017, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2017 Peter Ohler. All rights reserved.
5
2
 
6
- #ifndef __OJ_CODE_H__
7
- #define __OJ_CODE_H__
3
+ #ifndef OJ_CODE_H
4
+ #define OJ_CODE_H
8
5
 
9
6
  #include <ruby.h>
10
7
 
@@ -13,7 +10,7 @@
13
10
  typedef void (*EncodeFunc)(VALUE obj, int depth, Out out);
14
11
  typedef VALUE (*DecodeFunc)(VALUE clas, VALUE args);
15
12
 
16
- typedef struct _Code {
13
+ typedef struct _code {
17
14
  const char *name;
18
15
  VALUE clas;
19
16
  EncodeFunc encode;
@@ -22,7 +19,7 @@ typedef struct _Code {
22
19
  } *Code;
23
20
 
24
21
  // Used by encode functions.
25
- typedef struct _Attr {
22
+ typedef struct _attr {
26
23
  const char *name;
27
24
  int len;
28
25
  VALUE value;
@@ -37,6 +34,6 @@ extern bool oj_code_has(Code codes, VALUE clas, bool encode);
37
34
 
38
35
  extern void oj_code_attrs(VALUE obj, Attr attrs, int depth, Out out, bool with_class);
39
36
 
40
- extern struct _Code oj_compat_codes[];
37
+ extern struct _code oj_compat_codes[];
41
38
 
42
- #endif /* __OJ_CODE_H__ */
39
+ #endif /* OJ_CODE_H */
data/ext/oj/compat.c CHANGED
@@ -1,7 +1,4 @@
1
- /* compat.c
2
- * Copyright (c) 2012, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include <stdio.h>
7
4
 
@@ -65,7 +62,7 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
65
62
  static VALUE
66
63
  start_hash(ParseInfo pi) {
67
64
  volatile VALUE h;
68
-
65
+
69
66
  if (Qnil != pi->options.hash_class) {
70
67
  h = rb_class_new_instance(0, NULL, pi->options.hash_class);
71
68
  } else {
@@ -78,7 +75,7 @@ start_hash(ParseInfo pi) {
78
75
  }
79
76
 
80
77
  static void
81
- end_hash(struct _ParseInfo *pi) {
78
+ end_hash(struct _parseInfo *pi) {
82
79
  Val parent = stack_peek(&pi->stack);
83
80
 
84
81
  if (0 != parent->classname) {
@@ -87,7 +84,7 @@ end_hash(struct _ParseInfo *pi) {
87
84
  clas = oj_name2class(pi, parent->classname, parent->clen, 0, rb_eArgError);
88
85
  if (Qundef != clas) { // else an error
89
86
  ID creatable = rb_intern("json_creatable?");
90
-
87
+
91
88
  if (!rb_respond_to(clas, creatable) || Qtrue == rb_funcall(clas, creatable, 0)) {
92
89
  parent->val = rb_funcall(clas, oj_json_create_id, 1, parent->val);
93
90
  }
@@ -144,9 +141,9 @@ add_num(ParseInfo pi, NumInfo ni) {
144
141
  }
145
142
 
146
143
  static void
147
- hash_set_num(struct _ParseInfo *pi, Val parent, NumInfo ni) {
144
+ hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
148
145
  volatile VALUE rval = oj_num_as_value(ni);
149
-
146
+
150
147
  if (!oj_use_hash_alt && rb_cHash != rb_obj_class(parent->val)) {
151
148
  // The rb_hash_set would still work but the unit tests for the
152
149
  // json gem require the less efficient []= method be called to set
@@ -192,7 +189,7 @@ static void
192
189
  array_append_num(ParseInfo pi, NumInfo ni) {
193
190
  Val parent = stack_peek(&pi->stack);
194
191
  volatile VALUE rval = oj_num_as_value(ni);
195
-
192
+
196
193
  if (!oj_use_array_alt && rb_cArray != rb_obj_class(parent->val)) {
197
194
  // The rb_ary_push would still work but the unit tests for the json
198
195
  // gem require the less efficient << method be called to push the
@@ -242,7 +239,7 @@ oj_set_compat_callbacks(ParseInfo pi) {
242
239
 
243
240
  VALUE
244
241
  oj_compat_parse(int argc, VALUE *argv, VALUE self) {
245
- struct _ParseInfo pi;
242
+ struct _parseInfo pi;
246
243
 
247
244
  parse_info_init(&pi);
248
245
  pi.options = oj_default_options;
@@ -263,7 +260,7 @@ oj_compat_parse(int argc, VALUE *argv, VALUE self) {
263
260
 
264
261
  VALUE
265
262
  oj_compat_load(int argc, VALUE *argv, VALUE self) {
266
- struct _ParseInfo pi;
263
+ struct _parseInfo pi;
267
264
 
268
265
  parse_info_init(&pi);
269
266
  pi.options = oj_default_options;
@@ -274,7 +271,7 @@ oj_compat_load(int argc, VALUE *argv, VALUE self) {
274
271
  pi.options.nilnil = Yes;
275
272
  pi.options.empty_string = Yes;
276
273
  oj_set_compat_callbacks(&pi);
277
-
274
+
278
275
  if (T_STRING == rb_type(*argv)) {
279
276
  return oj_pi_parse(argc, argv, &pi, 0, 0, false);
280
277
  } else {
@@ -284,7 +281,7 @@ oj_compat_load(int argc, VALUE *argv, VALUE self) {
284
281
 
285
282
  VALUE
286
283
  oj_compat_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
287
- struct _ParseInfo pi;
284
+ struct _parseInfo pi;
288
285
 
289
286
  parse_info_init(&pi);
290
287
  pi.options = oj_default_options;
data/ext/oj/custom.c CHANGED
@@ -1,8 +1,6 @@
1
- /* custom.c
2
- * Copyright (c) 2012, 2017, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
5
2
 
3
+ #include <stdint.h>
6
4
  #include <stdio.h>
7
5
 
8
6
  #include "code.h"
@@ -15,13 +13,14 @@
15
13
  #include "parse.h"
16
14
  #include "resolve.h"
17
15
  #include "trace.h"
16
+ #include "util.h"
18
17
 
19
18
  extern void oj_set_obj_ivar(Val parent, Val kval, VALUE value);
20
19
  extern VALUE oj_parse_xml_time(const char *str, int len); // from object.c
21
20
 
22
21
  static void
23
22
  dump_obj_str(VALUE obj, int depth, Out out) {
24
- struct _Attr attrs[] = {
23
+ struct _attr attrs[] = {
25
24
  { "s", 1, Qnil },
26
25
  { NULL, 0, Qnil },
27
26
  };
@@ -30,6 +29,13 @@ dump_obj_str(VALUE obj, int depth, Out out) {
30
29
  oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
31
30
  }
32
31
 
32
+ static void
33
+ dump_obj_as_str(VALUE obj, int depth, Out out) {
34
+ volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
35
+ const char *str = rb_string_value_ptr((VALUE*)&rstr);
36
+
37
+ oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
38
+ }
33
39
 
34
40
  static void
35
41
  bigdecimal_dump(VALUE obj, int depth, Out out) {
@@ -55,19 +61,23 @@ static ID imag_id = 0;
55
61
 
56
62
  static void
57
63
  complex_dump(VALUE obj, int depth, Out out) {
58
- struct _Attr attrs[] = {
59
- { "real", 4, Qnil },
60
- { "imag", 4, Qnil },
61
- { NULL, 0, Qnil },
62
- };
63
- if (0 == real_id) {
64
- real_id = rb_intern("real");
65
- imag_id = rb_intern("imag");
66
- }
67
- attrs[0].value = rb_funcall(obj, real_id, 0);
68
- attrs[1].value = rb_funcall(obj, imag_id, 0);
64
+ if (NULL != out->opts->create_id) {
65
+ struct _attr attrs[] = {
66
+ { "real", 4, Qnil },
67
+ { "imag", 4, Qnil },
68
+ { NULL, 0, Qnil },
69
+ };
70
+ if (0 == real_id) {
71
+ real_id = rb_intern("real");
72
+ imag_id = rb_intern("imag");
73
+ }
74
+ attrs[0].value = rb_funcall(obj, real_id, 0);
75
+ attrs[1].value = rb_funcall(obj, imag_id, 0);
69
76
 
70
- oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
77
+ oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
78
+ } else {
79
+ dump_obj_as_str(obj, depth, out);
80
+ }
71
81
  }
72
82
 
73
83
  static VALUE
@@ -82,7 +92,7 @@ complex_load(VALUE clas, VALUE args) {
82
92
  static void
83
93
  time_dump(VALUE obj, int depth, Out out) {
84
94
  if (Yes == out->opts->create_ok) {
85
- struct _Attr attrs[] = {
95
+ struct _attr attrs[] = {
86
96
  { "time", 4, Qundef, 0, Qundef },
87
97
  { NULL, 0, Qnil },
88
98
  };
@@ -103,7 +113,7 @@ time_dump(VALUE obj, int depth, Out out) {
103
113
  static void
104
114
  date_dump(VALUE obj, int depth, Out out) {
105
115
  if (Yes == out->opts->create_ok) {
106
- struct _Attr attrs[] = {
116
+ struct _attr attrs[] = {
107
117
  { "s", 1, Qnil },
108
118
  { NULL, 0, Qnil },
109
119
  };
@@ -113,7 +123,7 @@ date_dump(VALUE obj, int depth, Out out) {
113
123
  } else {
114
124
  volatile VALUE v;
115
125
  volatile VALUE ov;
116
-
126
+
117
127
  switch (out->opts->time_format) {
118
128
  case RubyTime:
119
129
  case XmlTime:
@@ -148,7 +158,7 @@ date_dump(VALUE obj, int depth, Out out) {
148
158
  static VALUE
149
159
  date_load(VALUE clas, VALUE args) {
150
160
  volatile VALUE v;
151
-
161
+
152
162
  if (Qnil != (v = rb_hash_aref(args, rb_str_new2("s")))) {
153
163
  return rb_funcall(oj_date_class, rb_intern("parse"), 1, v);
154
164
  }
@@ -158,7 +168,7 @@ date_load(VALUE clas, VALUE args) {
158
168
  static VALUE
159
169
  datetime_load(VALUE clas, VALUE args) {
160
170
  volatile VALUE v;
161
-
171
+
162
172
  if (Qnil != (v = rb_hash_aref(args, rb_str_new2("s")))) {
163
173
  return rb_funcall(oj_datetime_class, rb_intern("parse"), 1, v);
164
174
  }
@@ -169,7 +179,7 @@ static ID table_id = 0;
169
179
 
170
180
  static void
171
181
  openstruct_dump(VALUE obj, int depth, Out out) {
172
- struct _Attr attrs[] = {
182
+ struct _attr attrs[] = {
173
183
  { "table", 5, Qnil },
174
184
  { NULL, 0, Qnil },
175
185
  };
@@ -191,23 +201,27 @@ openstruct_load(VALUE clas, VALUE args) {
191
201
 
192
202
  static void
193
203
  range_dump(VALUE obj, int depth, Out out) {
194
- struct _Attr attrs[] = {
195
- { "begin", 5, Qnil },
196
- { "end", 3, Qnil },
197
- { "exclude", 7, Qnil },
198
- { NULL, 0, Qnil },
199
- };
200
- attrs[0].value = rb_funcall(obj, oj_begin_id, 0);
201
- attrs[1].value = rb_funcall(obj, oj_end_id, 0);
202
- attrs[2].value = rb_funcall(obj, oj_exclude_end_id, 0);
204
+ if (NULL != out->opts->create_id) {
205
+ struct _attr attrs[] = {
206
+ { "begin", 5, Qnil },
207
+ { "end", 3, Qnil },
208
+ { "exclude", 7, Qnil },
209
+ { NULL, 0, Qnil },
210
+ };
211
+ attrs[0].value = rb_funcall(obj, oj_begin_id, 0);
212
+ attrs[1].value = rb_funcall(obj, oj_end_id, 0);
213
+ attrs[2].value = rb_funcall(obj, oj_exclude_end_id, 0);
203
214
 
204
- oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
215
+ oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
216
+ } else {
217
+ dump_obj_as_str(obj, depth, out);
218
+ }
205
219
  }
206
220
 
207
221
  static VALUE
208
222
  range_load(VALUE clas, VALUE args) {
209
223
  VALUE nargs[3];
210
-
224
+
211
225
  nargs[0] = rb_hash_aref(args, rb_id2str(oj_begin_id));
212
226
  nargs[1] = rb_hash_aref(args, rb_id2str(oj_end_id));
213
227
  nargs[2] = rb_hash_aref(args, rb_id2str(oj_exclude_end_id));
@@ -220,19 +234,23 @@ static ID denominator_id = 0;
220
234
 
221
235
  static void
222
236
  rational_dump(VALUE obj, int depth, Out out) {
223
- struct _Attr attrs[] = {
224
- { "numerator", 9, Qnil },
225
- { "denominator", 11, Qnil },
226
- { NULL, 0, Qnil },
227
- };
228
- if (0 == numerator_id) {
229
- numerator_id = rb_intern("numerator");
230
- denominator_id = rb_intern("denominator");
231
- }
232
- attrs[0].value = rb_funcall(obj, numerator_id, 0);
233
- attrs[1].value = rb_funcall(obj, denominator_id, 0);
237
+ if (NULL != out->opts->create_id) {
238
+ struct _attr attrs[] = {
239
+ { "numerator", 9, Qnil },
240
+ { "denominator", 11, Qnil },
241
+ { NULL, 0, Qnil },
242
+ };
243
+ if (0 == numerator_id) {
244
+ numerator_id = rb_intern("numerator");
245
+ denominator_id = rb_intern("denominator");
246
+ }
247
+ attrs[0].value = rb_funcall(obj, numerator_id, 0);
248
+ attrs[1].value = rb_funcall(obj, denominator_id, 0);
234
249
 
235
- oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
250
+ oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
251
+ } else {
252
+ dump_obj_as_str(obj, depth, out);
253
+ }
236
254
  }
237
255
 
238
256
  static VALUE
@@ -248,7 +266,7 @@ rational_load(VALUE clas, VALUE args) {
248
266
  static VALUE
249
267
  regexp_load(VALUE clas, VALUE args) {
250
268
  volatile VALUE v;
251
-
269
+
252
270
  if (Qnil != (v = rb_hash_aref(args, rb_str_new2("s")))) {
253
271
  return rb_funcall(rb_cRegexp, oj_new_id, 1, v);
254
272
  }
@@ -262,7 +280,7 @@ time_load(VALUE clas, VALUE args) {
262
280
  return args;
263
281
  }
264
282
 
265
- static struct _Code codes[] = {
283
+ static struct _code codes[] = {
266
284
  { "BigDecimal", Qnil, bigdecimal_dump, NULL, true },
267
285
  { "Complex", Qnil, complex_dump, complex_load, true },
268
286
  { "Date", Qnil, date_dump, date_load, true },
@@ -276,7 +294,8 @@ static struct _Code codes[] = {
276
294
  };
277
295
 
278
296
  static int
279
- hash_cb(VALUE key, VALUE value, Out out) {
297
+ hash_cb(VALUE key, VALUE value, VALUE ov) {
298
+ Out out = (Out)ov;
280
299
  int depth = out->depth;
281
300
 
282
301
  if (oj_dump_ignore(out->opts, value)) {
@@ -421,7 +440,7 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
421
440
  v = rb_funcall(obj, *odd->attrs, 0);
422
441
  if (Qundef == v || T_STRING != rb_type(v)) {
423
442
  rb_raise(rb_eEncodingError, "Invalid type for raw JSON.\n");
424
- } else {
443
+ } else {
425
444
  const char *s = rb_string_value_ptr((VALUE*)&v);
426
445
  int len = (int)RSTRING_LEN(v);
427
446
  const char *name = rb_id2name(*odd->attrs);
@@ -457,9 +476,11 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
457
476
  char *n;
458
477
  char *end;
459
478
  ID i;
460
-
479
+
461
480
  if (sizeof(nbuf) <= nlen) {
462
- n2 = strdup(name);
481
+ if (NULL == (n2 = strdup(name))) {
482
+ rb_raise(rb_eNoMemError, "for attribute name.");
483
+ }
463
484
  } else {
464
485
  strcpy(n2, name);
465
486
  }
@@ -493,7 +514,10 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
493
514
  // Return class if still needs dumping.
494
515
  static VALUE
495
516
  dump_common(VALUE obj, int depth, Out out) {
496
- if (Yes == out->opts->to_json && rb_respond_to(obj, oj_to_json_id)) {
517
+
518
+ if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
519
+ oj_dump_raw_json(obj, depth, out);
520
+ } else if (Yes == out->opts->to_json && rb_respond_to(obj, oj_to_json_id)) {
497
521
  volatile VALUE rs;
498
522
  const char *s;
499
523
  int len;
@@ -566,7 +590,8 @@ dump_common(VALUE obj, int depth, Out out) {
566
590
  }
567
591
 
568
592
  static int
569
- dump_attr_cb(ID key, VALUE value, Out out) {
593
+ dump_attr_cb(ID key, VALUE value, VALUE ov) {
594
+ Out out = (Out)ov;
570
595
  int depth = out->depth;
571
596
  size_t size;
572
597
  const char *attr;
@@ -583,6 +608,8 @@ dump_attr_cb(ID key, VALUE value, Out out) {
583
608
  // the key name is NULL. Not an empty string but NULL.
584
609
  if (NULL == attr) {
585
610
  attr = "";
611
+ } else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
612
+ return ST_CONTINUE;
586
613
  }
587
614
  if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
588
615
  return ST_CONTINUE;
@@ -604,7 +631,7 @@ dump_attr_cb(ID key, VALUE value, Out out) {
604
631
  oj_dump_custom_val(value, depth, out, true);
605
632
  out->depth = depth;
606
633
  *out->cur++ = ',';
607
-
634
+
608
635
  return ST_CONTINUE;
609
636
  }
610
637
 
@@ -776,7 +803,7 @@ static void
776
803
  dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
777
804
  long id = oj_check_circular(obj, out);
778
805
  VALUE clas;
779
-
806
+
780
807
  if (0 > id) {
781
808
  oj_dump_nil(Qnil, depth, out, false);
782
809
  } else if (Qnil != (clas = dump_common(obj, depth, out))) {
@@ -789,7 +816,7 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
789
816
  size_t size = d2 * out->indent + d3 * out->indent + 3;
790
817
  const char *name;
791
818
  int cnt;
792
- size_t len;
819
+ size_t len;
793
820
 
794
821
  assure_size(out, size);
795
822
  if (clas == rb_cRange) {
@@ -867,7 +894,11 @@ dump_data(VALUE obj, int depth, Out out, bool as_ok) {
867
894
 
868
895
  static void
869
896
  dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
870
- dump_obj_str(obj, depth, out);
897
+ if (NULL != out->opts->create_id) {
898
+ dump_obj_str(obj, depth, out);
899
+ } else {
900
+ dump_obj_as_str(obj, depth, out);
901
+ }
871
902
  }
872
903
 
873
904
  static void
@@ -997,7 +1028,7 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
997
1028
  }
998
1029
 
999
1030
  static void
1000
- end_hash(struct _ParseInfo *pi) {
1031
+ end_hash(struct _parseInfo *pi) {
1001
1032
  Val parent = stack_peek(&pi->stack);
1002
1033
 
1003
1034
  if (Qundef != parent->clas && parent->clas != rb_obj_class(parent->val)) {
@@ -1030,7 +1061,7 @@ calc_hash_key(ParseInfo pi, Val parent) {
1030
1061
  }
1031
1062
 
1032
1063
  static void
1033
- hash_set_num(struct _ParseInfo *pi, Val kval, NumInfo ni) {
1064
+ hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
1034
1065
  Val parent = stack_peek(&pi->stack);
1035
1066
  volatile VALUE rval = oj_num_as_value(ni);
1036
1067
 
@@ -1039,7 +1070,7 @@ hash_set_num(struct _ParseInfo *pi, Val kval, NumInfo ni) {
1039
1070
  oj_set_obj_ivar(parent, kval, rval);
1040
1071
  break;
1041
1072
  case T_HASH:
1042
- if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas && 0 == strncmp("time", parent->key, 4)) {
1073
+ if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas && 0 != ni->div && 0 == strncmp("time", parent->key, 4)) {
1043
1074
  int64_t nsec = ni->num * 1000000000LL / ni->div;
1044
1075
 
1045
1076
  if (ni->neg) {
@@ -1055,17 +1086,19 @@ hash_set_num(struct _ParseInfo *pi, Val kval, NumInfo ni) {
1055
1086
  // offset and then a conversion to UTC keeps makes the time
1056
1087
  // match the expected value.
1057
1088
  parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
1058
- } else if (ni->hasExp) {
1059
- time_t t = (time_t)(ni->i + ni->exp);
1060
- struct tm *st = gmtime(&t);
1061
- VALUE args[8];
1062
-
1063
- args[0] = LONG2NUM(1900 + st->tm_year);
1064
- args[1] = LONG2NUM(1 + st->tm_mon);
1065
- args[2] = LONG2NUM(st->tm_mday);
1066
- args[3] = LONG2NUM(st->tm_hour);
1067
- args[4] = LONG2NUM(st->tm_min);
1068
- args[5] = rb_float_new((double)st->tm_sec + ((double)nsec + 0.5) / 1000000000.0);
1089
+ } else if (ni->has_exp) {
1090
+ int64_t t = (int64_t)(ni->i + ni->exp);
1091
+ struct _timeInfo ti;
1092
+ VALUE args[8];
1093
+
1094
+ sec_as_time(t, &ti);
1095
+
1096
+ args[0] = LONG2NUM(ti.year);
1097
+ args[1] = LONG2NUM(ti.mon);
1098
+ args[2] = LONG2NUM(ti.day);
1099
+ args[3] = LONG2NUM(ti.hour);
1100
+ args[4] = LONG2NUM(ti.min);
1101
+ args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
1069
1102
  args[6] = LONG2NUM(ni->exp);
1070
1103
  parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
1071
1104
  } else {
@@ -1107,7 +1140,7 @@ static void
1107
1140
  array_append_num(ParseInfo pi, NumInfo ni) {
1108
1141
  Val parent = stack_peek(&pi->stack);
1109
1142
  volatile VALUE rval = oj_num_as_value(ni);
1110
-
1143
+
1111
1144
  rb_ary_push(parent->val, rval);
1112
1145
  if (Yes == pi->options.trace) {
1113
1146
  oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
@@ -1146,7 +1179,7 @@ oj_set_custom_callbacks(ParseInfo pi) {
1146
1179
 
1147
1180
  VALUE
1148
1181
  oj_custom_parse(int argc, VALUE *argv, VALUE self) {
1149
- struct _ParseInfo pi;
1182
+ struct _parseInfo pi;
1150
1183
 
1151
1184
  parse_info_init(&pi);
1152
1185
  pi.options = oj_default_options;
@@ -1166,7 +1199,7 @@ oj_custom_parse(int argc, VALUE *argv, VALUE self) {
1166
1199
 
1167
1200
  VALUE
1168
1201
  oj_custom_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
1169
- struct _ParseInfo pi;
1202
+ struct _parseInfo pi;
1170
1203
 
1171
1204
  parse_info_init(&pi);
1172
1205
  pi.options = oj_default_options;