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.
Files changed (156) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +96 -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 +1188 -0
  13. data/ext/oj/dump.c +1232 -0
  14. data/ext/oj/dump.h +94 -0
  15. data/ext/oj/dump_compat.c +973 -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 +873 -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 +1694 -0
  32. data/ext/oj/oj.h +381 -0
  33. data/ext/oj/parse.c +1085 -0
  34. data/ext/oj/parse.h +111 -0
  35. data/ext/oj/rails.c +1485 -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 +512 -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 +154 -0
  73. data/pages/Options.md +266 -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/big.rb +15 -0
  90. data/test/files.rb +29 -0
  91. data/test/foo.rb +33 -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/mem.rb +35 -0
  113. data/test/perf.rb +107 -0
  114. data/test/perf_compat.rb +130 -0
  115. data/test/perf_fast.rb +164 -0
  116. data/test/perf_file.rb +64 -0
  117. data/test/perf_object.rb +138 -0
  118. data/test/perf_saj.rb +109 -0
  119. data/test/perf_scp.rb +151 -0
  120. data/test/perf_simple.rb +287 -0
  121. data/test/perf_strict.rb +145 -0
  122. data/test/perf_wab.rb +131 -0
  123. data/test/sample.rb +54 -0
  124. data/test/sample/change.rb +14 -0
  125. data/test/sample/dir.rb +19 -0
  126. data/test/sample/doc.rb +36 -0
  127. data/test/sample/file.rb +48 -0
  128. data/test/sample/group.rb +16 -0
  129. data/test/sample/hasprops.rb +16 -0
  130. data/test/sample/layer.rb +12 -0
  131. data/test/sample/line.rb +20 -0
  132. data/test/sample/oval.rb +10 -0
  133. data/test/sample/rect.rb +10 -0
  134. data/test/sample/shape.rb +35 -0
  135. data/test/sample/text.rb +20 -0
  136. data/test/sample_json.rb +37 -0
  137. data/test/test_compat.rb +509 -0
  138. data/test/test_custom.rb +406 -0
  139. data/test/test_debian.rb +53 -0
  140. data/test/test_fast.rb +470 -0
  141. data/test/test_file.rb +239 -0
  142. data/test/test_gc.rb +49 -0
  143. data/test/test_hash.rb +29 -0
  144. data/test/test_integer_range.rb +73 -0
  145. data/test/test_null.rb +376 -0
  146. data/test/test_object.rb +1018 -0
  147. data/test/test_saj.rb +186 -0
  148. data/test/test_scp.rb +433 -0
  149. data/test/test_strict.rb +410 -0
  150. data/test/test_various.rb +739 -0
  151. data/test/test_wab.rb +307 -0
  152. data/test/test_writer.rb +380 -0
  153. data/test/tests.rb +24 -0
  154. data/test/tests_mimic.rb +14 -0
  155. data/test/tests_mimic_addition.rb +7 -0
  156. metadata +359 -0
@@ -0,0 +1,21 @@
1
+ /* rails.h
2
+ * Copyright (c) 2017, Peter Ohler
3
+ * All rights reserved.
4
+ */
5
+
6
+ #ifndef OJ_RAILS_H
7
+ #define OJ_RAILS_H
8
+
9
+ #include "dump.h"
10
+
11
+ extern void oj_mimic_rails_init();
12
+ extern ROpt oj_rails_get_opt(ROptTable rot, VALUE clas);
13
+
14
+ extern bool oj_rails_hash_opt;
15
+ extern bool oj_rails_array_opt;
16
+ extern bool oj_rails_float_opt;
17
+
18
+ extern VALUE oj_optimize_rails(VALUE self);
19
+
20
+
21
+ #endif /* OJ_RAILS_H */
@@ -0,0 +1,231 @@
1
+ /* reader.c
2
+ * Copyright (c) 2011, Peter Ohler
3
+ * All rights reserved.
4
+ */
5
+
6
+ #include <stdlib.h>
7
+ #include <errno.h>
8
+ #include <stdio.h>
9
+ #include <strings.h>
10
+ #include <sys/types.h>
11
+ #if NEEDS_UIO
12
+ #include <sys/uio.h>
13
+ #endif
14
+ #include <unistd.h>
15
+ #include <time.h>
16
+
17
+ #include "ruby.h"
18
+ #include "oj.h"
19
+ #include "reader.h"
20
+
21
+ #define BUF_PAD 4
22
+
23
+ static VALUE rescue_cb(VALUE rdr, VALUE err);
24
+ static VALUE io_cb(VALUE rdr);
25
+ static VALUE partial_io_cb(VALUE rdr);
26
+ static int read_from_io(Reader reader);
27
+ static int read_from_fd(Reader reader);
28
+ static int read_from_io_partial(Reader reader);
29
+ //static int read_from_str(Reader reader);
30
+
31
+ void
32
+ oj_reader_init(Reader reader, VALUE io, int fd, bool to_s) {
33
+ VALUE io_class = rb_obj_class(io);
34
+ VALUE stat;
35
+ VALUE ftype;
36
+
37
+ reader->head = reader->base;
38
+ *((char*)reader->head) = '\0';
39
+ reader->end = reader->head + sizeof(reader->base) - BUF_PAD;
40
+ reader->tail = reader->head;
41
+ reader->read_end = reader->head;
42
+ reader->pro = 0;
43
+ reader->str = 0;
44
+ reader->pos = 0;
45
+ reader->line = 1;
46
+ reader->col = 0;
47
+ reader->free_head = 0;
48
+
49
+ if (0 != fd) {
50
+ reader->read_func = read_from_fd;
51
+ reader->fd = fd;
52
+ } else if (rb_cString == io_class) {
53
+ reader->read_func = 0;
54
+ reader->in_str = StringValuePtr(io);
55
+ reader->head = (char*)reader->in_str;
56
+ reader->tail = reader->head;
57
+ reader->read_end = reader->head + RSTRING_LEN(io);
58
+ } else if (oj_stringio_class == io_class) {
59
+ VALUE s = rb_funcall2(io, oj_string_id, 0, 0);
60
+
61
+ reader->read_func = 0;
62
+ reader->in_str = StringValuePtr(s);
63
+ reader->head = (char*)reader->in_str;
64
+ reader->tail = reader->head;
65
+ reader->read_end = reader->head + RSTRING_LEN(s);
66
+ } else if (rb_cFile == io_class &&
67
+ Qnil != (stat = rb_funcall(io, oj_stat_id, 0)) &&
68
+ Qnil != (ftype = rb_funcall(stat, oj_ftype_id, 0)) &&
69
+ 0 == strcmp("file", StringValuePtr(ftype)) &&
70
+ 0 == FIX2INT(rb_funcall(io, oj_pos_id, 0))) {
71
+ reader->read_func = read_from_fd;
72
+ reader->fd = FIX2INT(rb_funcall(io, oj_fileno_id, 0));
73
+ } else if (rb_respond_to(io, oj_readpartial_id)) {
74
+ reader->read_func = read_from_io_partial;
75
+ reader->io = io;
76
+ } else if (rb_respond_to(io, oj_read_id)) {
77
+ reader->read_func = read_from_io;
78
+ reader->io = io;
79
+ } else if (to_s) {
80
+ volatile VALUE rstr = rb_funcall(io, oj_to_s_id, 0);
81
+
82
+ reader->read_func = 0;
83
+ reader->in_str = StringValuePtr(rstr);
84
+ reader->head = (char*)reader->in_str;
85
+ reader->tail = reader->head;
86
+ reader->read_end = reader->head + RSTRING_LEN(rstr);
87
+ } else {
88
+ rb_raise(rb_eArgError, "parser io argument must be a String or respond to readpartial() or read().\n");
89
+ }
90
+ }
91
+
92
+ int
93
+ oj_reader_read(Reader reader) {
94
+ int err;
95
+ size_t shift = 0;
96
+
97
+ if (0 == reader->read_func) {
98
+ return -1;
99
+ }
100
+ // if there is not much room to read into, shift or realloc a larger buffer.
101
+ if (reader->head < reader->tail && 4096 > reader->end - reader->tail) {
102
+ if (0 == reader->pro) {
103
+ shift = reader->tail - reader->head;
104
+ } else {
105
+ shift = reader->pro - reader->head - 1; // leave one character so we can backup one
106
+ }
107
+ if (0 >= shift) { /* no space left so allocate more */
108
+ const char *old = reader->head;
109
+ size_t size = reader->end - reader->head + BUF_PAD;
110
+
111
+ if (reader->head == reader->base) {
112
+ reader->head = ALLOC_N(char, size * 2);
113
+ memcpy((char*)reader->head, old, size);
114
+ } else {
115
+ REALLOC_N(reader->head, char, size * 2);
116
+ }
117
+ reader->free_head = 1;
118
+ reader->end = reader->head + size * 2 - BUF_PAD;
119
+ reader->tail = reader->head + (reader->tail - old);
120
+ reader->read_end = reader->head + (reader->read_end - old);
121
+ if (0 != reader->pro) {
122
+ reader->pro = reader->head + (reader->pro - old);
123
+ }
124
+ if (0 != reader->str) {
125
+ reader->str = reader->head + (reader->str - old);
126
+ }
127
+ } else {
128
+ memmove((char*)reader->head, reader->head + shift, reader->read_end - (reader->head + shift));
129
+ reader->tail -= shift;
130
+ reader->read_end -= shift;
131
+ if (0 != reader->pro) {
132
+ reader->pro -= shift;
133
+ }
134
+ if (0 != reader->str) {
135
+ reader->str -= shift;
136
+ }
137
+ }
138
+ }
139
+ err = reader->read_func(reader);
140
+ *(char*)reader->read_end = '\0';
141
+
142
+ return err;
143
+ }
144
+
145
+ static VALUE
146
+ rescue_cb(VALUE rbuf, VALUE err) {
147
+ VALUE clas = rb_obj_class(err);
148
+
149
+ if (rb_eTypeError != clas && rb_eEOFError != clas) {
150
+ Reader reader = (Reader)rbuf;
151
+
152
+ rb_raise(clas, "at line %d, column %d\n", reader->line, reader->col);
153
+ }
154
+ return Qfalse;
155
+ }
156
+
157
+ static VALUE
158
+ partial_io_cb(VALUE rbuf) {
159
+ Reader reader = (Reader)rbuf;
160
+ VALUE args[1];
161
+ VALUE rstr;
162
+ char *str;
163
+ size_t cnt;
164
+
165
+ args[0] = ULONG2NUM(reader->end - reader->tail);
166
+ rstr = rb_funcall2(reader->io, oj_readpartial_id, 1, args);
167
+ if (Qnil == rstr) {
168
+ return Qfalse;
169
+ }
170
+ str = StringValuePtr(rstr);
171
+ cnt = RSTRING_LEN(rstr);
172
+ //printf("*** partial read %lu bytes, str: '%s'\n", cnt, str);
173
+ strcpy(reader->tail, str);
174
+ reader->read_end = reader->tail + cnt;
175
+
176
+ return Qtrue;
177
+ }
178
+
179
+ static VALUE
180
+ io_cb(VALUE rbuf) {
181
+ Reader reader = (Reader)rbuf;
182
+ VALUE args[1];
183
+ VALUE rstr;
184
+ char *str;
185
+ size_t cnt;
186
+
187
+ args[0] = ULONG2NUM(reader->end - reader->tail);
188
+ rstr = rb_funcall2(reader->io, oj_read_id, 1, args);
189
+ if (Qnil == rstr) {
190
+ return Qfalse;
191
+ }
192
+ str = StringValuePtr(rstr);
193
+ cnt = RSTRING_LEN(rstr);
194
+ //printf("*** read %lu bytes, str: '%s'\n", cnt, str);
195
+ strcpy(reader->tail, str);
196
+ reader->read_end = reader->tail + cnt;
197
+
198
+ return Qtrue;
199
+ }
200
+
201
+ static int
202
+ read_from_io_partial(Reader reader) {
203
+ return (Qfalse == rb_rescue(partial_io_cb, (VALUE)reader, rescue_cb, (VALUE)reader));
204
+ }
205
+
206
+ static int
207
+ read_from_io(Reader reader) {
208
+ return (Qfalse == rb_rescue(io_cb, (VALUE)reader, rescue_cb, (VALUE)reader));
209
+ }
210
+
211
+ static int
212
+ read_from_fd(Reader reader) {
213
+ ssize_t cnt;
214
+ size_t max = reader->end - reader->tail;
215
+
216
+ cnt = read(reader->fd, reader->tail, max);
217
+ if (cnt <= 0) {
218
+ return -1;
219
+ } else if (0 != cnt) {
220
+ reader->read_end = reader->tail + cnt;
221
+ }
222
+ return 0;
223
+ }
224
+
225
+ // This is only called when the end of the string is reached so just return -1.
226
+ /*
227
+ static int
228
+ read_from_str(Reader reader) {
229
+ return -1;
230
+ }
231
+ */
@@ -0,0 +1,151 @@
1
+ /* reader.h
2
+ * Copyright (c) 2011, Peter Ohler
3
+ * All rights reserved.
4
+ */
5
+
6
+ #ifndef OJ_READER_H
7
+ #define OJ_READER_H
8
+
9
+ typedef struct _reader {
10
+ char base[0x00001000];
11
+ char *head;
12
+ char *end;
13
+ char *tail;
14
+ char *read_end; /* one past last character read */
15
+ char *pro; /* protection start, buffer can not slide past this point */
16
+ char *str; /* start of current string being read */
17
+ long pos;
18
+ int line;
19
+ int col;
20
+ int free_head;
21
+ int (*read_func)(struct _reader *reader);
22
+ union {
23
+ int fd;
24
+ VALUE io;
25
+ const char *in_str;
26
+ };
27
+ } *Reader;
28
+
29
+ extern void oj_reader_init(Reader reader, VALUE io, int fd, bool to_s);
30
+ extern int oj_reader_read(Reader reader);
31
+
32
+ static inline char
33
+ reader_get(Reader reader) {
34
+ //printf("*** drive get from '%s' from start: %ld buf: %p from read_end: %ld\n", reader->tail, reader->tail - reader->head, reader->head, reader->read_end - reader->tail);
35
+ if (reader->read_end <= reader->tail) {
36
+ if (0 != oj_reader_read(reader)) {
37
+ return '\0';
38
+ }
39
+ }
40
+ if ('\n' == *reader->tail) {
41
+ reader->line++;
42
+ reader->col = 0;
43
+ }
44
+ reader->col++;
45
+ reader->pos++;
46
+
47
+ return *reader->tail++;
48
+ }
49
+
50
+ static inline void
51
+ reader_backup(Reader reader) {
52
+ reader->tail--;
53
+ reader->col--;
54
+ reader->pos--;
55
+ if (0 >= reader->col) {
56
+ reader->line--;
57
+ // allow col to be negative since we never backup twice in a row
58
+ }
59
+ }
60
+
61
+ static inline void
62
+ reader_protect(Reader reader) {
63
+ reader->pro = reader->tail;
64
+ reader->str = reader->tail; // can't have str before pro
65
+ }
66
+
67
+ static inline void
68
+ reader_release(Reader reader) {
69
+ reader->pro = 0;
70
+ }
71
+
72
+ /* Starts by reading a character so it is safe to use with an empty or
73
+ * compacted buffer.
74
+ */
75
+ static inline char
76
+ reader_next_non_white(Reader reader) {
77
+ char c;
78
+
79
+ while ('\0' != (c = reader_get(reader))) {
80
+ switch(c) {
81
+ case ' ':
82
+ case '\t':
83
+ case '\f':
84
+ case '\n':
85
+ case '\r':
86
+ break;
87
+ default:
88
+ return c;
89
+ }
90
+ }
91
+ return '\0';
92
+ }
93
+
94
+ /* Starts by reading a character so it is safe to use with an empty or
95
+ * compacted buffer.
96
+ */
97
+ static inline char
98
+ reader_next_white(Reader reader) {
99
+ char c;
100
+
101
+ while ('\0' != (c = reader_get(reader))) {
102
+ switch(c) {
103
+ case ' ':
104
+ case '\t':
105
+ case '\f':
106
+ case '\n':
107
+ case '\r':
108
+ case '\0':
109
+ return c;
110
+ default:
111
+ break;
112
+ }
113
+ }
114
+ return '\0';
115
+ }
116
+
117
+ static inline int
118
+ reader_expect(Reader reader, const char *s) {
119
+ for (; '\0' != *s; s++) {
120
+ if (reader_get(reader) != *s) {
121
+ return -1;
122
+ }
123
+ }
124
+ return 0;
125
+ }
126
+
127
+ static inline void
128
+ reader_cleanup(Reader reader) {
129
+ if (reader->free_head && 0 != reader->head) {
130
+ xfree((char*)reader->head);
131
+ reader->head = 0;
132
+ reader->free_head = 0;
133
+ }
134
+ }
135
+
136
+ static inline int
137
+ is_white(char c) {
138
+ switch(c) {
139
+ case ' ':
140
+ case '\t':
141
+ case '\f':
142
+ case '\n':
143
+ case '\r':
144
+ return 1;
145
+ default:
146
+ break;
147
+ }
148
+ return 0;
149
+ }
150
+
151
+ #endif /* OJ_READER_H */
@@ -0,0 +1,102 @@
1
+ /* resolve.c
2
+ * Copyright (c) 2012, Peter Ohler
3
+ * All rights reserved.
4
+ */
5
+
6
+ #include <stdlib.h>
7
+ #include <stdio.h>
8
+ #include <string.h>
9
+ #if HAVE_LIBPTHREAD
10
+ #include <pthread.h>
11
+ #endif
12
+
13
+ #include "oj.h"
14
+ #include "err.h"
15
+ #include "parse.h"
16
+ #include "hash.h"
17
+
18
+ inline static VALUE
19
+ resolve_classname(VALUE mod, const char *classname, int auto_define) {
20
+ VALUE clas;
21
+ ID ci = rb_intern(classname);
22
+
23
+ if (rb_const_defined_at(mod, ci)) {
24
+ clas = rb_const_get_at(mod, ci);
25
+ } else if (auto_define) {
26
+ clas = rb_define_class_under(mod, classname, oj_bag_class);
27
+ } else {
28
+ clas = Qundef;
29
+ }
30
+ return clas;
31
+ }
32
+
33
+ static VALUE
34
+ resolve_classpath(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class) {
35
+ char class_name[1024];
36
+ VALUE clas;
37
+ char *end = class_name + sizeof(class_name) - 1;
38
+ char *s;
39
+ const char *n = name;
40
+
41
+ clas = rb_cObject;
42
+ for (s = class_name; 0 < len; n++, len--) {
43
+ if (':' == *n) {
44
+ *s = '\0';
45
+ n++;
46
+ len--;
47
+ if (':' != *n) {
48
+ return Qundef;
49
+ }
50
+ if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
51
+ return Qundef;
52
+ }
53
+ s = class_name;
54
+ } else if (end <= s) {
55
+ return Qundef;
56
+ } else {
57
+ *s++ = *n;
58
+ }
59
+ }
60
+ *s = '\0';
61
+ if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
62
+ oj_set_error_at(pi, error_class, __FILE__, __LINE__, "class %s is not defined", name);
63
+ if (Qnil != error_class) {
64
+ pi->err_class = error_class;
65
+ }
66
+ }
67
+ return clas;
68
+ }
69
+
70
+ VALUE
71
+ oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class) {
72
+ VALUE clas;
73
+ VALUE *slot;
74
+
75
+ if (No == pi->options.class_cache) {
76
+ return resolve_classpath(pi, name, len, auto_define, error_class);
77
+ }
78
+ #if HAVE_LIBPTHREAD
79
+ pthread_mutex_lock(&oj_cache_mutex);
80
+ #else
81
+ rb_mutex_lock(oj_cache_mutex);
82
+ #endif
83
+ if (Qnil == (clas = oj_class_hash_get(name, len, &slot))) {
84
+ if (Qundef != (clas = resolve_classpath(pi, name, len, auto_define, error_class))) {
85
+ *slot = clas;
86
+ }
87
+ }
88
+ #if HAVE_LIBPTHREAD
89
+ pthread_mutex_unlock(&oj_cache_mutex);
90
+ #else
91
+ rb_mutex_unlock(oj_cache_mutex);
92
+ #endif
93
+ return clas;
94
+ }
95
+
96
+ VALUE
97
+ oj_name2struct(ParseInfo pi, VALUE nameVal, VALUE error_class) {
98
+ size_t len = RSTRING_LEN(nameVal);
99
+ const char *str = StringValuePtr(nameVal);
100
+
101
+ return resolve_classpath(pi, str, len, 0, error_class);
102
+ }