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 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.4
27
+ ### Release 1.0.5
28
28
 
29
- - Fixed bug that did not allow symbols as keys in :compat mode.
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
 
@@ -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
- uuuuuuuuxxxuxxuuuuuuuuuuuuuuuuuu\
105
- ooxooooooooooooxoooooooooooooooo\
106
- ooooooooooooooooooooooooooooxooo\
107
- ooooooooooooooooooooooooooooooou\
108
- uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu\
109
- uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu\
110
- uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu\
111
- uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu";
112
-
113
- inline static int
114
- is_json_friendly(const u_char *str, size_t len) {
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
- if ('o' != json_friendly_chars[*str]) {
117
- return 0;
118
- }
128
+ size += json_friendly_chars[*str];
119
129
  }
120
- return 1;
130
+ return size - len * (size_t)'0';
121
131
  }
122
132
 
123
133
  inline static size_t
124
- json_friendly_size(const u_char *str, size_t len) {
125
- int cnt = 0;
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
- switch (json_friendly_chars[*str]) {
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 cnt;
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 = json_friendly_size((u_char*)str, cnt);
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 (json_friendly_chars[(u_char)*str]) {
375
- case 'o':
387
+ switch (cmap[(u_char)*str]) {
388
+ case '1':
376
389
  *out->cur++ = *str;
377
390
  break;
378
- case 'x':
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 'u':
402
+ case '6':
390
403
  *out->cur++ = '\\';
391
404
  *out->cur++ = 'u';
392
405
  if ((u_char)*str <= 0x7F) {
@@ -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, mode_sym)) {
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
- if (Qnil == v) {
190
- *o->attr = NotSet;
191
- } else if (Qtrue == v) {
192
- *o->attr = Yes;
193
- } else if (Qfalse == v) {
194
- *o->attr = No;
195
- } else {
196
- rb_raise(rb_eArgError, "%s must be true, false, or nil.\n", StringValuePtr(o->sym));
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", StringValuePtr(o->sym));
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);
@@ -85,6 +85,7 @@ typedef struct _Options {
85
85
  char circular; // YesNo
86
86
  char auto_define; // YesNo
87
87
  char sym_key; // YesNo
88
+ char ascii_only; // YesNo
88
89
  char mode; // Mode
89
90
  } *Options;
90
91
 
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '1.0.4'
4
+ VERSION = '1.0.5'
5
5
  end
@@ -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=>false,
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 = { :encoding => nil }
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
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-16 00:00:00.000000000 Z
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