oj 1.2.0 → 1.2.1

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,11 +24,11 @@ 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.2.0
27
+ ### Release 1.2.1
28
28
 
29
- - Removed the encoding option and fixed a misunderstanding of the string encoding. Unicode code points are now used instead of byte codes. This is not compatible with previous releases but is compliant with RFC4627.
29
+ - Organized compile configuration better.
30
30
 
31
- - Time encoding in :object mode is faster and higher nanosecond precision.
31
+ - as_json() support now more flexible thanks to a contribution by sauliusg.
32
32
 
33
33
  ## <a name="description">Description</a>
34
34
 
@@ -39,18 +39,11 @@
39
39
  #include "oj.h"
40
40
  #include "cache8.h"
41
41
 
42
- #ifdef RUBY_API_VERSION_MAJOR
43
- #define HAS_TIMESPEC
44
- #endif
45
-
46
- #ifndef HAVE_RUBY_ENCODING_H
47
- #define rb_eEncodingError rb_eException
48
- #endif
49
- #ifdef RUBINIUS
42
+ #if !HAS_ENCODING_SUPPORT
50
43
  #define rb_eEncodingError rb_eException
51
44
  #endif
52
45
 
53
- typedef unsigned long ulong;
46
+ typedef unsigned long ulong;
54
47
 
55
48
  typedef struct _Out {
56
49
  char *buf;
@@ -64,7 +57,7 @@ typedef struct _Out {
64
57
  uint32_t hash_cnt;
65
58
  } *Out;
66
59
 
67
- static void dump_obj_to_json(VALUE obj, Options copts, Out out);
60
+ static void dump_obj_to_json(VALUE obj, Options copts, Out out);
68
61
  static void raise_strict(VALUE obj);
69
62
  static void dump_val(VALUE obj, int depth, Out out);
70
63
  static void dump_nil(Out out);
@@ -91,16 +84,16 @@ static void dump_data_comp(VALUE obj, Out out);
91
84
  static void dump_data_obj(VALUE obj, Out out);
92
85
  static void dump_obj_comp(VALUE obj, int depth, Out out);
93
86
  static void dump_obj_obj(VALUE obj, int depth, Out out);
94
- #ifndef NO_RSTRUCT
87
+ #if HAS_RSTRUCT
95
88
  static void dump_struct_comp(VALUE obj, int depth, Out out);
96
89
  static void dump_struct_obj(VALUE obj, int depth, Out out);
97
90
  #endif
98
- #if IVAR_HELPERS
91
+ #if HAS_IVAR_HELPERS
99
92
  static int dump_attr_cb(ID key, VALUE value, Out out);
100
93
  #endif
101
94
  static void dump_obj_attrs(VALUE obj, int with_class, slot_t id, int depth, Out out);
102
95
 
103
- static void grow(Out out, size_t len);
96
+ static void grow(Out out, size_t len);
104
97
  static size_t hibit_friendly_size(const u_char *str, size_t len);
105
98
  static size_t ascii_friendly_size(const u_char *str, size_t len);
106
99
 
@@ -115,7 +108,7 @@ static void dump_leaf_hash(Leaf leaf, int depth, Out out);
115
108
 
116
109
  static const char hex_chars[17] = "0123456789abcdef";
117
110
 
118
- static char hibit_friendly_chars[256] = "\
111
+ static char hibit_friendly_chars[256] = "\
119
112
  66666666222622666666666666666666\
120
113
  11211111111111121111111111111111\
121
114
  11111111111111111111111111112111\
@@ -127,7 +120,7 @@ static char hibit_friendly_chars[256] = "\
127
120
 
128
121
  // High bit set characters are always encoded as unicode. Worse case is 3
129
122
  // bytes per character in the output. That makes this conservative.
130
- static char ascii_friendly_chars[256] = "\
123
+ static char ascii_friendly_chars[256] = "\
131
124
  66666666222622666666666666666666\
132
125
  11211111111111121111111111111111\
133
126
  11111111111111111111111111112111\
@@ -161,20 +154,20 @@ inline static void
161
154
  fill_indent(Out out, int cnt) {
162
155
  if (0 < cnt && 0 < out->indent) {
163
156
  cnt *= out->indent;
164
- *out->cur++ = '\n';
165
- for (; 0 < cnt; cnt--) {
166
- *out->cur++ = ' ';
167
- }
157
+ *out->cur++ = '\n';
158
+ for (; 0 < cnt; cnt--) {
159
+ *out->cur++ = ' ';
160
+ }
168
161
  }
169
162
  }
170
163
 
171
164
  inline static const char*
172
165
  ulong2str(uint32_t num, char *end) {
173
- char *b;
166
+ char *b;
174
167
 
175
168
  *end-- = '\0';
176
169
  for (b = end; 0 < num || b == end; num /= 10, b--) {
177
- *b = (num % 10) + '0';
170
+ *b = (num % 10) + '0';
178
171
  }
179
172
  b++;
180
173
 
@@ -183,20 +176,20 @@ ulong2str(uint32_t num, char *end) {
183
176
 
184
177
  inline static void
185
178
  dump_ulong(unsigned long num, Out out) {
186
- char buf[32];
187
- char *b = buf + sizeof(buf) - 1;
179
+ char buf[32];
180
+ char *b = buf + sizeof(buf) - 1;
188
181
 
189
182
  *b-- = '\0';
190
183
  if (0 < num) {
191
- for (; 0 < num; num /= 10, b--) {
192
- *b = (num % 10) + '0';
193
- }
184
+ for (; 0 < num; num /= 10, b--) {
185
+ *b = (num % 10) + '0';
186
+ }
194
187
  b++;
195
188
  } else {
196
- *b = '0';
189
+ *b = '0';
197
190
  }
198
191
  for (; '\0' != *b; b++) {
199
- *out->cur++ = *b;
192
+ *out->cur++ = *b;
200
193
  }
201
194
  *out->cur = '\0';
202
195
  }
@@ -206,14 +199,14 @@ grow(Out out, size_t len) {
206
199
  size_t size = out->end - out->buf;
207
200
  long pos = out->cur - out->buf;
208
201
  char *buf;
209
-
202
+
210
203
  size *= 2;
211
204
  if (size <= len * 2 + pos) {
212
- size += len;
205
+ size += len;
213
206
  }
214
207
  buf = REALLOC_N(out->buf, char, (size + 10));
215
208
  if (0 == buf) { // 1 extra for terminator character plus extra (paranoid)
216
- rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
209
+ rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
217
210
  }
218
211
  out->buf = buf;
219
212
  out->end = buf + size;
@@ -251,7 +244,7 @@ dump_unicode(const char *str, const char *end, Out out) {
251
244
  cnt = 5;
252
245
  code = b & 0x00000001;
253
246
  } else {
254
- rb_raise(rb_eEncodingError, "Invalid Unicode\n");
247
+ rb_raise(rb_eEncodingError, "Invalid Unicode\n");
255
248
  }
256
249
  str++;
257
250
  for (; 0 < cnt; cnt--, str++) {
@@ -311,10 +304,10 @@ check_circular(VALUE obj, Out out) {
311
304
 
312
305
  static void
313
306
  dump_nil(Out out) {
314
- size_t size = 4;
307
+ size_t size = 4;
315
308
 
316
309
  if (out->end - out->cur <= (long)size) {
317
- grow(out, size);
310
+ grow(out, size);
318
311
  }
319
312
  *out->cur++ = 'n';
320
313
  *out->cur++ = 'u';
@@ -325,10 +318,10 @@ dump_nil(Out out) {
325
318
 
326
319
  static void
327
320
  dump_true(Out out) {
328
- size_t size = 4;
321
+ size_t size = 4;
329
322
 
330
323
  if (out->end - out->cur <= (long)size) {
331
- grow(out, size);
324
+ grow(out, size);
332
325
  }
333
326
  *out->cur++ = 't';
334
327
  *out->cur++ = 'r';
@@ -339,10 +332,10 @@ dump_true(Out out) {
339
332
 
340
333
  static void
341
334
  dump_false(Out out) {
342
- size_t size = 5;
335
+ size_t size = 5;
343
336
 
344
337
  if (out->end - out->cur <= (long)size) {
345
- grow(out, size);
338
+ grow(out, size);
346
339
  }
347
340
  *out->cur++ = 'f';
348
341
  *out->cur++ = 'a';
@@ -354,33 +347,33 @@ dump_false(Out out) {
354
347
 
355
348
  static void
356
349
  dump_fixnum(VALUE obj, Out out) {
357
- char buf[32];
358
- char *b = buf + sizeof(buf) - 1;
350
+ char buf[32];
351
+ char *b = buf + sizeof(buf) - 1;
359
352
  long num = NUM2LONG(obj);
360
- int neg = 0;
353
+ int neg = 0;
361
354
 
362
355
  if (0 > num) {
363
- neg = 1;
364
- num = -num;
356
+ neg = 1;
357
+ num = -num;
365
358
  }
366
359
  *b-- = '\0';
367
360
  if (0 < num) {
368
- for (; 0 < num; num /= 10, b--) {
369
- *b = (num % 10) + '0';
370
- }
371
- if (neg) {
372
- *b = '-';
373
- } else {
374
- b++;
375
- }
361
+ for (; 0 < num; num /= 10, b--) {
362
+ *b = (num % 10) + '0';
363
+ }
364
+ if (neg) {
365
+ *b = '-';
366
+ } else {
367
+ b++;
368
+ }
376
369
  } else {
377
- *b = '0';
370
+ *b = '0';
378
371
  }
379
372
  if (out->end - out->cur <= (long)(sizeof(buf) - (b - buf))) {
380
- grow(out, sizeof(buf) - (b - buf));
373
+ grow(out, sizeof(buf) - (b - buf));
381
374
  }
382
375
  for (; '\0' != *b; b++) {
383
- *out->cur++ = *b;
376
+ *out->cur++ = *b;
384
377
  }
385
378
  *out->cur = '\0';
386
379
  }
@@ -391,7 +384,7 @@ dump_bignum(VALUE obj, Out out) {
391
384
  int cnt = (int)RSTRING_LEN(rs);
392
385
 
393
386
  if (out->end - out->cur <= (long)cnt) {
394
- grow(out, cnt);
387
+ grow(out, cnt);
395
388
  }
396
389
  memcpy(out->cur, StringValuePtr(rs), cnt);
397
390
  out->cur += cnt;
@@ -432,10 +425,10 @@ dump_float(VALUE obj, Out out) {
432
425
  break;
433
426
  }
434
427
  if (out->end - out->cur <= (long)cnt) {
435
- grow(out, cnt);
428
+ grow(out, cnt);
436
429
  }
437
430
  for (b = buf; '\0' != *b; b++) {
438
- *out->cur++ = *b;
431
+ *out->cur++ = *b;
439
432
  }
440
433
  *out->cur = '\0';
441
434
  }
@@ -599,7 +592,7 @@ dump_array(VALUE a, int depth, Out out) {
599
592
  }
600
593
  size = 2;
601
594
  if (out->end - out->cur <= (long)size) {
602
- grow(out, size);
595
+ grow(out, size);
603
596
  }
604
597
  if (0 == cnt) {
605
598
  *out->cur++ = ']';
@@ -916,13 +909,17 @@ dump_time(VALUE obj, Out out) {
916
909
  char *b = buf + sizeof(buf) - 1;
917
910
  long size;
918
911
  char *dot = b - 10;
919
- #ifdef HAS_TIMESPEC
912
+ #if HAS_RB_TIME_TIMESPEC
920
913
  struct timespec ts = rb_time_timespec(obj);
921
914
  time_t sec = ts.tv_sec;
922
915
  long nsec = ts.tv_nsec;
923
916
  #else
924
917
  time_t sec = NUM2LONG(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
918
+ #if HAS_NANO_TIME
925
919
  long nsec = NUM2LONG(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
920
+ #else
921
+ long nsec = NUM2LONG(rb_funcall2(obj, oj_tv_usec_id, 0, 0)) * 1000;
922
+ #endif
926
923
  #endif
927
924
 
928
925
  *b-- = '\0';
@@ -986,12 +983,7 @@ dump_obj_comp(VALUE obj, int depth, Out out) {
986
983
  }
987
984
  dump_hash(h, depth, out->opts->mode, out);
988
985
  } else if (rb_respond_to(obj, oj_as_json_id)) {
989
- VALUE h = rb_funcall(obj, oj_as_json_id, 0);
990
-
991
- if (T_HASH != rb_type(h)) {
992
- rb_raise(rb_eTypeError, "%s.as_json() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
993
- }
994
- dump_hash(h, depth, out->opts->mode, out);
986
+ dump_val(rb_funcall(obj, oj_as_json_id, 0), depth, out);
995
987
  } else if (rb_respond_to(obj, oj_to_json_id)) {
996
988
  VALUE rs = rb_funcall(obj, oj_to_json_id, 0);
997
989
  const char *s = StringValuePtr(rs);
@@ -1017,7 +1009,7 @@ dump_obj_obj(VALUE obj, int depth, Out out) {
1017
1009
  }
1018
1010
  }
1019
1011
 
1020
- #if IVAR_HELPERS
1012
+ #if HAS_IVAR_HELPERS
1021
1013
  static int
1022
1014
  dump_attr_cb(ID key, VALUE value, Out out) {
1023
1015
  int depth = out->depth;
@@ -1090,7 +1082,7 @@ dump_obj_attrs(VALUE obj, int with_class, slot_t id, int depth, Out out) {
1090
1082
  {
1091
1083
  int cnt;
1092
1084
  // use encoding as the indicator for Ruby 1.8.7 or 1.9.x
1093
- #if IVAR_HELPERS
1085
+ #if HAS_IVAR_HELPERS
1094
1086
  cnt = (int)rb_ivar_count(obj);
1095
1087
  #else
1096
1088
  VALUE vars = rb_funcall2(obj, oj_instance_variables_id, 0, 0);
@@ -1105,14 +1097,14 @@ dump_obj_attrs(VALUE obj, int with_class, slot_t id, int depth, Out out) {
1105
1097
  *out->cur++ = ',';
1106
1098
  }
1107
1099
  out->depth = depth + 1;
1108
- #if IVAR_HELPERS
1100
+ #if HAS_IVAR_HELPERS
1109
1101
  rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
1110
1102
  out->cur--; // backup to overwrite last comma
1111
1103
  #else
1112
1104
  size = d2 * out->indent + 1;
1113
1105
  for (i = cnt; 0 < i; i--, np++) {
1114
1106
  if (out->end - out->cur <= (long)size) {
1115
- grow(out, size);
1107
+ grow(out, size);
1116
1108
  }
1117
1109
  vid = rb_to_id(*np);
1118
1110
  fill_indent(out, d2);
@@ -1131,7 +1123,7 @@ dump_obj_attrs(VALUE obj, int with_class, slot_t id, int depth, Out out) {
1131
1123
  *out->cur++ = ':';
1132
1124
  dump_val(rb_ivar_get(obj, vid), d2, out);
1133
1125
  if (out->end - out->cur <= 2) {
1134
- grow(out, 2);
1126
+ grow(out, 2);
1135
1127
  }
1136
1128
  if (1 < i) {
1137
1129
  *out->cur++ = ',';
@@ -1144,7 +1136,7 @@ dump_obj_attrs(VALUE obj, int with_class, slot_t id, int depth, Out out) {
1144
1136
  *out->cur = '\0';
1145
1137
  }
1146
1138
 
1147
- #ifndef NO_RSTRUCT
1139
+ #if HAS_RSTRUCT
1148
1140
  static void
1149
1141
  dump_struct_comp(VALUE obj, int depth, Out out) {
1150
1142
  if (rb_respond_to(obj, oj_to_hash_id)) {
@@ -1179,7 +1171,7 @@ dump_struct_obj(VALUE obj, int depth, Out out) {
1179
1171
  int d3 = d2 + 1;
1180
1172
  size_t len = strlen(class_name);
1181
1173
  size_t size = d2 * out->indent + d3 * out->indent + 10 + len;
1182
-
1174
+
1183
1175
  if (out->end - out->cur <= (long)size) {
1184
1176
  grow(out, size);
1185
1177
  }
@@ -1274,7 +1266,7 @@ dump_val(VALUE obj, int depth, Out out) {
1274
1266
  default: dump_data_obj(obj, out); break;
1275
1267
  }
1276
1268
  break;
1277
- #ifndef NO_RSTRUCT
1269
+ #if HAS_RSTRUCT
1278
1270
  case T_STRUCT: // for Range
1279
1271
  switch (out->opts->mode) {
1280
1272
  case StrictMode: raise_strict(obj); break;
@@ -1316,12 +1308,12 @@ dump_obj_to_json(VALUE obj, Options copts, Out out) {
1316
1308
  out->opts = copts;
1317
1309
  out->hash_cnt = 0;
1318
1310
  if (Yes == copts->circular) {
1319
- oj_cache8_new(&out->circ_cache);
1311
+ oj_cache8_new(&out->circ_cache);
1320
1312
  }
1321
1313
  out->indent = copts->indent;
1322
1314
  dump_val(obj, 0, out);
1323
1315
  if (Yes == copts->circular) {
1324
- oj_cache8_delete(out->circ_cache);
1316
+ oj_cache8_delete(out->circ_cache);
1325
1317
  }
1326
1318
  }
1327
1319
 
@@ -1337,18 +1329,18 @@ oj_write_obj_to_str(VALUE obj, Options copts) {
1337
1329
  void
1338
1330
  oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
1339
1331
  struct _Out out;
1340
- size_t size;
1341
- FILE *f;
1332
+ size_t size;
1333
+ FILE *f;
1342
1334
 
1343
1335
  dump_obj_to_json(obj, copts, &out);
1344
1336
  size = out.cur - out.buf;
1345
1337
  if (0 == (f = fopen(path, "w"))) {
1346
- rb_raise(rb_eIOError, "%s\n", strerror(errno));
1338
+ rb_raise(rb_eIOError, "%s\n", strerror(errno));
1347
1339
  }
1348
1340
  if (size != fwrite(out.buf, 1, size, f)) {
1349
- int err = ferror(f);
1341
+ int err = ferror(f);
1350
1342
 
1351
- rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err));
1343
+ rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err));
1352
1344
  }
1353
1345
  xfree(out.buf);
1354
1346
  fclose(f);
@@ -1425,7 +1417,7 @@ dump_leaf_array(Leaf leaf, int depth, Out out) {
1425
1417
 
1426
1418
  size = 2;
1427
1419
  if (out->end - out->cur <= (long)size) {
1428
- grow(out, size);
1420
+ grow(out, size);
1429
1421
  }
1430
1422
  *out->cur++ = '[';
1431
1423
  if (0 == leaf->elements) {
@@ -1463,7 +1455,7 @@ dump_leaf_hash(Leaf leaf, int depth, Out out) {
1463
1455
 
1464
1456
  size = 2;
1465
1457
  if (out->end - out->cur <= (long)size) {
1466
- grow(out, size);
1458
+ grow(out, size);
1467
1459
  }
1468
1460
  *out->cur++ = '{';
1469
1461
  if (0 == leaf->elements) {
@@ -1553,18 +1545,18 @@ oj_write_leaf_to_str(Leaf leaf, Options copts) {
1553
1545
  void
1554
1546
  oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts) {
1555
1547
  struct _Out out;
1556
- size_t size;
1557
- FILE *f;
1548
+ size_t size;
1549
+ FILE *f;
1558
1550
 
1559
1551
  dump_leaf_to_json(leaf, copts, &out);
1560
1552
  size = out.cur - out.buf;
1561
1553
  if (0 == (f = fopen(path, "w"))) {
1562
- rb_raise(rb_eIOError, "%s\n", strerror(errno));
1554
+ rb_raise(rb_eIOError, "%s\n", strerror(errno));
1563
1555
  }
1564
1556
  if (size != fwrite(out.buf, 1, size, f)) {
1565
- int err = ferror(f);
1557
+ int err = ferror(f);
1566
1558
 
1567
- rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err));
1559
+ rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err));
1568
1560
  }
1569
1561
  xfree(out.buf);
1570
1562
  fclose(f);