oj 1.0.4 → 1.0.5
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.
- data/README.md +2 -2
- data/ext/oj/dump.c +45 -32
- data/ext/oj/oj.c +18 -13
- data/ext/oj/oj.h +1 -0
- data/lib/oj/version.rb +1 -1
- data/test/tests.rb +7 -2
- metadata +2 -2
data/README.md
CHANGED
@@ -24,9 +24,9 @@ A fast JSON parser and Object marshaller as a Ruby gem.
|
|
24
24
|
|
25
25
|
## <a name="release">Release Notes</a>
|
26
26
|
|
27
|
-
### Release 1.0.
|
27
|
+
### Release 1.0.5
|
28
28
|
|
29
|
-
-
|
29
|
+
- Added :ascii_only options for dumping JSON where all high-bit characters are encoded as escaped sequences.
|
30
30
|
|
31
31
|
## <a name="description">Description</a>
|
32
32
|
|
data/ext/oj/dump.c
CHANGED
@@ -94,45 +94,50 @@ static int dump_attr_cb(ID key, VALUE value, Out out);
|
|
94
94
|
static void dump_obj_attrs(VALUE obj, int with_class, slot_t id, int depth, Out out);
|
95
95
|
|
96
96
|
static void grow(Out out, size_t len);
|
97
|
-
static int is_json_friendly(const u_char *str, size_t len);
|
98
97
|
static size_t json_friendly_size(const u_char *str, size_t len);
|
98
|
+
static size_t ascii_friendly_size(const u_char *str, size_t len);
|
99
99
|
|
100
100
|
|
101
101
|
static const char hex_chars[17] = "0123456789abcdef";
|
102
102
|
|
103
103
|
static char json_friendly_chars[256] = "\
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
104
|
+
66666666222622666666666666666666\
|
105
|
+
11211111111111121111111111111111\
|
106
|
+
11111111111111111111111111112111\
|
107
|
+
11111111111111111111111111111111\
|
108
|
+
11111111111111111111111111111111\
|
109
|
+
11111111111111111111111111111111\
|
110
|
+
11111111111111111111111111111111\
|
111
|
+
11111111111111111111111111111111";
|
112
|
+
|
113
|
+
static char ascii_friendly_chars[256] = "\
|
114
|
+
66666666222622666666666666666666\
|
115
|
+
11211111111111121111111111111111\
|
116
|
+
11111111111111111111111111112111\
|
117
|
+
11111111111111111111111111111116\
|
118
|
+
66666666666666666666666666666666\
|
119
|
+
66666666666666666666666666666666\
|
120
|
+
66666666666666666666666666666666\
|
121
|
+
66666666666666666666666666666666";
|
122
|
+
|
123
|
+
inline static size_t
|
124
|
+
json_friendly_size(const u_char *str, size_t len) {
|
125
|
+
size_t size = 0;
|
126
|
+
|
115
127
|
for (; 0 < len; str++, len--) {
|
116
|
-
|
117
|
-
return 0;
|
118
|
-
}
|
128
|
+
size += json_friendly_chars[*str];
|
119
129
|
}
|
120
|
-
return
|
130
|
+
return size - len * (size_t)'0';
|
121
131
|
}
|
122
132
|
|
123
133
|
inline static size_t
|
124
|
-
|
125
|
-
|
126
|
-
|
134
|
+
ascii_friendly_size(const u_char *str, size_t len) {
|
135
|
+
size_t size = 0;
|
136
|
+
|
127
137
|
for (; 0 < len; str++, len--) {
|
128
|
-
|
129
|
-
case 'o': cnt++; break;
|
130
|
-
case 'x': cnt += 2; break;
|
131
|
-
case 'u': cnt += 6; break;
|
132
|
-
default: break;
|
133
|
-
}
|
138
|
+
size += ascii_friendly_chars[*str];
|
134
139
|
}
|
135
|
-
return
|
140
|
+
return size - len * (size_t)'0';
|
136
141
|
}
|
137
142
|
|
138
143
|
inline static void
|
@@ -341,8 +346,16 @@ dump_float(VALUE obj, Out out) {
|
|
341
346
|
|
342
347
|
static void
|
343
348
|
dump_cstr(const char *str, size_t cnt, int is_sym, int escape1, Out out) {
|
344
|
-
size_t size
|
345
|
-
|
349
|
+
size_t size;
|
350
|
+
char *cmap;
|
351
|
+
|
352
|
+
if (Yes == out->opts->ascii_only) {
|
353
|
+
cmap = ascii_friendly_chars;
|
354
|
+
size = ascii_friendly_size((u_char*)str, cnt);
|
355
|
+
} else {
|
356
|
+
cmap = json_friendly_chars;
|
357
|
+
size = json_friendly_size((u_char*)str, cnt);
|
358
|
+
}
|
346
359
|
if (out->end - out->cur <= (long)size + 10) { // extra 10 for escaped first char, quotes, and sym
|
347
360
|
grow(out, size + 10);
|
348
361
|
}
|
@@ -371,11 +384,11 @@ dump_cstr(const char *str, size_t cnt, int is_sym, int escape1, Out out) {
|
|
371
384
|
*out->cur++ = ':';
|
372
385
|
}
|
373
386
|
for (; 0 < cnt; cnt--, str++) {
|
374
|
-
switch (
|
375
|
-
case '
|
387
|
+
switch (cmap[(u_char)*str]) {
|
388
|
+
case '1':
|
376
389
|
*out->cur++ = *str;
|
377
390
|
break;
|
378
|
-
case '
|
391
|
+
case '2':
|
379
392
|
*out->cur++ = '\\';
|
380
393
|
switch (*str) {
|
381
394
|
case '\b': *out->cur++ = 'b'; break;
|
@@ -386,7 +399,7 @@ dump_cstr(const char *str, size_t cnt, int is_sym, int escape1, Out out) {
|
|
386
399
|
default: *out->cur++ = *str; break;
|
387
400
|
}
|
388
401
|
break;
|
389
|
-
case '
|
402
|
+
case '6':
|
390
403
|
*out->cur++ = '\\';
|
391
404
|
*out->cur++ = 'u';
|
392
405
|
if ((u_char)*str <= 0x7F) {
|
data/ext/oj/oj.c
CHANGED
@@ -66,6 +66,7 @@ VALUE oj_time_class;
|
|
66
66
|
|
67
67
|
VALUE oj_slash_string;
|
68
68
|
|
69
|
+
static VALUE ascii_only_sym;
|
69
70
|
static VALUE auto_define_sym;
|
70
71
|
static VALUE circular_sym;
|
71
72
|
static VALUE compat_sym;
|
@@ -86,6 +87,7 @@ struct _Options oj_default_options = {
|
|
86
87
|
No, // circular
|
87
88
|
Yes, // auto_define
|
88
89
|
No, // sym_key
|
90
|
+
No, // ascii_only
|
89
91
|
ObjectMode, // mode
|
90
92
|
};
|
91
93
|
|
@@ -109,6 +111,7 @@ get_def_opts(VALUE self) {
|
|
109
111
|
rb_hash_aset(opts, indent_sym, INT2FIX(oj_default_options.indent));
|
110
112
|
rb_hash_aset(opts, circular_sym, (Yes == oj_default_options.circular) ? Qtrue : ((No == oj_default_options.circular) ? Qfalse : Qnil));
|
111
113
|
rb_hash_aset(opts, auto_define_sym, (Yes == oj_default_options.auto_define) ? Qtrue : ((No == oj_default_options.auto_define) ? Qfalse : Qnil));
|
114
|
+
rb_hash_aset(opts, ascii_only_sym, (Yes == oj_default_options.ascii_only) ? Qtrue : ((No == oj_default_options.ascii_only) ? Qfalse : Qnil));
|
112
115
|
rb_hash_aset(opts, symbol_keys_sym, (Yes == oj_default_options.sym_key) ? Qtrue : ((No == oj_default_options.sym_key) ? Qfalse : Qnil));
|
113
116
|
switch (oj_default_options.mode) {
|
114
117
|
case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
|
@@ -129,6 +132,7 @@ get_def_opts(VALUE self) {
|
|
129
132
|
* @param [true|false|nil] :circular support circular references while dumping
|
130
133
|
* @param [true|false|nil] :auto_define automatically define classes if they do not exist
|
131
134
|
* @param [true|false|nil] :symbol_keys convert hash keys to symbols
|
135
|
+
* @param [true|false|nil] :ascii_only encode all high-bit characters as escaped sequences if true
|
132
136
|
* @param [:object|:strict|:compat|:null] load and dump mode to use for JSON
|
133
137
|
* :strict raises an exception when a non-supported Object is
|
134
138
|
* encountered. :compat attempts to extract variable values from an
|
@@ -144,6 +148,7 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
144
148
|
{ circular_sym, &oj_default_options.circular },
|
145
149
|
{ auto_define_sym, &oj_default_options.auto_define },
|
146
150
|
{ symbol_keys_sym, &oj_default_options.sym_key },
|
151
|
+
{ ascii_only_sym, &oj_default_options.ascii_only },
|
147
152
|
{ Qnil, 0 }
|
148
153
|
};
|
149
154
|
YesNoOpt o;
|
@@ -182,19 +187,18 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
182
187
|
}
|
183
188
|
|
184
189
|
for (o = ynos; 0 != o->attr; o++) {
|
185
|
-
if (Qtrue != rb_funcall(opts, rb_intern("has_key?"), 1,
|
190
|
+
if (Qtrue != rb_funcall(opts, rb_intern("has_key?"), 1, o->sym)) {
|
186
191
|
continue;
|
187
192
|
}
|
188
|
-
v = rb_hash_lookup(opts, o->sym)
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
}
|
193
|
+
if (Qnil != (v = rb_hash_lookup(opts, o->sym))) {
|
194
|
+
if (Qtrue == v) {
|
195
|
+
*o->attr = Yes;
|
196
|
+
} else if (Qfalse == v) {
|
197
|
+
*o->attr = No;
|
198
|
+
} else {
|
199
|
+
rb_raise(rb_eArgError, "%s must be true, false, or nil.\n", rb_id2name(SYM2ID(o->sym)));
|
200
|
+
}
|
201
|
+
}
|
198
202
|
}
|
199
203
|
return Qnil;
|
200
204
|
}
|
@@ -205,6 +209,7 @@ parse_options(VALUE ropts, Options copts) {
|
|
205
209
|
{ circular_sym, &copts->circular },
|
206
210
|
{ auto_define_sym, &copts->auto_define },
|
207
211
|
{ symbol_keys_sym, &copts->sym_key },
|
212
|
+
{ ascii_only_sym, &copts->ascii_only },
|
208
213
|
{ Qnil, 0 }
|
209
214
|
};
|
210
215
|
YesNoOpt o;
|
@@ -239,13 +244,12 @@ parse_options(VALUE ropts, Options copts) {
|
|
239
244
|
}
|
240
245
|
for (o = ynos; 0 != o->attr; o++) {
|
241
246
|
if (Qnil != (v = rb_hash_lookup(ropts, o->sym))) {
|
242
|
-
|
243
247
|
if (Qtrue == v) {
|
244
248
|
*o->attr = Yes;
|
245
249
|
} else if (Qfalse == v) {
|
246
250
|
*o->attr = No;
|
247
251
|
} else {
|
248
|
-
rb_raise(rb_eArgError, "%s must be true or false.\n",
|
252
|
+
rb_raise(rb_eArgError, "%s must be true or false.\n", rb_id2name(SYM2ID(o->sym)));
|
249
253
|
}
|
250
254
|
}
|
251
255
|
}
|
@@ -431,6 +435,7 @@ void Init_oj() {
|
|
431
435
|
oj_date_class = rb_const_get(rb_cObject, rb_intern("Date"));
|
432
436
|
oj_stringio_class = rb_const_get(rb_cObject, rb_intern("StringIO"));
|
433
437
|
|
438
|
+
ascii_only_sym = ID2SYM(rb_intern("ascii_only")); rb_ary_push(keep, ascii_only_sym);
|
434
439
|
auto_define_sym = ID2SYM(rb_intern("auto_define")); rb_ary_push(keep, auto_define_sym);
|
435
440
|
circular_sym = ID2SYM(rb_intern("circular")); rb_ary_push(keep, circular_sym);
|
436
441
|
compat_sym = ID2SYM(rb_intern("compat")); rb_ary_push(keep, compat_sym);
|
data/ext/oj/oj.h
CHANGED
data/lib/oj/version.rb
CHANGED
data/test/tests.rb
CHANGED
@@ -72,6 +72,7 @@ class Juice < ::Test::Unit::TestCase
|
|
72
72
|
:circular=>false,
|
73
73
|
:auto_define=>true,
|
74
74
|
:symbol_keys=>false,
|
75
|
+
:ascii_only=>false,
|
75
76
|
:mode=>:object}, opts)
|
76
77
|
end
|
77
78
|
|
@@ -82,13 +83,15 @@ class Juice < ::Test::Unit::TestCase
|
|
82
83
|
:circular=>false,
|
83
84
|
:auto_define=>true,
|
84
85
|
:symbol_keys=>false,
|
86
|
+
:ascii_only=>false,
|
85
87
|
:mode=>:object}
|
86
88
|
o2 = {
|
87
89
|
:encoding=>"UTF-8",
|
88
90
|
:indent=>4,
|
89
91
|
:circular=>true,
|
90
92
|
:auto_define=>false,
|
91
|
-
:symbol_keys=>
|
93
|
+
:symbol_keys=>true,
|
94
|
+
:ascii_only=>true,
|
92
95
|
:mode=>:compat}
|
93
96
|
o3 = { :indent => 4 }
|
94
97
|
Oj.default_options = o2
|
@@ -143,7 +146,9 @@ class Juice < ::Test::Unit::TestCase
|
|
143
146
|
def test_encode
|
144
147
|
Oj.default_options = { :encoding => 'UTF-8' }
|
145
148
|
dump_and_load("ぴーたー", false)
|
146
|
-
Oj.default_options = { :
|
149
|
+
Oj.default_options = { :ascii_only => true }
|
150
|
+
dump_and_load("ぴーたー", false)
|
151
|
+
Oj.default_options = { :encoding => nil, :ascii_only => false }
|
147
152
|
end
|
148
153
|
|
149
154
|
def test_array
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-03-
|
12
|
+
date: 2012-03-17 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! 'The fastest JSON parser and object serializer. '
|
15
15
|
email: peter@ohler.com
|