oj 3.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +104 -0
  4. data/ext/oj/buf.h +103 -0
  5. data/ext/oj/cache8.c +107 -0
  6. data/ext/oj/cache8.h +48 -0
  7. data/ext/oj/circarray.c +68 -0
  8. data/ext/oj/circarray.h +23 -0
  9. data/ext/oj/code.c +235 -0
  10. data/ext/oj/code.h +42 -0
  11. data/ext/oj/compat.c +299 -0
  12. data/ext/oj/custom.c +1191 -0
  13. data/ext/oj/dump.c +1252 -0
  14. data/ext/oj/dump.h +96 -0
  15. data/ext/oj/dump_compat.c +977 -0
  16. data/ext/oj/dump_leaf.c +252 -0
  17. data/ext/oj/dump_object.c +837 -0
  18. data/ext/oj/dump_strict.c +433 -0
  19. data/ext/oj/encode.h +45 -0
  20. data/ext/oj/err.c +57 -0
  21. data/ext/oj/err.h +70 -0
  22. data/ext/oj/extconf.rb +47 -0
  23. data/ext/oj/fast.c +1771 -0
  24. data/ext/oj/hash.c +163 -0
  25. data/ext/oj/hash.h +46 -0
  26. data/ext/oj/hash_test.c +512 -0
  27. data/ext/oj/mimic_json.c +878 -0
  28. data/ext/oj/object.c +771 -0
  29. data/ext/oj/odd.c +231 -0
  30. data/ext/oj/odd.h +44 -0
  31. data/ext/oj/oj.c +1704 -0
  32. data/ext/oj/oj.h +385 -0
  33. data/ext/oj/parse.c +1086 -0
  34. data/ext/oj/parse.h +111 -0
  35. data/ext/oj/rails.c +1493 -0
  36. data/ext/oj/rails.h +21 -0
  37. data/ext/oj/reader.c +231 -0
  38. data/ext/oj/reader.h +151 -0
  39. data/ext/oj/resolve.c +102 -0
  40. data/ext/oj/resolve.h +14 -0
  41. data/ext/oj/rxclass.c +147 -0
  42. data/ext/oj/rxclass.h +27 -0
  43. data/ext/oj/saj.c +714 -0
  44. data/ext/oj/scp.c +224 -0
  45. data/ext/oj/sparse.c +910 -0
  46. data/ext/oj/stream_writer.c +363 -0
  47. data/ext/oj/strict.c +212 -0
  48. data/ext/oj/string_writer.c +534 -0
  49. data/ext/oj/trace.c +79 -0
  50. data/ext/oj/trace.h +28 -0
  51. data/ext/oj/util.c +136 -0
  52. data/ext/oj/util.h +19 -0
  53. data/ext/oj/val_stack.c +118 -0
  54. data/ext/oj/val_stack.h +185 -0
  55. data/ext/oj/wab.c +631 -0
  56. data/lib/oj.rb +21 -0
  57. data/lib/oj/active_support_helper.rb +41 -0
  58. data/lib/oj/bag.rb +88 -0
  59. data/lib/oj/easy_hash.rb +52 -0
  60. data/lib/oj/error.rb +22 -0
  61. data/lib/oj/json.rb +176 -0
  62. data/lib/oj/mimic.rb +267 -0
  63. data/lib/oj/saj.rb +66 -0
  64. data/lib/oj/schandler.rb +142 -0
  65. data/lib/oj/state.rb +131 -0
  66. data/lib/oj/version.rb +5 -0
  67. data/pages/Advanced.md +22 -0
  68. data/pages/Compatibility.md +25 -0
  69. data/pages/Custom.md +23 -0
  70. data/pages/Encoding.md +65 -0
  71. data/pages/JsonGem.md +79 -0
  72. data/pages/Modes.md +155 -0
  73. data/pages/Options.md +283 -0
  74. data/pages/Rails.md +116 -0
  75. data/pages/Security.md +20 -0
  76. data/pages/WAB.md +13 -0
  77. data/test/_test_active.rb +76 -0
  78. data/test/_test_active_mimic.rb +96 -0
  79. data/test/_test_mimic_rails.rb +126 -0
  80. data/test/activerecord/result_test.rb +27 -0
  81. data/test/activesupport4/decoding_test.rb +108 -0
  82. data/test/activesupport4/encoding_test.rb +531 -0
  83. data/test/activesupport4/test_helper.rb +41 -0
  84. data/test/activesupport5/decoding_test.rb +125 -0
  85. data/test/activesupport5/encoding_test.rb +485 -0
  86. data/test/activesupport5/encoding_test_cases.rb +90 -0
  87. data/test/activesupport5/test_helper.rb +50 -0
  88. data/test/activesupport5/time_zone_test_helpers.rb +24 -0
  89. data/test/bar.rb +25 -0
  90. data/test/files.rb +29 -0
  91. data/test/foo.rb +167 -0
  92. data/test/helper.rb +26 -0
  93. data/test/isolated/shared.rb +308 -0
  94. data/test/isolated/test_mimic_after.rb +13 -0
  95. data/test/isolated/test_mimic_alone.rb +12 -0
  96. data/test/isolated/test_mimic_as_json.rb +45 -0
  97. data/test/isolated/test_mimic_before.rb +13 -0
  98. data/test/isolated/test_mimic_define.rb +28 -0
  99. data/test/isolated/test_mimic_rails_after.rb +22 -0
  100. data/test/isolated/test_mimic_rails_before.rb +21 -0
  101. data/test/isolated/test_mimic_redefine.rb +15 -0
  102. data/test/json_gem/json_addition_test.rb +216 -0
  103. data/test/json_gem/json_common_interface_test.rb +148 -0
  104. data/test/json_gem/json_encoding_test.rb +107 -0
  105. data/test/json_gem/json_ext_parser_test.rb +20 -0
  106. data/test/json_gem/json_fixtures_test.rb +35 -0
  107. data/test/json_gem/json_generator_test.rb +383 -0
  108. data/test/json_gem/json_generic_object_test.rb +90 -0
  109. data/test/json_gem/json_parser_test.rb +470 -0
  110. data/test/json_gem/json_string_matching_test.rb +42 -0
  111. data/test/json_gem/test_helper.rb +18 -0
  112. data/test/perf.rb +107 -0
  113. data/test/perf_compat.rb +130 -0
  114. data/test/perf_fast.rb +164 -0
  115. data/test/perf_file.rb +64 -0
  116. data/test/perf_object.rb +138 -0
  117. data/test/perf_saj.rb +109 -0
  118. data/test/perf_scp.rb +151 -0
  119. data/test/perf_simple.rb +287 -0
  120. data/test/perf_strict.rb +145 -0
  121. data/test/perf_wab.rb +131 -0
  122. data/test/sample.rb +54 -0
  123. data/test/sample/change.rb +14 -0
  124. data/test/sample/dir.rb +19 -0
  125. data/test/sample/doc.rb +36 -0
  126. data/test/sample/file.rb +48 -0
  127. data/test/sample/group.rb +16 -0
  128. data/test/sample/hasprops.rb +16 -0
  129. data/test/sample/layer.rb +12 -0
  130. data/test/sample/line.rb +20 -0
  131. data/test/sample/oval.rb +10 -0
  132. data/test/sample/rect.rb +10 -0
  133. data/test/sample/shape.rb +35 -0
  134. data/test/sample/text.rb +20 -0
  135. data/test/sample_json.rb +37 -0
  136. data/test/test_compat.rb +509 -0
  137. data/test/test_custom.rb +503 -0
  138. data/test/test_debian.rb +53 -0
  139. data/test/test_fast.rb +470 -0
  140. data/test/test_file.rb +239 -0
  141. data/test/test_gc.rb +49 -0
  142. data/test/test_hash.rb +29 -0
  143. data/test/test_integer_range.rb +73 -0
  144. data/test/test_null.rb +376 -0
  145. data/test/test_object.rb +1018 -0
  146. data/test/test_saj.rb +186 -0
  147. data/test/test_scp.rb +433 -0
  148. data/test/test_strict.rb +410 -0
  149. data/test/test_various.rb +741 -0
  150. data/test/test_wab.rb +307 -0
  151. data/test/test_writer.rb +380 -0
  152. data/test/tests.rb +24 -0
  153. data/test/tests_mimic.rb +14 -0
  154. data/test/tests_mimic_addition.rb +7 -0
  155. data/test/zoo.rb +13 -0
  156. metadata +359 -0
@@ -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
+ }
@@ -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 */
@@ -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
+ }
@@ -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 */
@@ -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
+ }
@@ -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 */