oj 3.7.4 → 3.11.2

Sign up to get free protection for your applications and to get access to all the features.
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;