oj 2.2.1 → 2.2.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of oj might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +6 -0
- data/ext/oj/extconf.rb +2 -1
- data/ext/oj/object.c +6 -2
- data/ext/oj/oj.c +8 -3
- data/ext/oj/oj.h +6 -2
- data/ext/oj/parse.c +9 -7
- data/ext/oj/resolve.c +7 -3
- data/ext/oj/scp.c +5 -3
- data/ext/oj/val_stack.c +15 -0
- data/ext/oj/val_stack.h +14 -0
- data/lib/oj/version.rb +1 -1
- data/test/lots.rb +6 -3
- data/test/test_scp.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01dd99731dba1d9feeffe3135e41b282718c6342
|
4
|
+
data.tar.gz: 0c635bcad7be8c0a8b86a074dc2cc42946a4938a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cabf96957642d870530a33ed6b4236505d6e67e06d6cddbb7f2b29e2dcc567a12b844a5fe7abe317bb0f3a65cccadf81240c8af23aa4ff7c45363c744bfc045
|
7
|
+
data.tar.gz: 2e2b979fbe2a517b04bca9eb3144b9c3edfeccfd33a3849b4d175a882036b3dff2631de3c888fa608fdbc13a1f3e3b97cbd71fef3f5b87d3ac27074d70606109
|
data/README.md
CHANGED
@@ -20,6 +20,12 @@ Follow [@peterohler on Twitter](http://twitter.com/#!/peterohler) for announceme
|
|
20
20
|
|
21
21
|
[![Build Status](https://secure.travis-ci.org/ohler55/oj.png?branch=master)](http://travis-ci.org/ohler55/oj)
|
22
22
|
|
23
|
+
### Current Release 2.2.2
|
24
|
+
|
25
|
+
- Added mutex support for Windows.
|
26
|
+
|
27
|
+
- Protected SCP parser for GC.
|
28
|
+
|
23
29
|
### Current Release 2.2.1
|
24
30
|
|
25
31
|
- Made all VALUEs in parse volatile to avoid garbage collection while in use.
|
data/ext/oj/extconf.rb
CHANGED
@@ -31,7 +31,8 @@ dflags = {
|
|
31
31
|
'HAS_TOP_LEVEL_ST_H' => ('ree' == type || ('ruby' == type && '1' == version[0] && '8' == version[1])) ? 1 : 0,
|
32
32
|
'NEEDS_RATIONAL' => ('1' == version[0] && '8' == version[1]) ? 1 : 0,
|
33
33
|
'IS_WINDOWS' => is_windows ? 1 : 0,
|
34
|
-
'
|
34
|
+
'USE_PTHREAD_MUTEX' => is_windows ? 0 : 1,
|
35
|
+
'USE_RB_MUTEX' => (is_windows && !('1' == version[0] && '8' == version[1])) ? 1 : 0,
|
35
36
|
}
|
36
37
|
# This is a monster hack to get around issues with 1.9.3-p0 on CentOS 5.4. SO
|
37
38
|
# some reason math.h and string.h contents are not processed. Might be a
|
data/ext/oj/object.c
CHANGED
@@ -263,8 +263,10 @@ set_obj_ivar(Val parent, const char *key, size_t klen, VALUE value) {
|
|
263
263
|
rb_funcall(parent->val, rb_intern("set_backtrace"), 1, value);
|
264
264
|
}
|
265
265
|
}
|
266
|
-
#if
|
266
|
+
#if USE_PTHREAD_MUTEX
|
267
267
|
pthread_mutex_lock(&oj_cache_mutex);
|
268
|
+
#elif USE_RB_MUTEX
|
269
|
+
rb_mutex_lock(oj_cache_mutex);
|
268
270
|
#endif
|
269
271
|
if (0 == (var_id = oj_attr_hash_get(key, klen, &slot))) {
|
270
272
|
char attr[256];
|
@@ -295,8 +297,10 @@ set_obj_ivar(Val parent, const char *key, size_t klen, VALUE value) {
|
|
295
297
|
}
|
296
298
|
*slot = var_id;
|
297
299
|
}
|
298
|
-
#if
|
300
|
+
#if USE_PTHREAD_MUTEX
|
299
301
|
pthread_mutex_unlock(&oj_cache_mutex);
|
302
|
+
#elif USE_RB_MUTEX
|
303
|
+
rb_mutex_unlock(oj_cache_mutex);
|
300
304
|
#endif
|
301
305
|
rb_ivar_set(parent->val, var_id, value);
|
302
306
|
}
|
data/ext/oj/oj.c
CHANGED
@@ -129,8 +129,10 @@ rb_encoding *oj_utf8_encoding = 0;
|
|
129
129
|
VALUE oj_utf8_encoding = Qnil;
|
130
130
|
#endif
|
131
131
|
|
132
|
-
#if
|
133
|
-
pthread_mutex_t oj_cache_mutex;
|
132
|
+
#if USE_PTHREAD_MUTEX
|
133
|
+
pthread_mutex_t oj_cache_mutex;
|
134
|
+
#elif USE_RB_MUTEX
|
135
|
+
VALUE oj_cache_mutex = Qnil;
|
134
136
|
#endif
|
135
137
|
static const char json_class[] = "json_class";
|
136
138
|
|
@@ -1269,8 +1271,11 @@ void Init_oj() {
|
|
1269
1271
|
oj_hash_init();
|
1270
1272
|
oj_odd_init();
|
1271
1273
|
|
1272
|
-
#if
|
1274
|
+
#if USE_PTHREAD_MUTEX
|
1273
1275
|
pthread_mutex_init(&oj_cache_mutex, 0);
|
1276
|
+
#elif USE_RB_MUTEX
|
1277
|
+
oj_cache_mutex = rb_mutex_new();
|
1278
|
+
rb_gc_register_address(&oj_cache_mutex);
|
1274
1279
|
#endif
|
1275
1280
|
oj_init_doc();
|
1276
1281
|
}
|
data/ext/oj/oj.h
CHANGED
@@ -46,7 +46,8 @@ extern "C" {
|
|
46
46
|
#endif
|
47
47
|
|
48
48
|
#include "stdint.h"
|
49
|
-
|
49
|
+
|
50
|
+
#if USE_PTHREAD_MUTEX
|
50
51
|
#include <pthread.h>
|
51
52
|
#endif
|
52
53
|
#include "cache8.h"
|
@@ -224,9 +225,12 @@ extern ID oj_tv_usec_id;
|
|
224
225
|
extern ID oj_utc_offset_id;
|
225
226
|
extern ID oj_write_id;
|
226
227
|
|
227
|
-
#if
|
228
|
+
#if USE_PTHREAD_MUTEX
|
228
229
|
extern pthread_mutex_t oj_cache_mutex;
|
230
|
+
#elif USE_RB_MUTEX
|
231
|
+
extern VALUE oj_cache_mutex;
|
229
232
|
#endif
|
233
|
+
|
230
234
|
#if defined(__cplusplus)
|
231
235
|
#if 0
|
232
236
|
{ /* satisfy cc-mode */
|
data/ext/oj/parse.c
CHANGED
@@ -569,11 +569,8 @@ colon(ParseInfo pi) {
|
|
569
569
|
|
570
570
|
void
|
571
571
|
oj_parse2(ParseInfo pi) {
|
572
|
-
volatile VALUE rstack = Qnil;
|
573
|
-
|
574
572
|
pi->cur = pi->json;
|
575
573
|
err_init(&pi->err);
|
576
|
-
rstack = oj_stack_init(&pi->stack);
|
577
574
|
while (1) {
|
578
575
|
next_non_white(pi);
|
579
576
|
switch (*pi->cur++) {
|
@@ -647,7 +644,7 @@ oj_parse2(ParseInfo pi) {
|
|
647
644
|
|
648
645
|
VALUE
|
649
646
|
oj_num_as_value(NumInfo ni) {
|
650
|
-
|
647
|
+
VALUE rnum = Qnil;
|
651
648
|
|
652
649
|
if (ni->infinity) {
|
653
650
|
if (ni->neg) {
|
@@ -721,7 +718,8 @@ VALUE
|
|
721
718
|
oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json) {
|
722
719
|
char *buf = 0;
|
723
720
|
volatile VALUE input;
|
724
|
-
volatile VALUE
|
721
|
+
volatile VALUE wrapped_stack;
|
722
|
+
VALUE result = Qnil;
|
725
723
|
int line = 0;
|
726
724
|
int free_json = 0;
|
727
725
|
|
@@ -782,10 +780,14 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json) {
|
|
782
780
|
pi->circ_array = 0;
|
783
781
|
}
|
784
782
|
// GC can run at any time. When it runs any Object created by C will be
|
785
|
-
// freed.
|
786
|
-
//
|
783
|
+
// freed. We protect against this by wrapping the value stack in a ruby
|
784
|
+
// data object and poviding a mark function for ruby objects on the
|
785
|
+
// value stack (while it is in scope).
|
786
|
+
wrapped_stack = oj_stack_init(&pi->stack);
|
787
787
|
rb_protect(protect_parse, (VALUE)pi, &line);
|
788
788
|
result = stack_head_val(&pi->stack);
|
789
|
+
DATA_PTR(wrapped_stack) = 0;
|
790
|
+
|
789
791
|
// proceed with cleanup
|
790
792
|
if (0 != pi->circ_array) {
|
791
793
|
oj_circ_array_free(pi->circ_array);
|
data/ext/oj/resolve.c
CHANGED
@@ -31,7 +31,7 @@
|
|
31
31
|
#include <stdlib.h>
|
32
32
|
#include <stdio.h>
|
33
33
|
#include <string.h>
|
34
|
-
#if
|
34
|
+
#if USE_PTHREAD_MUTEX
|
35
35
|
#include <pthread.h>
|
36
36
|
#endif
|
37
37
|
|
@@ -102,16 +102,20 @@ oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define) {
|
|
102
102
|
if (No == pi->options.class_cache) {
|
103
103
|
return resolve_classpath(pi, name, len, auto_define);
|
104
104
|
}
|
105
|
-
#if
|
105
|
+
#if USE_PTHREAD_MUTEX
|
106
106
|
pthread_mutex_lock(&oj_cache_mutex);
|
107
|
+
#elif USE_RB_MUTEX
|
108
|
+
rb_mutex_lock(oj_cache_mutex);
|
107
109
|
#endif
|
108
110
|
if (Qnil == (clas = oj_class_hash_get(name, len, &slot))) {
|
109
111
|
if (Qundef != (clas = resolve_classpath(pi, name, len, auto_define))) {
|
110
112
|
*slot = clas;
|
111
113
|
}
|
112
114
|
}
|
113
|
-
#if
|
115
|
+
#if USE_PTHREAD_MUTEX
|
114
116
|
pthread_mutex_unlock(&oj_cache_mutex);
|
117
|
+
#elif USE_RB_MUTEX
|
118
|
+
rb_mutex_unlock(oj_cache_mutex);
|
115
119
|
#endif
|
116
120
|
return clas;
|
117
121
|
}
|
data/ext/oj/scp.c
CHANGED
@@ -198,6 +198,7 @@ oj_sc_parse(int argc, VALUE *argv, VALUE self) {
|
|
198
198
|
char *buf = 0;
|
199
199
|
VALUE input;
|
200
200
|
VALUE handler;
|
201
|
+
volatile VALUE wrapped_stack;
|
201
202
|
int line = 0;
|
202
203
|
|
203
204
|
if (argc < 2) {
|
@@ -252,8 +253,8 @@ oj_sc_parse(int argc, VALUE *argv, VALUE self) {
|
|
252
253
|
if (rb_type(input) == T_STRING) {
|
253
254
|
pi.json = StringValuePtr(input);
|
254
255
|
} else {
|
255
|
-
VALUE
|
256
|
-
VALUE s;
|
256
|
+
VALUE clas = rb_obj_class(input);
|
257
|
+
volatile VALUE s;
|
257
258
|
|
258
259
|
if (oj_stringio_class == clas) {
|
259
260
|
s = rb_funcall2(input, oj_string_id, 0, 0);
|
@@ -285,8 +286,9 @@ oj_sc_parse(int argc, VALUE *argv, VALUE self) {
|
|
285
286
|
rb_raise(rb_eArgError, "saj_parse() expected a String or IO Object.");
|
286
287
|
}
|
287
288
|
}
|
289
|
+
wrapped_stack = oj_stack_init(&pi.stack);
|
288
290
|
rb_protect(protect_parse, (VALUE)&pi, &line);
|
289
|
-
|
291
|
+
DATA_PTR(wrapped_stack) = NULL;
|
290
292
|
if (0 != buf) {
|
291
293
|
xfree(buf);
|
292
294
|
}
|
data/ext/oj/val_stack.c
CHANGED
@@ -36,18 +36,33 @@ mark(void *ptr) {
|
|
36
36
|
ValStack stack = (ValStack)ptr;
|
37
37
|
Val v;
|
38
38
|
|
39
|
+
if (ptr == NULL) return;
|
40
|
+
|
41
|
+
#if USE_PTHREAD_MUTEX
|
39
42
|
pthread_mutex_lock(&stack->mutex);
|
43
|
+
#elif USE_RB_MUTEX
|
44
|
+
rb_mutex_lock(stack->mutex);
|
45
|
+
rb_gc_mark(stack->mutex);
|
46
|
+
#endif
|
40
47
|
for (v = stack->head; v < stack->tail; v++) {
|
41
48
|
if (Qnil != v->val && Qundef != v->val) {
|
42
49
|
rb_gc_mark(v->val);
|
43
50
|
}
|
44
51
|
}
|
52
|
+
#if USE_PTHREAD_MUTEX
|
45
53
|
pthread_mutex_unlock(&stack->mutex);
|
54
|
+
#elif USE_RB_MUTEX
|
55
|
+
rb_mutex_unlock(stack->mutex);
|
56
|
+
#endif
|
46
57
|
}
|
47
58
|
|
48
59
|
VALUE
|
49
60
|
oj_stack_init(ValStack stack) {
|
61
|
+
#if USE_PTHREAD_MUTEX
|
50
62
|
pthread_mutex_init(&stack->mutex, 0);
|
63
|
+
#elif USE_RB_MUTEX
|
64
|
+
stack->mutex = rb_mutex_new();
|
65
|
+
#endif
|
51
66
|
stack->head = stack->base;
|
52
67
|
stack->end = stack->base + sizeof(stack->base) / sizeof(struct _Val);
|
53
68
|
stack->tail = stack->head;
|
data/ext/oj/val_stack.h
CHANGED
@@ -68,7 +68,13 @@ typedef struct _ValStack {
|
|
68
68
|
Val head; // current stack
|
69
69
|
Val end; // stack end
|
70
70
|
Val tail; // pointer to one past last element name on stack
|
71
|
+
|
72
|
+
#if USE_PTHREAD_MUTEX
|
71
73
|
pthread_mutex_t mutex;
|
74
|
+
#elif USE_RB_MUTEX
|
75
|
+
VALUE mutex;
|
76
|
+
#endif
|
77
|
+
|
72
78
|
} *ValStack;
|
73
79
|
|
74
80
|
extern VALUE oj_stack_init(ValStack stack);
|
@@ -100,11 +106,19 @@ stack_push(ValStack stack, VALUE val, ValNext next) {
|
|
100
106
|
} else {
|
101
107
|
REALLOC_N(head, struct _Val, len + STACK_INC);
|
102
108
|
}
|
109
|
+
#if USE_PTHREAD_MUTEX
|
103
110
|
pthread_mutex_lock(&stack->mutex);
|
111
|
+
#elif USE_RB_MUTEX
|
112
|
+
rb_mutex_lock(stack->mutex);
|
113
|
+
#endif
|
104
114
|
stack->head = head;
|
105
115
|
stack->tail = stack->head + toff;
|
106
116
|
stack->end = stack->head + len + STACK_INC;
|
117
|
+
#if USE_PTHREAD_MUTEX
|
107
118
|
pthread_mutex_unlock(&stack->mutex);
|
119
|
+
#elif USE_RB_MUTEX
|
120
|
+
rb_mutex_unlock(stack->mutex);
|
121
|
+
#endif
|
108
122
|
}
|
109
123
|
stack->tail->val = val;
|
110
124
|
stack->tail->next = next;
|
data/lib/oj/version.rb
CHANGED
data/test/lots.rb
CHANGED
@@ -53,13 +53,16 @@ $obj = {
|
|
53
53
|
'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
|
54
54
|
}
|
55
55
|
|
56
|
+
$obj = [$obj]*10000
|
57
|
+
|
56
58
|
Oj.default_options = { :indent => 2, :mode => :compat }
|
57
59
|
|
58
60
|
$json = Oj.dump($obj, :mode => :compat)
|
59
61
|
|
60
|
-
|
61
|
-
|
62
|
-
|
62
|
+
$result = nil
|
63
|
+
100.times { |i|
|
64
|
+
print(".") if (0 == i % 10)
|
65
|
+
$result = Oj.compat_load($json)
|
63
66
|
}
|
64
67
|
|
65
68
|
|
data/test/test_scp.rb
CHANGED
@@ -217,7 +217,7 @@ class ScpTest < ::Test::Unit::TestCase
|
|
217
217
|
begin
|
218
218
|
Oj.sc_parse(handler, json)
|
219
219
|
rescue Exception => e
|
220
|
-
assert_equal("unexpected character at line 1, column 6 [parse.c:
|
220
|
+
assert_equal("unexpected character at line 1, column 6 [parse.c:636]", e.message)
|
221
221
|
end
|
222
222
|
end
|
223
223
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: 'The fastest JSON parser and object serializer. '
|
14
14
|
email: peter@ohler.com
|