oj 3.7.12
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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +96 -0
- data/ext/oj/buf.h +103 -0
- data/ext/oj/cache8.c +107 -0
- data/ext/oj/cache8.h +48 -0
- data/ext/oj/circarray.c +68 -0
- data/ext/oj/circarray.h +23 -0
- data/ext/oj/code.c +235 -0
- data/ext/oj/code.h +42 -0
- data/ext/oj/compat.c +299 -0
- data/ext/oj/custom.c +1188 -0
- data/ext/oj/dump.c +1232 -0
- data/ext/oj/dump.h +94 -0
- data/ext/oj/dump_compat.c +973 -0
- data/ext/oj/dump_leaf.c +252 -0
- data/ext/oj/dump_object.c +837 -0
- data/ext/oj/dump_strict.c +433 -0
- data/ext/oj/encode.h +45 -0
- data/ext/oj/err.c +57 -0
- data/ext/oj/err.h +70 -0
- data/ext/oj/extconf.rb +47 -0
- data/ext/oj/fast.c +1771 -0
- data/ext/oj/hash.c +163 -0
- data/ext/oj/hash.h +46 -0
- data/ext/oj/hash_test.c +512 -0
- data/ext/oj/mimic_json.c +873 -0
- data/ext/oj/object.c +771 -0
- data/ext/oj/odd.c +231 -0
- data/ext/oj/odd.h +44 -0
- data/ext/oj/oj.c +1694 -0
- data/ext/oj/oj.h +381 -0
- data/ext/oj/parse.c +1085 -0
- data/ext/oj/parse.h +111 -0
- data/ext/oj/rails.c +1485 -0
- data/ext/oj/rails.h +21 -0
- data/ext/oj/reader.c +231 -0
- data/ext/oj/reader.h +151 -0
- data/ext/oj/resolve.c +102 -0
- data/ext/oj/resolve.h +14 -0
- data/ext/oj/rxclass.c +147 -0
- data/ext/oj/rxclass.h +27 -0
- data/ext/oj/saj.c +714 -0
- data/ext/oj/scp.c +224 -0
- data/ext/oj/sparse.c +910 -0
- data/ext/oj/stream_writer.c +363 -0
- data/ext/oj/strict.c +212 -0
- data/ext/oj/string_writer.c +512 -0
- data/ext/oj/trace.c +79 -0
- data/ext/oj/trace.h +28 -0
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +19 -0
- data/ext/oj/val_stack.c +118 -0
- data/ext/oj/val_stack.h +185 -0
- data/ext/oj/wab.c +631 -0
- data/lib/oj.rb +21 -0
- data/lib/oj/active_support_helper.rb +41 -0
- data/lib/oj/bag.rb +88 -0
- data/lib/oj/easy_hash.rb +52 -0
- data/lib/oj/error.rb +22 -0
- data/lib/oj/json.rb +176 -0
- data/lib/oj/mimic.rb +267 -0
- data/lib/oj/saj.rb +66 -0
- data/lib/oj/schandler.rb +142 -0
- data/lib/oj/state.rb +131 -0
- data/lib/oj/version.rb +5 -0
- data/pages/Advanced.md +22 -0
- data/pages/Compatibility.md +25 -0
- data/pages/Custom.md +23 -0
- data/pages/Encoding.md +65 -0
- data/pages/JsonGem.md +79 -0
- data/pages/Modes.md +154 -0
- data/pages/Options.md +266 -0
- data/pages/Rails.md +116 -0
- data/pages/Security.md +20 -0
- data/pages/WAB.md +13 -0
- data/test/_test_active.rb +76 -0
- data/test/_test_active_mimic.rb +96 -0
- data/test/_test_mimic_rails.rb +126 -0
- data/test/activerecord/result_test.rb +27 -0
- data/test/activesupport4/decoding_test.rb +108 -0
- data/test/activesupport4/encoding_test.rb +531 -0
- data/test/activesupport4/test_helper.rb +41 -0
- data/test/activesupport5/decoding_test.rb +125 -0
- data/test/activesupport5/encoding_test.rb +485 -0
- data/test/activesupport5/encoding_test_cases.rb +90 -0
- data/test/activesupport5/test_helper.rb +50 -0
- data/test/activesupport5/time_zone_test_helpers.rb +24 -0
- data/test/big.rb +15 -0
- data/test/files.rb +29 -0
- data/test/foo.rb +33 -0
- data/test/helper.rb +26 -0
- data/test/isolated/shared.rb +308 -0
- data/test/isolated/test_mimic_after.rb +13 -0
- data/test/isolated/test_mimic_alone.rb +12 -0
- data/test/isolated/test_mimic_as_json.rb +45 -0
- data/test/isolated/test_mimic_before.rb +13 -0
- data/test/isolated/test_mimic_define.rb +28 -0
- data/test/isolated/test_mimic_rails_after.rb +22 -0
- data/test/isolated/test_mimic_rails_before.rb +21 -0
- data/test/isolated/test_mimic_redefine.rb +15 -0
- data/test/json_gem/json_addition_test.rb +216 -0
- data/test/json_gem/json_common_interface_test.rb +148 -0
- data/test/json_gem/json_encoding_test.rb +107 -0
- data/test/json_gem/json_ext_parser_test.rb +20 -0
- data/test/json_gem/json_fixtures_test.rb +35 -0
- data/test/json_gem/json_generator_test.rb +383 -0
- data/test/json_gem/json_generic_object_test.rb +90 -0
- data/test/json_gem/json_parser_test.rb +470 -0
- data/test/json_gem/json_string_matching_test.rb +42 -0
- data/test/json_gem/test_helper.rb +18 -0
- data/test/mem.rb +35 -0
- data/test/perf.rb +107 -0
- data/test/perf_compat.rb +130 -0
- data/test/perf_fast.rb +164 -0
- data/test/perf_file.rb +64 -0
- data/test/perf_object.rb +138 -0
- data/test/perf_saj.rb +109 -0
- data/test/perf_scp.rb +151 -0
- data/test/perf_simple.rb +287 -0
- data/test/perf_strict.rb +145 -0
- data/test/perf_wab.rb +131 -0
- data/test/sample.rb +54 -0
- data/test/sample/change.rb +14 -0
- data/test/sample/dir.rb +19 -0
- data/test/sample/doc.rb +36 -0
- data/test/sample/file.rb +48 -0
- data/test/sample/group.rb +16 -0
- data/test/sample/hasprops.rb +16 -0
- data/test/sample/layer.rb +12 -0
- data/test/sample/line.rb +20 -0
- data/test/sample/oval.rb +10 -0
- data/test/sample/rect.rb +10 -0
- data/test/sample/shape.rb +35 -0
- data/test/sample/text.rb +20 -0
- data/test/sample_json.rb +37 -0
- data/test/test_compat.rb +509 -0
- data/test/test_custom.rb +406 -0
- data/test/test_debian.rb +53 -0
- data/test/test_fast.rb +470 -0
- data/test/test_file.rb +239 -0
- data/test/test_gc.rb +49 -0
- data/test/test_hash.rb +29 -0
- data/test/test_integer_range.rb +73 -0
- data/test/test_null.rb +376 -0
- data/test/test_object.rb +1018 -0
- data/test/test_saj.rb +186 -0
- data/test/test_scp.rb +433 -0
- data/test/test_strict.rb +410 -0
- data/test/test_various.rb +739 -0
- data/test/test_wab.rb +307 -0
- data/test/test_writer.rb +380 -0
- data/test/tests.rb +24 -0
- data/test/tests_mimic.rb +14 -0
- data/test/tests_mimic_addition.rb +7 -0
- metadata +359 -0
data/ext/oj/trace.c
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/* trace.h
|
|
2
|
+
* Copyright (c) 2018, Peter Ohler
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#include "parse.h"
|
|
7
|
+
#include "trace.h"
|
|
8
|
+
|
|
9
|
+
#define MAX_INDENT 256
|
|
10
|
+
|
|
11
|
+
static void
|
|
12
|
+
fill_indent(char *indent, int depth) {
|
|
13
|
+
if (MAX_INDENT <= depth) {
|
|
14
|
+
depth = MAX_INDENT - 1;
|
|
15
|
+
} else if (depth < 0) {
|
|
16
|
+
depth = 0;
|
|
17
|
+
}
|
|
18
|
+
if (0 < depth) {
|
|
19
|
+
memset(indent, ' ', depth);
|
|
20
|
+
}
|
|
21
|
+
indent[depth] = '\0';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void
|
|
25
|
+
oj_trace(const char *func, VALUE obj, const char *file, int line, int depth, TraceWhere where) {
|
|
26
|
+
char fmt[64];
|
|
27
|
+
char indent[MAX_INDENT];
|
|
28
|
+
|
|
29
|
+
depth *= 2;
|
|
30
|
+
fill_indent(indent, depth);
|
|
31
|
+
sprintf(fmt, "#0:%%13s:%%3d:Oj:%c:%%%ds %%s %%s\n", where, depth);
|
|
32
|
+
printf(fmt, file, line, indent, func, rb_obj_classname(obj));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
void
|
|
36
|
+
oj_trace_parse_call(const char *func, ParseInfo pi, const char *file, int line, VALUE obj) {
|
|
37
|
+
char fmt[64];
|
|
38
|
+
char indent[MAX_INDENT];
|
|
39
|
+
int depth = (int)(stack_size(&pi->stack) * 2);
|
|
40
|
+
|
|
41
|
+
fill_indent(indent, depth);
|
|
42
|
+
sprintf(fmt, "#0:%%13s:%%3d:Oj:-:%%%ds %%s %%s\n", depth);
|
|
43
|
+
printf(fmt, file, line, indent, func, rb_obj_classname(obj));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
void
|
|
47
|
+
oj_trace_parse_in(const char *func, ParseInfo pi, const char *file, int line) {
|
|
48
|
+
char fmt[64];
|
|
49
|
+
char indent[MAX_INDENT];
|
|
50
|
+
int depth = (int)(stack_size(&pi->stack) * 2);
|
|
51
|
+
|
|
52
|
+
fill_indent(indent, depth);
|
|
53
|
+
sprintf(fmt, "#0:%%13s:%%3d:Oj:}:%%%ds %%s\n", depth);
|
|
54
|
+
printf(fmt, file, line, indent, func);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
void
|
|
58
|
+
oj_trace_parse_hash_end(ParseInfo pi, const char *file, int line) {
|
|
59
|
+
char fmt[64];
|
|
60
|
+
char indent[MAX_INDENT];
|
|
61
|
+
int depth = (int)(stack_size(&pi->stack) * 2 - 2);
|
|
62
|
+
Val v = stack_peek(&pi->stack);
|
|
63
|
+
VALUE obj = v->val;
|
|
64
|
+
|
|
65
|
+
fill_indent(indent, depth);
|
|
66
|
+
sprintf(fmt, "#0:%%13s:%%3d:Oj:{:%%%ds hash_end %%s\n", depth);
|
|
67
|
+
printf(fmt, file, line, indent, rb_obj_classname(obj));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
void
|
|
71
|
+
oj_trace_parse_array_end(ParseInfo pi, const char *file, int line) {
|
|
72
|
+
char fmt[64];
|
|
73
|
+
char indent[MAX_INDENT];
|
|
74
|
+
int depth = (int)(stack_size(&pi->stack) * 2);
|
|
75
|
+
|
|
76
|
+
fill_indent(indent, depth);
|
|
77
|
+
sprintf(fmt, "#0:%%13s:%%3d:Oj:{:%%%ds array_ned\n", depth);
|
|
78
|
+
printf(fmt, file, line, indent);
|
|
79
|
+
}
|
data/ext/oj/trace.h
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* trace.h
|
|
2
|
+
* Copyright (c) 2018, Peter Ohler
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#ifndef OJ_TRACE_H
|
|
7
|
+
#define OJ_TRACE_H
|
|
8
|
+
|
|
9
|
+
#include <stdbool.h>
|
|
10
|
+
#include <ruby.h>
|
|
11
|
+
|
|
12
|
+
typedef enum {
|
|
13
|
+
TraceIn = '}',
|
|
14
|
+
TraceOut = '{',
|
|
15
|
+
TraceCall = '-',
|
|
16
|
+
TraceRubyIn = '>',
|
|
17
|
+
TraceRubyOut = '<',
|
|
18
|
+
} TraceWhere;
|
|
19
|
+
|
|
20
|
+
struct _parseInfo;
|
|
21
|
+
|
|
22
|
+
extern void oj_trace(const char *func, VALUE obj, const char *file, int line, int depth, TraceWhere where);
|
|
23
|
+
extern void oj_trace_parse_in(const char *func, struct _parseInfo *pi, const char *file, int line);
|
|
24
|
+
extern void oj_trace_parse_call(const char *func, struct _parseInfo *pi, const char *file, int line, VALUE obj);
|
|
25
|
+
extern void oj_trace_parse_hash_end(struct _parseInfo *pi, const char *file, int line);
|
|
26
|
+
extern void oj_trace_parse_array_end(struct _parseInfo *pi, const char *file, int line);
|
|
27
|
+
|
|
28
|
+
#endif /* OJ_TRACE_H */
|
data/ext/oj/util.c
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// Copyright (c) 2019, Peter Ohler, All rights reserved.
|
|
2
|
+
|
|
3
|
+
#include "util.h"
|
|
4
|
+
|
|
5
|
+
#include <stdbool.h>
|
|
6
|
+
#include <stdint.h>
|
|
7
|
+
#include <stdio.h>
|
|
8
|
+
#include <string.h>
|
|
9
|
+
#include <time.h>
|
|
10
|
+
|
|
11
|
+
#define SECS_PER_DAY 86400LL
|
|
12
|
+
#define SECS_PER_YEAR 31536000LL
|
|
13
|
+
#define SECS_PER_LEAP 31622400LL
|
|
14
|
+
#define SECS_PER_QUAD_YEAR (SECS_PER_YEAR * 3 + SECS_PER_LEAP)
|
|
15
|
+
#define SECS_PER_CENT (SECS_PER_QUAD_YEAR * 24 + SECS_PER_YEAR * 4)
|
|
16
|
+
#define SECS_PER_LEAP_CENT (SECS_PER_CENT + SECS_PER_DAY)
|
|
17
|
+
#define SECS_PER_QUAD_CENT (SECS_PER_CENT * 4 + SECS_PER_DAY)
|
|
18
|
+
|
|
19
|
+
static int64_t eom_secs[] = {
|
|
20
|
+
2678400, // January (31)
|
|
21
|
+
5097600, // February (28) 2419200 2505600
|
|
22
|
+
7776000, // March (31)
|
|
23
|
+
10368000, // April (30 2592000
|
|
24
|
+
13046400, // May (31)
|
|
25
|
+
15638400, // June (30)
|
|
26
|
+
18316800, // July (31)
|
|
27
|
+
20995200, // August (31)
|
|
28
|
+
23587200, // September (30)
|
|
29
|
+
26265600, // October (31)
|
|
30
|
+
28857600, // November (30)
|
|
31
|
+
31536000, // December (31)
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
static int64_t eom_leap_secs[] = {
|
|
35
|
+
2678400, // January (31)
|
|
36
|
+
5184000, // February (28) 2419200 2505600
|
|
37
|
+
7862400, // March (31)
|
|
38
|
+
10454400, // April (30 2592000
|
|
39
|
+
13132800, // May (31)
|
|
40
|
+
15724800, // June (30)
|
|
41
|
+
18403200, // July (31)
|
|
42
|
+
21081600, // August (31)
|
|
43
|
+
23673600, // September (30)
|
|
44
|
+
26352000, // October (31)
|
|
45
|
+
28944000, // November (30)
|
|
46
|
+
31622400, // December (31)
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
void
|
|
51
|
+
sec_as_time(int64_t secs, TimeInfo ti) {
|
|
52
|
+
int64_t qc = 0;
|
|
53
|
+
int64_t c = 0;
|
|
54
|
+
int64_t qy = 0;
|
|
55
|
+
int64_t y = 0;
|
|
56
|
+
bool leap = false;
|
|
57
|
+
int64_t *ms;
|
|
58
|
+
int m;
|
|
59
|
+
int shift = 0;
|
|
60
|
+
|
|
61
|
+
secs += 62167219200LL; // normalize to first day of the year 0
|
|
62
|
+
if (secs < 0) {
|
|
63
|
+
shift = -secs / SECS_PER_QUAD_CENT;
|
|
64
|
+
shift++;
|
|
65
|
+
secs += shift * SECS_PER_QUAD_CENT;
|
|
66
|
+
}
|
|
67
|
+
qc = secs / SECS_PER_QUAD_CENT;
|
|
68
|
+
secs = secs - qc * SECS_PER_QUAD_CENT;
|
|
69
|
+
if (secs < SECS_PER_LEAP) {
|
|
70
|
+
leap = true;
|
|
71
|
+
} else if (secs < SECS_PER_QUAD_YEAR) {
|
|
72
|
+
if (SECS_PER_LEAP <= secs) {
|
|
73
|
+
secs -= SECS_PER_LEAP;
|
|
74
|
+
y = secs / SECS_PER_YEAR;
|
|
75
|
+
secs = secs - y * SECS_PER_YEAR;
|
|
76
|
+
y++;
|
|
77
|
+
leap = false;
|
|
78
|
+
}
|
|
79
|
+
} else if (secs < SECS_PER_LEAP_CENT) { // first century in 400 years is a leap century (one extra day)
|
|
80
|
+
qy = secs / SECS_PER_QUAD_YEAR;
|
|
81
|
+
secs = secs - qy * SECS_PER_QUAD_YEAR;
|
|
82
|
+
if (secs < SECS_PER_LEAP) {
|
|
83
|
+
leap = true;
|
|
84
|
+
} else {
|
|
85
|
+
secs -= SECS_PER_LEAP;
|
|
86
|
+
y = secs / SECS_PER_YEAR;
|
|
87
|
+
secs = secs - y * SECS_PER_YEAR;
|
|
88
|
+
y++;
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
secs -= SECS_PER_LEAP_CENT;
|
|
92
|
+
c = secs / SECS_PER_CENT;
|
|
93
|
+
secs = secs - c * SECS_PER_CENT;
|
|
94
|
+
c++;
|
|
95
|
+
if (secs < SECS_PER_YEAR * 4) {
|
|
96
|
+
y = secs / SECS_PER_YEAR;
|
|
97
|
+
secs = secs - y * SECS_PER_YEAR;
|
|
98
|
+
} else {
|
|
99
|
+
secs -= SECS_PER_YEAR * 4;
|
|
100
|
+
qy = secs / SECS_PER_QUAD_YEAR;
|
|
101
|
+
secs = secs - qy * SECS_PER_QUAD_YEAR;
|
|
102
|
+
qy++;
|
|
103
|
+
if (secs < SECS_PER_LEAP) {
|
|
104
|
+
leap = true;
|
|
105
|
+
} else {
|
|
106
|
+
secs -= SECS_PER_LEAP;
|
|
107
|
+
y = secs / SECS_PER_YEAR;
|
|
108
|
+
secs = secs - y * SECS_PER_YEAR;
|
|
109
|
+
y++;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
ti->year = (qc - shift) * 400 + c * 100 + qy * 4 + y;
|
|
114
|
+
if (leap) {
|
|
115
|
+
ms = eom_leap_secs;
|
|
116
|
+
} else {
|
|
117
|
+
ms = eom_secs;
|
|
118
|
+
}
|
|
119
|
+
for (m = 1; m <= 12; m++, ms++) {
|
|
120
|
+
if (secs < *ms) {
|
|
121
|
+
if (1 < m) {
|
|
122
|
+
secs -= *(ms - 1);
|
|
123
|
+
}
|
|
124
|
+
ti->mon = m;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
ti->day = secs / 86400LL;
|
|
129
|
+
secs = secs - (int64_t)ti->day * 86400LL;
|
|
130
|
+
ti->day++;
|
|
131
|
+
ti->hour = secs / 3600LL;
|
|
132
|
+
secs = secs - (int64_t)ti->hour * 3600LL;
|
|
133
|
+
ti->min = secs / 60LL;
|
|
134
|
+
secs = secs - (int64_t)ti->min * 60LL;
|
|
135
|
+
ti->sec = secs;
|
|
136
|
+
}
|
data/ext/oj/util.h
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Copyright (c) 2019, Peter Ohler, All rights reserved.
|
|
2
|
+
|
|
3
|
+
#ifndef OJ_UTIL_H
|
|
4
|
+
#define OJ_UTIL_H
|
|
5
|
+
|
|
6
|
+
#include <stdint.h>
|
|
7
|
+
|
|
8
|
+
typedef struct _timeInfo {
|
|
9
|
+
int sec;
|
|
10
|
+
int min;
|
|
11
|
+
int hour;
|
|
12
|
+
int day;
|
|
13
|
+
int mon;
|
|
14
|
+
int year;
|
|
15
|
+
} *TimeInfo;
|
|
16
|
+
|
|
17
|
+
extern void sec_as_time(int64_t secs, TimeInfo ti);
|
|
18
|
+
|
|
19
|
+
#endif /* OJ_UTIL_H */
|
data/ext/oj/val_stack.c
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/* val_stack.c
|
|
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
|
+
*/
|
|
30
|
+
|
|
31
|
+
#include <string.h>
|
|
32
|
+
|
|
33
|
+
#include "oj.h"
|
|
34
|
+
#include "odd.h"
|
|
35
|
+
#include "val_stack.h"
|
|
36
|
+
|
|
37
|
+
static void
|
|
38
|
+
mark(void *ptr) {
|
|
39
|
+
ValStack stack = (ValStack)ptr;
|
|
40
|
+
Val v;
|
|
41
|
+
|
|
42
|
+
if (0 == ptr) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
#if HAVE_LIBPTHREAD
|
|
46
|
+
pthread_mutex_lock(&stack->mutex);
|
|
47
|
+
#else
|
|
48
|
+
rb_mutex_lock(stack->mutex);
|
|
49
|
+
rb_gc_mark(stack->mutex);
|
|
50
|
+
#endif
|
|
51
|
+
for (v = stack->head; v < stack->tail; v++) {
|
|
52
|
+
if (Qnil != v->val && Qundef != v->val) {
|
|
53
|
+
rb_gc_mark(v->val);
|
|
54
|
+
}
|
|
55
|
+
if (Qnil != v->key_val && Qundef != v->key_val) {
|
|
56
|
+
rb_gc_mark(v->key_val);
|
|
57
|
+
}
|
|
58
|
+
if (NULL != v->odd_args) {
|
|
59
|
+
VALUE *a;
|
|
60
|
+
int i;
|
|
61
|
+
|
|
62
|
+
for (i = v->odd_args->odd->attr_cnt, a = v->odd_args->args; 0 < i; i--, a++) {
|
|
63
|
+
if (Qnil != *a) {
|
|
64
|
+
rb_gc_mark(*a);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
#if HAVE_LIBPTHREAD
|
|
70
|
+
pthread_mutex_unlock(&stack->mutex);
|
|
71
|
+
#else
|
|
72
|
+
rb_mutex_unlock(stack->mutex);
|
|
73
|
+
#endif
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
VALUE
|
|
77
|
+
oj_stack_init(ValStack stack) {
|
|
78
|
+
#if HAVE_LIBPTHREAD
|
|
79
|
+
int err;
|
|
80
|
+
|
|
81
|
+
if (0 != (err = pthread_mutex_init(&stack->mutex, 0))) {
|
|
82
|
+
rb_raise(rb_eException, "failed to initialize a mutex. %s", strerror(err));
|
|
83
|
+
}
|
|
84
|
+
#else
|
|
85
|
+
stack->mutex = rb_mutex_new();
|
|
86
|
+
#endif
|
|
87
|
+
stack->head = stack->base;
|
|
88
|
+
stack->end = stack->base + sizeof(stack->base) / sizeof(struct _val);
|
|
89
|
+
stack->tail = stack->head;
|
|
90
|
+
stack->head->val = Qundef;
|
|
91
|
+
stack->head->key = NULL;
|
|
92
|
+
stack->head->key_val = Qundef;
|
|
93
|
+
stack->head->classname = NULL;
|
|
94
|
+
stack->head->odd_args = NULL;
|
|
95
|
+
stack->head->clas = Qundef;
|
|
96
|
+
stack->head->klen = 0;
|
|
97
|
+
stack->head->clen = 0;
|
|
98
|
+
stack->head->next = NEXT_NONE;
|
|
99
|
+
|
|
100
|
+
return Data_Wrap_Struct(oj_cstack_class, mark, 0, stack);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const char*
|
|
104
|
+
oj_stack_next_string(ValNext n) {
|
|
105
|
+
switch (n) {
|
|
106
|
+
case NEXT_ARRAY_NEW: return "array element or close";
|
|
107
|
+
case NEXT_ARRAY_ELEMENT: return "array element";
|
|
108
|
+
case NEXT_ARRAY_COMMA: return "comma";
|
|
109
|
+
case NEXT_HASH_NEW: return "hash pair or close";
|
|
110
|
+
case NEXT_HASH_KEY: return "hash key";
|
|
111
|
+
case NEXT_HASH_COLON: return "colon";
|
|
112
|
+
case NEXT_HASH_VALUE: return "hash value";
|
|
113
|
+
case NEXT_HASH_COMMA: return "comma";
|
|
114
|
+
case NEXT_NONE: break;
|
|
115
|
+
default: break;
|
|
116
|
+
}
|
|
117
|
+
return "nothing";
|
|
118
|
+
}
|
data/ext/oj/val_stack.h
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/* val_stack.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
|
+
*/
|
|
30
|
+
|
|
31
|
+
#ifndef OJ_VAL_STACK_H
|
|
32
|
+
#define OJ_VAL_STACK_H
|
|
33
|
+
|
|
34
|
+
#include "ruby.h"
|
|
35
|
+
#include "odd.h"
|
|
36
|
+
#include <stdint.h>
|
|
37
|
+
#if HAVE_LIBPTHREAD
|
|
38
|
+
#include <pthread.h>
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
#define STACK_INC 64
|
|
42
|
+
|
|
43
|
+
typedef enum {
|
|
44
|
+
NEXT_NONE = 0,
|
|
45
|
+
NEXT_ARRAY_NEW = 'a',
|
|
46
|
+
NEXT_ARRAY_ELEMENT = 'e',
|
|
47
|
+
NEXT_ARRAY_COMMA = ',',
|
|
48
|
+
NEXT_HASH_NEW = 'h',
|
|
49
|
+
NEXT_HASH_KEY = 'k',
|
|
50
|
+
NEXT_HASH_COLON = ':',
|
|
51
|
+
NEXT_HASH_VALUE = 'v',
|
|
52
|
+
NEXT_HASH_COMMA = 'n',
|
|
53
|
+
} ValNext;
|
|
54
|
+
|
|
55
|
+
typedef struct _val {
|
|
56
|
+
volatile VALUE val;
|
|
57
|
+
const char *key;
|
|
58
|
+
char karray[32];
|
|
59
|
+
volatile VALUE key_val;
|
|
60
|
+
const char *classname;
|
|
61
|
+
VALUE clas;
|
|
62
|
+
OddArgs odd_args;
|
|
63
|
+
uint16_t klen;
|
|
64
|
+
uint16_t clen;
|
|
65
|
+
char next; // ValNext
|
|
66
|
+
char k1; // first original character in the key
|
|
67
|
+
char kalloc;
|
|
68
|
+
} *Val;
|
|
69
|
+
|
|
70
|
+
typedef struct _valStack {
|
|
71
|
+
struct _val base[STACK_INC];
|
|
72
|
+
Val head; // current stack
|
|
73
|
+
Val end; // stack end
|
|
74
|
+
Val tail; // pointer to one past last element name on stack
|
|
75
|
+
#if HAVE_LIBPTHREAD
|
|
76
|
+
pthread_mutex_t mutex;
|
|
77
|
+
#else
|
|
78
|
+
VALUE mutex;
|
|
79
|
+
#endif
|
|
80
|
+
|
|
81
|
+
} *ValStack;
|
|
82
|
+
|
|
83
|
+
extern VALUE oj_stack_init(ValStack stack);
|
|
84
|
+
|
|
85
|
+
inline static int
|
|
86
|
+
stack_empty(ValStack stack) {
|
|
87
|
+
return (stack->head == stack->tail);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
inline static void
|
|
91
|
+
stack_cleanup(ValStack stack) {
|
|
92
|
+
if (stack->base != stack->head) {
|
|
93
|
+
xfree(stack->head);
|
|
94
|
+
stack->head = NULL;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
inline static void
|
|
99
|
+
stack_push(ValStack stack, VALUE val, ValNext next) {
|
|
100
|
+
if (stack->end <= stack->tail) {
|
|
101
|
+
size_t len = stack->end - stack->head;
|
|
102
|
+
size_t toff = stack->tail - stack->head;
|
|
103
|
+
Val head = stack->head;
|
|
104
|
+
|
|
105
|
+
// A realloc can trigger a GC so make sure it happens outside the lock
|
|
106
|
+
// but lock before changing pointers.
|
|
107
|
+
if (stack->base == stack->head) {
|
|
108
|
+
head = ALLOC_N(struct _val, len + STACK_INC);
|
|
109
|
+
memcpy(head, stack->base, sizeof(struct _val) * len);
|
|
110
|
+
} else {
|
|
111
|
+
REALLOC_N(head, struct _val, len + STACK_INC);
|
|
112
|
+
}
|
|
113
|
+
#if HAVE_LIBPTHREAD
|
|
114
|
+
pthread_mutex_lock(&stack->mutex);
|
|
115
|
+
#else
|
|
116
|
+
rb_mutex_lock(stack->mutex);
|
|
117
|
+
#endif
|
|
118
|
+
stack->head = head;
|
|
119
|
+
stack->tail = stack->head + toff;
|
|
120
|
+
stack->end = stack->head + len + STACK_INC;
|
|
121
|
+
#if HAVE_LIBPTHREAD
|
|
122
|
+
pthread_mutex_unlock(&stack->mutex);
|
|
123
|
+
#else
|
|
124
|
+
rb_mutex_unlock(stack->mutex);
|
|
125
|
+
#endif
|
|
126
|
+
}
|
|
127
|
+
stack->tail->val = val;
|
|
128
|
+
stack->tail->next = next;
|
|
129
|
+
stack->tail->classname = NULL;
|
|
130
|
+
stack->tail->clas = Qundef;
|
|
131
|
+
stack->tail->odd_args = NULL;
|
|
132
|
+
stack->tail->key = 0;
|
|
133
|
+
stack->tail->key_val = Qundef;
|
|
134
|
+
stack->tail->clen = 0;
|
|
135
|
+
stack->tail->klen = 0;
|
|
136
|
+
stack->tail->kalloc = 0;
|
|
137
|
+
stack->tail++;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
inline static size_t
|
|
141
|
+
stack_size(ValStack stack) {
|
|
142
|
+
return stack->tail - stack->head;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
inline static Val
|
|
146
|
+
stack_peek(ValStack stack) {
|
|
147
|
+
if (stack->head < stack->tail) {
|
|
148
|
+
return stack->tail - 1;
|
|
149
|
+
}
|
|
150
|
+
return 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
inline static Val
|
|
154
|
+
stack_peek_up(ValStack stack) {
|
|
155
|
+
if (stack->head < stack->tail - 1) {
|
|
156
|
+
return stack->tail - 2;
|
|
157
|
+
}
|
|
158
|
+
return 0;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
inline static Val
|
|
162
|
+
stack_prev(ValStack stack) {
|
|
163
|
+
return stack->tail;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
inline static VALUE
|
|
167
|
+
stack_head_val(ValStack stack) {
|
|
168
|
+
if (Qundef != stack->head->val) {
|
|
169
|
+
return stack->head->val;
|
|
170
|
+
}
|
|
171
|
+
return Qnil;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
inline static Val
|
|
175
|
+
stack_pop(ValStack stack) {
|
|
176
|
+
if (stack->head < stack->tail) {
|
|
177
|
+
stack->tail--;
|
|
178
|
+
return stack->tail;
|
|
179
|
+
}
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
extern const char* oj_stack_next_string(ValNext n);
|
|
184
|
+
|
|
185
|
+
#endif /* OJ_VAL_STACK_H */
|