oj 3.11.5 → 3.16.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1421 -0
- data/README.md +19 -5
- data/RELEASE_NOTES.md +61 -0
- data/ext/oj/buf.h +20 -6
- data/ext/oj/cache.c +329 -0
- data/ext/oj/cache.h +22 -0
- data/ext/oj/cache8.c +10 -9
- data/ext/oj/circarray.c +8 -6
- data/ext/oj/circarray.h +2 -2
- data/ext/oj/code.c +19 -33
- data/ext/oj/code.h +2 -2
- data/ext/oj/compat.c +27 -77
- data/ext/oj/custom.c +86 -179
- data/ext/oj/debug.c +126 -0
- data/ext/oj/dump.c +256 -249
- data/ext/oj/dump.h +26 -12
- data/ext/oj/dump_compat.c +565 -642
- data/ext/oj/dump_leaf.c +17 -63
- data/ext/oj/dump_object.c +65 -187
- data/ext/oj/dump_strict.c +27 -51
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/err.c +2 -13
- data/ext/oj/err.h +24 -8
- data/ext/oj/extconf.rb +21 -6
- data/ext/oj/fast.c +149 -149
- data/ext/oj/intern.c +313 -0
- data/ext/oj/intern.h +22 -0
- data/ext/oj/mem.c +318 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +121 -106
- data/ext/oj/object.c +85 -162
- data/ext/oj/odd.c +89 -67
- data/ext/oj/odd.h +15 -15
- data/ext/oj/oj.c +542 -411
- data/ext/oj/oj.h +99 -73
- data/ext/oj/parse.c +175 -187
- data/ext/oj/parse.h +26 -24
- data/ext/oj/parser.c +1600 -0
- data/ext/oj/parser.h +101 -0
- data/ext/oj/rails.c +112 -159
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +11 -14
- data/ext/oj/reader.h +4 -2
- data/ext/oj/resolve.c +5 -24
- data/ext/oj/rxclass.c +7 -6
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/saj.c +22 -33
- data/ext/oj/saj2.c +584 -0
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/scp.c +5 -28
- data/ext/oj/sparse.c +28 -72
- data/ext/oj/stream_writer.c +50 -40
- data/ext/oj/strict.c +56 -61
- data/ext/oj/string_writer.c +72 -39
- data/ext/oj/trace.h +31 -4
- data/ext/oj/usual.c +1218 -0
- data/ext/oj/usual.h +69 -0
- data/ext/oj/util.h +1 -1
- data/ext/oj/val_stack.c +14 -3
- data/ext/oj/val_stack.h +8 -7
- data/ext/oj/validate.c +46 -0
- data/ext/oj/wab.c +63 -88
- data/lib/oj/active_support_helper.rb +1 -3
- data/lib/oj/bag.rb +7 -1
- data/lib/oj/easy_hash.rb +4 -5
- data/lib/oj/error.rb +1 -2
- data/lib/oj/json.rb +162 -150
- data/lib/oj/mimic.rb +9 -7
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/schandler.rb +5 -4
- data/lib/oj/state.rb +12 -8
- data/lib/oj/version.rb +1 -2
- data/lib/oj.rb +2 -0
- data/pages/Compatibility.md +1 -1
- data/pages/InstallOptions.md +20 -0
- data/pages/JsonGem.md +15 -0
- data/pages/Modes.md +8 -3
- data/pages/Options.md +43 -5
- data/pages/Parser.md +309 -0
- data/pages/Rails.md +14 -2
- data/test/_test_active.rb +8 -9
- data/test/_test_active_mimic.rb +7 -8
- data/test/_test_mimic_rails.rb +17 -20
- data/test/activerecord/result_test.rb +5 -6
- data/test/activesupport6/encoding_test.rb +63 -28
- data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
- data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
- data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
- data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
- data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
- data/test/files.rb +15 -15
- data/test/foo.rb +16 -45
- data/test/helper.rb +11 -8
- data/test/isolated/shared.rb +3 -2
- data/test/json_gem/json_addition_test.rb +2 -2
- data/test/json_gem/json_common_interface_test.rb +8 -6
- data/test/json_gem/json_encoding_test.rb +0 -0
- data/test/json_gem/json_ext_parser_test.rb +1 -0
- data/test/json_gem/json_fixtures_test.rb +3 -2
- data/test/json_gem/json_generator_test.rb +56 -38
- data/test/json_gem/json_generic_object_test.rb +11 -11
- data/test/json_gem/json_parser_test.rb +54 -47
- data/test/json_gem/json_string_matching_test.rb +9 -9
- data/test/json_gem/test_helper.rb +7 -3
- data/test/mem.rb +34 -0
- data/test/perf.rb +22 -27
- data/test/perf_compat.rb +31 -33
- data/test/perf_dump.rb +50 -0
- data/test/perf_fast.rb +80 -82
- data/test/perf_file.rb +27 -29
- data/test/perf_object.rb +65 -69
- data/test/perf_once.rb +59 -0
- data/test/perf_parser.rb +183 -0
- data/test/perf_saj.rb +46 -54
- data/test/perf_scp.rb +58 -69
- data/test/perf_simple.rb +41 -39
- data/test/perf_strict.rb +74 -82
- data/test/perf_wab.rb +67 -69
- data/test/prec.rb +5 -5
- data/test/sample/change.rb +0 -1
- data/test/sample/dir.rb +0 -1
- data/test/sample/doc.rb +0 -1
- data/test/sample/file.rb +0 -1
- data/test/sample/group.rb +0 -1
- data/test/sample/hasprops.rb +0 -1
- data/test/sample/layer.rb +0 -1
- data/test/sample/rect.rb +0 -1
- data/test/sample/shape.rb +0 -1
- data/test/sample/text.rb +0 -1
- data/test/sample.rb +16 -16
- data/test/sample_json.rb +8 -8
- data/test/test_compat.rb +95 -43
- data/test/test_custom.rb +73 -51
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +135 -79
- data/test/test_file.rb +41 -30
- data/test/test_gc.rb +16 -5
- data/test/test_generate.rb +5 -5
- data/test/test_hash.rb +5 -5
- data/test/test_integer_range.rb +9 -9
- data/test/test_null.rb +20 -20
- data/test/test_object.rb +99 -96
- data/test/test_parser.rb +11 -0
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +337 -0
- data/test/test_parser_usual.rb +251 -0
- data/test/test_rails.rb +2 -2
- data/test/test_saj.rb +10 -8
- data/test/test_scp.rb +37 -39
- data/test/test_strict.rb +40 -32
- data/test/test_various.rb +165 -84
- data/test/test_wab.rb +48 -44
- data/test/test_writer.rb +47 -47
- data/test/tests.rb +13 -5
- data/test/tests_mimic.rb +12 -3
- data/test/tests_mimic_addition.rb +12 -3
- metadata +74 -128
- data/ext/oj/hash.c +0 -131
- data/ext/oj/hash.h +0 -19
- data/ext/oj/hash_test.c +0 -491
- data/test/activesupport4/decoding_test.rb +0 -108
- data/test/activesupport4/encoding_test.rb +0 -531
- data/test/activesupport4/test_helper.rb +0 -41
- data/test/activesupport5/test_helper.rb +0 -72
- data/test/bar.rb +0 -35
- data/test/baz.rb +0 -16
- 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
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
|
11
|
+
static void stack_mark(void *ptr) {
|
12
12
|
ValStack stack = (ValStack)ptr;
|
13
13
|
Val v;
|
14
14
|
|
15
|
-
if (
|
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
|
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
|
32
|
+
const char *key;
|
32
33
|
char karray[32];
|
33
34
|
volatile VALUE key_val;
|
34
|
-
const char
|
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
|
-
} *
|
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
|
-
} *
|
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
|
-
|
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 =
|
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
|
-
|
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
|
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(
|
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 =
|
204
|
-
nsec =
|
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 =
|
227
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
234
228
|
|
235
|
-
oj_dump_raw(
|
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(
|
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(
|
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
|
-
|
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
|
-
|
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
|
296
|
-
|
297
|
-
|
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
|
-
|
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
|
-
|
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
|
-
'
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|