oj 2.7.3 → 2.8.0
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 +5 -2
- data/ext/oj/dump.c +87 -65
- data/ext/oj/odd.c +50 -8
- data/ext/oj/odd.h +1 -0
- data/ext/oj/oj.c +31 -0
- data/lib/oj/version.rb +1 -1
- data/test/a.rb +38 -0
- data/test/bug.rb +17 -0
- data/test/e.rb +12 -0
- data/test/foo.rb +24 -0
- data/test/lots.rb +68 -0
- data/test/mj.rb +48 -0
- data/test/struct.rb +29 -0
- data/test/test_object.rb +31 -0
- data/test/x.rb +59 -0
- metadata +11 -5
- data/test/perf1.rb +0 -64
- data/test/perf2.rb +0 -76
- data/test/perf_obj_old.rb +0 -213
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44d745373ae1530f6a0ae6ec981b62c84eac8f2d
|
4
|
+
data.tar.gz: c5c3c1506daf7f2ea35185d67fe1d469ced94fda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ef8a3aee09c48dce3f3a8565b1f4412c3703c3c9aad396f08573fc978631ea364dd58d2bd684960b29ec2dfd2b989ea3145f93a994c75b2c1eb0d8a9e5ed1620
|
7
|
+
data.tar.gz: 95429819075ae22192b957da153ea1768eab8e93441e74e988daa4f994d7723e6947d8d6d341f05a3253717c08a3e800d7bd4b770e39ffc702028faf57b96025
|
data/README.md
CHANGED
@@ -26,9 +26,12 @@ Follow [@peterohler on Twitter](http://twitter.com/#!/peterohler) for announceme
|
|
26
26
|
|
27
27
|
[![Build Status](https://secure.travis-ci.org/ohler55/oj.png?branch=master)](http://travis-ci.org/ohler55/oj)
|
28
28
|
|
29
|
-
### Current Release 2.
|
29
|
+
### Current Release 2.8.0
|
30
30
|
|
31
|
-
-
|
31
|
+
- Added support for registering special encoding and decoding rules for
|
32
|
+
specific classes. This the ActiveSupport subclass of the String class for
|
33
|
+
safe strings. For an example look at the `test_object.rb` file,
|
34
|
+
`test_odd_string` test.
|
32
35
|
|
33
36
|
[Older release notes](http://www.ohler.com/dev/oj_misc/release_notes.html).
|
34
37
|
|
data/ext/oj/dump.c
CHANGED
@@ -70,7 +70,7 @@ static void dump_raw(const char *str, size_t cnt, Out out);
|
|
70
70
|
static void dump_cstr(const char *str, size_t cnt, int is_sym, int escape1, Out out);
|
71
71
|
static void dump_hex(uint8_t c, Out out);
|
72
72
|
static void dump_str_comp(VALUE obj, Out out);
|
73
|
-
static void dump_str_obj(VALUE obj, Out out);
|
73
|
+
static void dump_str_obj(VALUE obj, int depth, Out out);
|
74
74
|
static void dump_sym_comp(VALUE obj, Out out);
|
75
75
|
static void dump_sym_obj(VALUE obj, Out out);
|
76
76
|
static void dump_class_comp(VALUE obj, Out out);
|
@@ -545,12 +545,19 @@ dump_str_comp(VALUE obj, Out out) {
|
|
545
545
|
}
|
546
546
|
|
547
547
|
static void
|
548
|
-
dump_str_obj(VALUE obj, Out out) {
|
549
|
-
|
550
|
-
|
551
|
-
|
548
|
+
dump_str_obj(VALUE obj, int depth, Out out) {
|
549
|
+
VALUE clas = rb_obj_class(obj);
|
550
|
+
Odd odd;
|
551
|
+
|
552
|
+
if (rb_cString != clas && 0 != (odd = oj_get_odd(clas))) {
|
553
|
+
dump_odd(obj, odd, clas, depth + 1, out);
|
554
|
+
} else {
|
555
|
+
const char *s = rb_string_value_ptr((VALUE*)&obj);
|
556
|
+
size_t len = RSTRING_LEN(obj);
|
557
|
+
char s1 = s[1];
|
552
558
|
|
553
|
-
|
559
|
+
dump_cstr(s, len, 0, (':' == *s || ('^' == *s && ('r' == s1 || 'i' == s1))), out);
|
560
|
+
}
|
554
561
|
}
|
555
562
|
|
556
563
|
static void
|
@@ -812,7 +819,7 @@ hash_cb_object(VALUE key, VALUE value, Out out) {
|
|
812
819
|
}
|
813
820
|
fill_indent(out, depth);
|
814
821
|
if (rb_type(key) == T_STRING) {
|
815
|
-
dump_str_obj(key, out);
|
822
|
+
dump_str_obj(key, depth, out);
|
816
823
|
*out->cur++ = ':';
|
817
824
|
dump_val(value, depth, out);
|
818
825
|
} else if (rb_type(key) == T_SYMBOL) {
|
@@ -1609,36 +1616,17 @@ raise_strict(VALUE obj) {
|
|
1609
1616
|
|
1610
1617
|
static void
|
1611
1618
|
dump_val(VALUE obj, int depth, Out out) {
|
1619
|
+
int type = rb_type(obj);
|
1620
|
+
|
1612
1621
|
if (MAX_DEPTH < depth) {
|
1613
1622
|
rb_raise(rb_eNoMemError, "Too deeply nested.\n");
|
1614
1623
|
}
|
1615
1624
|
switch (rb_type(obj)) {
|
1616
|
-
case T_NIL: dump_nil(out);
|
1617
|
-
case T_TRUE: dump_true(out);
|
1618
|
-
case T_FALSE: dump_false(out);
|
1619
|
-
case T_FIXNUM: dump_fixnum(obj, out);
|
1620
|
-
case T_FLOAT: dump_float(obj, out);
|
1621
|
-
case T_BIGNUM: dump_bignum(obj, out); break;
|
1622
|
-
case T_STRING:
|
1623
|
-
switch (out->opts->mode) {
|
1624
|
-
case StrictMode:
|
1625
|
-
case NullMode:
|
1626
|
-
case CompatMode: dump_str_comp(obj, out); break;
|
1627
|
-
case ObjectMode:
|
1628
|
-
default: dump_str_obj(obj, out); break;
|
1629
|
-
}
|
1630
|
-
break;
|
1631
|
-
case T_SYMBOL:
|
1632
|
-
switch (out->opts->mode) {
|
1633
|
-
case StrictMode: raise_strict(obj); break;
|
1634
|
-
case NullMode: dump_nil(out); break;
|
1635
|
-
case CompatMode: dump_sym_comp(obj, out); break;
|
1636
|
-
case ObjectMode:
|
1637
|
-
default: dump_sym_obj(obj, out); break;
|
1638
|
-
}
|
1639
|
-
break;
|
1640
|
-
case T_ARRAY: dump_array(obj, depth, out); break;
|
1641
|
-
case T_HASH: dump_hash(obj, depth, out->opts->mode, out); break;
|
1625
|
+
case T_NIL: dump_nil(out); break;
|
1626
|
+
case T_TRUE: dump_true(out); break;
|
1627
|
+
case T_FALSE: dump_false(out); break;
|
1628
|
+
case T_FIXNUM: dump_fixnum(obj, out); break;
|
1629
|
+
case T_FLOAT: dump_float(obj, out); break;
|
1642
1630
|
case T_CLASS:
|
1643
1631
|
switch (out->opts->mode) {
|
1644
1632
|
case StrictMode: raise_strict(obj); break;
|
@@ -1648,28 +1636,15 @@ dump_val(VALUE obj, int depth, Out out) {
|
|
1648
1636
|
default: dump_class_obj(obj, out); break;
|
1649
1637
|
}
|
1650
1638
|
break;
|
1651
|
-
|
1652
|
-
case T_RATIONAL:
|
1653
|
-
#endif
|
1654
|
-
case T_OBJECT:
|
1655
|
-
switch (out->opts->mode) {
|
1656
|
-
case StrictMode: dump_data_strict(obj, out); break;
|
1657
|
-
case NullMode: dump_data_null(obj, out); break;
|
1658
|
-
case CompatMode: dump_obj_comp(obj, depth, out); break;
|
1659
|
-
case ObjectMode:
|
1660
|
-
default: dump_obj_obj(obj, depth, out); break;
|
1661
|
-
}
|
1662
|
-
break;
|
1663
|
-
case T_DATA:
|
1639
|
+
case T_SYMBOL:
|
1664
1640
|
switch (out->opts->mode) {
|
1665
|
-
case StrictMode:
|
1666
|
-
case NullMode:
|
1667
|
-
case CompatMode:
|
1641
|
+
case StrictMode: raise_strict(obj); break;
|
1642
|
+
case NullMode: dump_nil(out); break;
|
1643
|
+
case CompatMode: dump_sym_comp(obj, out); break;
|
1668
1644
|
case ObjectMode:
|
1669
|
-
default:
|
1645
|
+
default: dump_sym_obj(obj, out); break;
|
1670
1646
|
}
|
1671
1647
|
break;
|
1672
|
-
|
1673
1648
|
case T_STRUCT: // for Range
|
1674
1649
|
switch (out->opts->mode) {
|
1675
1650
|
case StrictMode: raise_strict(obj); break;
|
@@ -1679,23 +1654,70 @@ dump_val(VALUE obj, int depth, Out out) {
|
|
1679
1654
|
default: dump_struct_obj(obj, depth, out); break;
|
1680
1655
|
}
|
1681
1656
|
break;
|
1682
|
-
|
1657
|
+
default:
|
1658
|
+
// Most developers have enough sense not to subclass primitive types but
|
1659
|
+
// since these classes could potentially be subclassed a check for odd
|
1660
|
+
// classes is performed.
|
1661
|
+
{
|
1662
|
+
VALUE clas = rb_obj_class(obj);
|
1663
|
+
Odd odd;
|
1664
|
+
|
1665
|
+
if (ObjectMode == out->opts->mode && 0 != (odd = oj_get_odd(clas))) {
|
1666
|
+
dump_odd(obj, odd, clas, depth + 1, out);
|
1667
|
+
return;
|
1668
|
+
}
|
1669
|
+
switch (type) {
|
1670
|
+
case T_BIGNUM: dump_bignum(obj, out); break;
|
1671
|
+
case T_STRING:
|
1672
|
+
switch (out->opts->mode) {
|
1673
|
+
case StrictMode:
|
1674
|
+
case NullMode:
|
1675
|
+
case CompatMode: dump_str_comp(obj, out); break;
|
1676
|
+
case ObjectMode:
|
1677
|
+
default: dump_str_obj(obj, depth, out); break;
|
1678
|
+
}
|
1679
|
+
break;
|
1680
|
+
case T_ARRAY: dump_array(obj, depth, out); break;
|
1681
|
+
case T_HASH: dump_hash(obj, depth, out->opts->mode, out); break;
|
1682
|
+
#if (defined T_RATIONAL && defined RRATIONAL)
|
1683
|
+
case T_RATIONAL:
|
1684
|
+
#endif
|
1685
|
+
case T_OBJECT:
|
1686
|
+
switch (out->opts->mode) {
|
1687
|
+
case StrictMode: dump_data_strict(obj, out); break;
|
1688
|
+
case NullMode: dump_data_null(obj, out); break;
|
1689
|
+
case CompatMode: dump_obj_comp(obj, depth, out); break;
|
1690
|
+
case ObjectMode:
|
1691
|
+
default: dump_obj_obj(obj, depth, out); break;
|
1692
|
+
}
|
1693
|
+
break;
|
1694
|
+
case T_DATA:
|
1695
|
+
switch (out->opts->mode) {
|
1696
|
+
case StrictMode: dump_data_strict(obj, out); break;
|
1697
|
+
case NullMode: dump_data_null(obj, out); break;
|
1698
|
+
case CompatMode: dump_data_comp(obj, depth, out);break;
|
1699
|
+
case ObjectMode:
|
1700
|
+
default: dump_data_obj(obj, depth, out); break;
|
1701
|
+
}
|
1702
|
+
break;
|
1683
1703
|
#if (defined T_COMPLEX && defined RCOMPLEX)
|
1684
|
-
|
1704
|
+
case T_COMPLEX:
|
1685
1705
|
#endif
|
1686
|
-
|
1687
|
-
|
1688
|
-
|
1689
|
-
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1706
|
+
case T_REGEXP:
|
1707
|
+
switch (out->opts->mode) {
|
1708
|
+
case StrictMode: raise_strict(obj); break;
|
1709
|
+
case NullMode: dump_nil(out); break;
|
1710
|
+
case CompatMode:
|
1711
|
+
case ObjectMode:
|
1712
|
+
default: dump_obj_comp(obj, depth, out); break;
|
1713
|
+
}
|
1714
|
+
break;
|
1715
|
+
default:
|
1716
|
+
rb_raise(rb_eNotImpError, "Failed to dump '%s' Object (%02x)\n",
|
1717
|
+
rb_class2name(rb_obj_class(obj)), rb_type(obj));
|
1718
|
+
break;
|
1719
|
+
}
|
1693
1720
|
}
|
1694
|
-
break;
|
1695
|
-
default:
|
1696
|
-
rb_raise(rb_eNotImpError, "Failed to dump '%s' Object (%02x)\n",
|
1697
|
-
rb_class2name(rb_obj_class(obj)), rb_type(obj));
|
1698
|
-
break;
|
1699
1721
|
}
|
1700
1722
|
}
|
1701
1723
|
|
data/ext/oj/odd.c
CHANGED
@@ -28,9 +28,13 @@
|
|
28
28
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
29
|
*/
|
30
30
|
|
31
|
+
#include <string.h>
|
32
|
+
|
31
33
|
#include "odd.h"
|
32
34
|
|
33
|
-
struct _Odd
|
35
|
+
static struct _Odd _odds[4]; // bump up if new initial Odd classes are added
|
36
|
+
static struct _Odd *odds = _odds;
|
37
|
+
static int odd_cnt = 0;
|
34
38
|
|
35
39
|
static void
|
36
40
|
set_class(Odd odd, const char *classname) {
|
@@ -96,16 +100,15 @@ oj_odd_init() {
|
|
96
100
|
*np++ = 0;
|
97
101
|
set_class(odd, "Range");
|
98
102
|
odd->attr_cnt = 3;
|
99
|
-
|
100
|
-
odd
|
101
|
-
odd->clas = Qundef;
|
103
|
+
|
104
|
+
odd_cnt = odd - odds + 1;
|
102
105
|
}
|
103
106
|
|
104
107
|
Odd
|
105
108
|
oj_get_odd(VALUE clas) {
|
106
|
-
Odd odd
|
109
|
+
Odd odd;
|
107
110
|
|
108
|
-
for (;
|
111
|
+
for (odd = odds + odd_cnt - 1; odds <= odd; odd--) {
|
109
112
|
if (clas == odd->clas) {
|
110
113
|
return odd;
|
111
114
|
}
|
@@ -115,9 +118,9 @@ oj_get_odd(VALUE clas) {
|
|
115
118
|
|
116
119
|
Odd
|
117
120
|
oj_get_oddc(const char *classname, size_t len) {
|
118
|
-
Odd odd
|
121
|
+
Odd odd;
|
119
122
|
|
120
|
-
for (;
|
123
|
+
for (odd = odds + odd_cnt - 1; odds <= odd; odd--) {
|
121
124
|
if (len == odd->clen && 0 == strncmp(classname, odd->classname, len)) {
|
122
125
|
return odd;
|
123
126
|
}
|
@@ -157,3 +160,42 @@ oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
|
|
157
160
|
}
|
158
161
|
return -1;
|
159
162
|
}
|
163
|
+
|
164
|
+
void
|
165
|
+
oj_reg_odd(VALUE clas, VALUE create_method, int mcnt, VALUE *members) {
|
166
|
+
Odd odd;
|
167
|
+
const char **np;
|
168
|
+
ID *ap;
|
169
|
+
|
170
|
+
if (_odds == odds) {
|
171
|
+
odds = ALLOC_N(struct _Odd, odd_cnt + 1);
|
172
|
+
|
173
|
+
memcpy(odds, _odds, sizeof(struct _Odd) * odd_cnt);
|
174
|
+
} else {
|
175
|
+
REALLOC_N(odds, struct _Odd, odd_cnt + 1);
|
176
|
+
}
|
177
|
+
odd = odds + odd_cnt;
|
178
|
+
odd->clas = clas;
|
179
|
+
odd->classname = strdup(rb_class2name(clas));
|
180
|
+
odd->clen = strlen(odd->classname);
|
181
|
+
odd->create_obj = clas;
|
182
|
+
odd->create_op = SYM2ID(create_method);
|
183
|
+
odd->attr_cnt = mcnt;
|
184
|
+
for (ap = odd->attrs, np = odd->attr_names; 0 < mcnt; mcnt--, ap++, np++, members++) {
|
185
|
+
switch (rb_type(*members)) {
|
186
|
+
case T_STRING:
|
187
|
+
*np = strdup(rb_string_value_ptr(members));
|
188
|
+
break;
|
189
|
+
case T_SYMBOL:
|
190
|
+
*np = rb_id2name(SYM2ID(*members));
|
191
|
+
break;
|
192
|
+
default:
|
193
|
+
rb_raise(rb_eArgError, "registered member identifiers must be Strings or Symbols.");
|
194
|
+
break;
|
195
|
+
}
|
196
|
+
*ap = rb_intern(*np);
|
197
|
+
}
|
198
|
+
*np = 0;
|
199
|
+
*ap = 0;
|
200
|
+
odd_cnt++;
|
201
|
+
}
|
data/ext/oj/odd.h
CHANGED
@@ -57,5 +57,6 @@ extern Odd oj_get_oddc(const char *classname, size_t len);
|
|
57
57
|
extern OddArgs oj_odd_alloc_args(Odd odd);
|
58
58
|
extern void oj_odd_free(OddArgs args);
|
59
59
|
extern int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value);
|
60
|
+
extern void oj_reg_odd(VALUE clas, VALUE create_method, int mcnt, VALUE *members);
|
60
61
|
|
61
62
|
#endif /* __OJ_ODD_H__ */
|
data/ext/oj/oj.c
CHANGED
@@ -841,6 +841,36 @@ to_stream(int argc, VALUE *argv, VALUE self) {
|
|
841
841
|
return Qnil;
|
842
842
|
}
|
843
843
|
|
844
|
+
/* call-seq: register_odd(clas, create_method, *members)
|
845
|
+
*
|
846
|
+
* Registers a class as special. This is useful for working around subclasses of
|
847
|
+
* primitive types as is done with ActiveSupport classes. The use of this
|
848
|
+
* function should be limited to just classes that can not be handled in the
|
849
|
+
* normal way. It is not intended as a hook for changing the output of all
|
850
|
+
* classes as it is not optimized for large numbers of classes.
|
851
|
+
*
|
852
|
+
* @param [Class] clas Class to me made special
|
853
|
+
* @param [Symbol] create_method method on the clas that will create a new
|
854
|
+
* instance of the clas when given all the member values in the
|
855
|
+
* order specified.
|
856
|
+
* @param [Symbol|String] members methods used to get the member values from
|
857
|
+
* instances of the clas
|
858
|
+
*/
|
859
|
+
static VALUE
|
860
|
+
register_odd(int argc, VALUE *argv, VALUE self) {
|
861
|
+
if (2 > argc) {
|
862
|
+
rb_raise(rb_eArgError, "incorrect number of arguments.");
|
863
|
+
}
|
864
|
+
Check_Type(argv[0], T_CLASS);
|
865
|
+
Check_Type(argv[1], T_SYMBOL);
|
866
|
+
if (MAX_ODD_ARGS < argc - 1) {
|
867
|
+
rb_raise(rb_eArgError, "too many members.");
|
868
|
+
}
|
869
|
+
oj_reg_odd(argv[0], argv[1], argc - 2, argv + 2);
|
870
|
+
|
871
|
+
return Qnil;
|
872
|
+
}
|
873
|
+
|
844
874
|
static void
|
845
875
|
str_writer_free(void *ptr) {
|
846
876
|
StrWriter sw;
|
@@ -1804,6 +1834,7 @@ void Init_oj() {
|
|
1804
1834
|
rb_define_module_function(Oj, "dump", dump, -1);
|
1805
1835
|
rb_define_module_function(Oj, "to_file", to_file, -1);
|
1806
1836
|
rb_define_module_function(Oj, "to_stream", to_stream, -1);
|
1837
|
+
rb_define_module_function(Oj, "register_odd", register_odd, -1);
|
1807
1838
|
|
1808
1839
|
rb_define_module_function(Oj, "saj_parse", oj_saj_parse, -1);
|
1809
1840
|
rb_define_module_function(Oj, "sc_parse", oj_sc_parse, -1);
|
data/lib/oj/version.rb
CHANGED
data/test/a.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby -wW1
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << File.dirname(__FILE__)
|
5
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
6
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
7
|
+
|
8
|
+
require 'pp'
|
9
|
+
require 'oj'
|
10
|
+
require 'perf'
|
11
|
+
|
12
|
+
obj = [[1],[2],[3],[4],[5],[6],[7],[8],[9]]
|
13
|
+
obj = [[],[],[],[],[],[],[],[],[]]
|
14
|
+
obj = {
|
15
|
+
'a' => 'Alpha', # string
|
16
|
+
'b' => true, # boolean
|
17
|
+
'c' => 12345, # number
|
18
|
+
'd' => [ true, [false, [12345, nil], 3.967, ['something', false], nil]], # mix it up array
|
19
|
+
'e' => { 'one' => 1, 'two' => 2 }, # hash
|
20
|
+
'f' => nil, # nil
|
21
|
+
'g' => 12345678901234567890123456789, # big number
|
22
|
+
'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
|
23
|
+
'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
|
24
|
+
}
|
25
|
+
|
26
|
+
json = Oj.dump(obj, mode: :compat)
|
27
|
+
|
28
|
+
puts json
|
29
|
+
#pp Oj.saj_parse(nil, json)
|
30
|
+
pp Oj.t_parse(json)
|
31
|
+
|
32
|
+
if true
|
33
|
+
perf = Perf.new()
|
34
|
+
perf.add('SAJ', 'oj') { Oj.saj_parse(nil, json) }
|
35
|
+
perf.add('T', 'oj') { Oj.t_parse(json) }
|
36
|
+
perf.add('load', 'oj') { Oj.load(json) }
|
37
|
+
perf.run(10000)
|
38
|
+
end
|
data/test/bug.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
# Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
|
5
|
+
# required. That can be set in the RUBYOPT environment variable.
|
6
|
+
# export RUBYOPT=-w
|
7
|
+
|
8
|
+
$VERBOSE = true
|
9
|
+
|
10
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
11
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
12
|
+
|
13
|
+
require 'oj'
|
14
|
+
|
15
|
+
obj = Oj.load_file('bug.json', :mode => :object)
|
16
|
+
|
17
|
+
puts Oj.dump(obj, :mode => :object, :indent => 0)
|
data/test/e.rb
ADDED
data/test/foo.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
# Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
|
5
|
+
# required. That can be set in the RUBYOPT environment variable.
|
6
|
+
# export RUBYOPT=-w
|
7
|
+
|
8
|
+
$VERBOSE = true
|
9
|
+
|
10
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
11
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
12
|
+
|
13
|
+
require 'oj'
|
14
|
+
|
15
|
+
reltypes={}
|
16
|
+
Oj::Doc.open_file('foo.json') do |doc|
|
17
|
+
doc.each_child do |target|
|
18
|
+
puts "#{target.local_key} is #{target.local_key.class}"
|
19
|
+
target.each_leaf do |score|
|
20
|
+
reltype=score.local_key
|
21
|
+
reltypes[reltype] = (reltypes[reltype] || 0) + 1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/test/lots.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
# Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
|
5
|
+
# required. That can be set in the RUBYOPT environment variable.
|
6
|
+
# export RUBYOPT=-w
|
7
|
+
|
8
|
+
$VERBOSE = true
|
9
|
+
|
10
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
11
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
12
|
+
|
13
|
+
require 'oj'
|
14
|
+
|
15
|
+
module One
|
16
|
+
module Two
|
17
|
+
module Three
|
18
|
+
class Empty
|
19
|
+
|
20
|
+
def initialize()
|
21
|
+
end
|
22
|
+
|
23
|
+
def eql?(o)
|
24
|
+
self.class == o.class
|
25
|
+
end
|
26
|
+
alias == eql?
|
27
|
+
|
28
|
+
def to_hash()
|
29
|
+
{'json_class' => "#{self.class.name}"}
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_json(*a)
|
33
|
+
%{{"json_class":"#{self.class.name}"}}
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.json_create(h)
|
37
|
+
self.new()
|
38
|
+
end
|
39
|
+
end # Empty
|
40
|
+
end # Three
|
41
|
+
end # Two
|
42
|
+
end # One
|
43
|
+
|
44
|
+
$obj = {
|
45
|
+
'a' => 'Alpha', # string
|
46
|
+
'b' => true, # boolean
|
47
|
+
'c' => 12345, # number
|
48
|
+
'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
|
49
|
+
'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
|
50
|
+
'f' => nil, # nil
|
51
|
+
'g' => One::Two::Three::Empty.new(),
|
52
|
+
'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
|
53
|
+
'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
|
54
|
+
}
|
55
|
+
|
56
|
+
$obj = [$obj]*10000
|
57
|
+
|
58
|
+
Oj.default_options = { :indent => 2, :mode => :compat }
|
59
|
+
|
60
|
+
$json = Oj.dump($obj, :mode => :compat)
|
61
|
+
|
62
|
+
$result = nil
|
63
|
+
100.times { |i|
|
64
|
+
print(".") if (0 == i % 10)
|
65
|
+
$result = Oj.compat_load($json)
|
66
|
+
}
|
67
|
+
|
68
|
+
|
data/test/mj.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
5
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
6
|
+
# $: << File.join(File.dirname(__FILE__), "../../multi_json/lib")
|
7
|
+
|
8
|
+
require 'multi_json'
|
9
|
+
require 'benchmark'
|
10
|
+
require 'yajl'
|
11
|
+
require 'json'
|
12
|
+
require 'oj'
|
13
|
+
|
14
|
+
iter = 1_000_000
|
15
|
+
iter = 100_000
|
16
|
+
|
17
|
+
json = %({"k1":"val1","k2":"val2","k3":"val3"})
|
18
|
+
obj = { k1: "val1", k2: "val2", k3: "val3" }
|
19
|
+
|
20
|
+
puts "Benchmarks for different JSON handlers with MultiJson."
|
21
|
+
puts " Ruby #{RUBY_VERSION}"
|
22
|
+
puts " #{iter} iterations"
|
23
|
+
|
24
|
+
MultiJson.engine = :oj
|
25
|
+
dt = Benchmark.realtime { iter.times { MultiJson.decode(json) }}
|
26
|
+
et = Benchmark.realtime { iter.times { MultiJson.encode(obj) }}
|
27
|
+
puts " Oj decode: #{dt} encode: #{et}"
|
28
|
+
|
29
|
+
MultiJson.engine = :yajl
|
30
|
+
dt = Benchmark.realtime { iter.times { MultiJson.decode(json) }}
|
31
|
+
et = Benchmark.realtime { iter.times { MultiJson.encode(obj) }}
|
32
|
+
puts " Yajl decode: #{dt} encode: #{et}"
|
33
|
+
|
34
|
+
MultiJson.engine = :json_gem
|
35
|
+
dt = Benchmark.realtime { iter.times { MultiJson.decode(json) }}
|
36
|
+
et = Benchmark.realtime { iter.times { MultiJson.encode(obj) }}
|
37
|
+
puts " Json decode: #{dt} encode: #{et}"
|
38
|
+
|
39
|
+
Oj.default_options = { :mode => :compat, :time_format => :ruby }
|
40
|
+
dt = Benchmark.realtime { iter.times { Oj.load(json) }}
|
41
|
+
et = Benchmark.realtime { iter.times { Oj.dump(obj) }}
|
42
|
+
puts "Raw Oj decode: #{dt} encode: #{et}"
|
43
|
+
|
44
|
+
ye = Yajl::Encoder.new
|
45
|
+
dt = Benchmark.realtime { iter.times { Yajl::Parser.parse(json) }}
|
46
|
+
et = Benchmark.realtime { iter.times { Yajl::Encoder.encode(obj) }}
|
47
|
+
e2 = Benchmark.realtime { iter.times { ye.encode(obj) }}
|
48
|
+
puts "Raw Yajl decode: #{dt} encode: #{et}, encoder: #{e2}"
|
data/test/struct.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
# Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
|
5
|
+
# required. That can be set in the RUBYOPT environment variable.
|
6
|
+
# export RUBYOPT=-w
|
7
|
+
|
8
|
+
$VERBOSE = true
|
9
|
+
|
10
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
11
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
12
|
+
|
13
|
+
require 'oj'
|
14
|
+
|
15
|
+
A = Struct.new(:a,:b,:c,:d)
|
16
|
+
B = Struct.new(:e,:f)
|
17
|
+
|
18
|
+
obj = [A.new(55, B.new(1, 'X'), B.new(2, 'Y'), 3)]
|
19
|
+
|
20
|
+
s = Oj.dump(obj, :mode => :object)
|
21
|
+
|
22
|
+
100000.times do
|
23
|
+
Oj.load(s, :mode => :object)
|
24
|
+
# ds = Oj.dump(o, :mode => :object)
|
25
|
+
# if ds != s
|
26
|
+
# puts ds
|
27
|
+
# raise "holy crap"
|
28
|
+
# end
|
29
|
+
end
|
data/test/test_object.rb
CHANGED
@@ -77,6 +77,31 @@ end # One
|
|
77
77
|
class Stuck < Struct.new(:a, :b)
|
78
78
|
end
|
79
79
|
|
80
|
+
class Strung < String
|
81
|
+
|
82
|
+
def initialize(str, safe)
|
83
|
+
super(str)
|
84
|
+
@safe = safe
|
85
|
+
end
|
86
|
+
|
87
|
+
def safe?()
|
88
|
+
@safe
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.create(str, safe)
|
92
|
+
new(str, safe)
|
93
|
+
end
|
94
|
+
|
95
|
+
def eql?(o)
|
96
|
+
super && self.class == o.class && @safe == o.safe?
|
97
|
+
end
|
98
|
+
alias == eql?
|
99
|
+
|
100
|
+
def inspect()
|
101
|
+
return super + '(' + @safe + ')'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
80
105
|
def hash_eql(h1, h2)
|
81
106
|
return false if h1.size != h2.size
|
82
107
|
h1.keys.each do |k|
|
@@ -390,6 +415,12 @@ class ObjectJuice < ::Test::Unit::TestCase
|
|
390
415
|
dump_and_load(Date.new(2012, 6, 19), false)
|
391
416
|
end
|
392
417
|
|
418
|
+
def test_odd_string
|
419
|
+
Oj.register_odd(Strung, :create, :to_s, 'safe?')
|
420
|
+
s = Strung.new("Pete", true)
|
421
|
+
dump_and_load(Strung.new("Pete", true), false)
|
422
|
+
end
|
423
|
+
|
393
424
|
def dump_and_load(obj, trace=false)
|
394
425
|
json = Oj.dump(obj, :indent => 2, :mode => :object)
|
395
426
|
puts json if trace
|
data/test/x.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
# Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
|
5
|
+
# required. That can be set in the RUBYOPT environment variable.
|
6
|
+
# export RUBYOPT=-w
|
7
|
+
|
8
|
+
$VERBOSE = true
|
9
|
+
|
10
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
11
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
12
|
+
|
13
|
+
require 'oj'
|
14
|
+
|
15
|
+
# Oj is not able to deserialize all classes that are a subclass of a Ruby
|
16
|
+
# Exception. Only exception that take one required string argument in the
|
17
|
+
# initialize() method are supported. This is an example of how to write an
|
18
|
+
# Exception subclass that supports both a single string intializer and an
|
19
|
+
# Exception as an argument. Additional optional arguments can be added as well.
|
20
|
+
#
|
21
|
+
# The reason for this restriction has to do with a design decision on the part
|
22
|
+
# of the Ruby developers. Exceptions are special Objects. They do not follow the
|
23
|
+
# rules of other Objects. Exceptions have 'mesg' and a 'bt' attribute. Note that
|
24
|
+
# these are not '@mesg' and '@bt'. They can not be set using the normal C or
|
25
|
+
# Ruby calls. The only way I have found to set the 'mesg' attribute is through
|
26
|
+
# the initializer. Unfortunately that means any subclass that provides a
|
27
|
+
# different initializer can not be automatically decoded. A way around this is
|
28
|
+
# to use a create function but this example shows an alternative.
|
29
|
+
|
30
|
+
class WrapException < StandardError
|
31
|
+
attr_reader :original
|
32
|
+
|
33
|
+
def initialize(msg_or_err)
|
34
|
+
if msg_or_err.is_a?(Exception)
|
35
|
+
super(msg_or_err.message)
|
36
|
+
@original = msg_or_err
|
37
|
+
set_backtrace(msg_or_err.backtrace)
|
38
|
+
else
|
39
|
+
super(message)
|
40
|
+
@original = nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
e = WrapException.new(RuntimeError.new("Something broke."))
|
46
|
+
|
47
|
+
json = Oj.dump(e, :mode => :object)
|
48
|
+
puts "original:\n#{json}"
|
49
|
+
# outputs:
|
50
|
+
# original:
|
51
|
+
# {"^o":"WrapException","original":{"^o":"RuntimeError","~mesg":"Something broke.","~bt":null},"~mesg":"Something broke.","~bt":null}
|
52
|
+
|
53
|
+
e2 = Oj.load(json, :mode => :object)
|
54
|
+
puts "dumped, loaded, and dumped again:\n#{Oj.dump(e2, :mode => :object)}"
|
55
|
+
# outputs:
|
56
|
+
# original: {"^o":"WrapException","original":{"^o":"RuntimeError","~mesg":"Something broke.","~bt":null},"~mesg":"Something broke.","~bt":null}
|
57
|
+
# dumped, loaded, and dumped again:
|
58
|
+
# {"^o":"WrapException","original":{"^o":"RuntimeError","~mesg":"Something broke.","~bt":null},"~mesg":"Something broke.","~bt":null}
|
59
|
+
|
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.
|
4
|
+
version: 2.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: 'The fastest JSON parser and object serializer. '
|
14
14
|
email: peter@ohler.com
|
@@ -56,14 +56,17 @@ files:
|
|
56
56
|
- lib/oj/saj.rb
|
57
57
|
- lib/oj/schandler.rb
|
58
58
|
- lib/oj/version.rb
|
59
|
+
- test/a.rb
|
60
|
+
- test/bug.rb
|
59
61
|
- test/debian_test.rb
|
62
|
+
- test/e.rb
|
60
63
|
- test/files.rb
|
64
|
+
- test/foo.rb
|
65
|
+
- test/lots.rb
|
66
|
+
- test/mj.rb
|
61
67
|
- test/perf.rb
|
62
|
-
- test/perf1.rb
|
63
|
-
- test/perf2.rb
|
64
68
|
- test/perf_compat.rb
|
65
69
|
- test/perf_fast.rb
|
66
|
-
- test/perf_obj_old.rb
|
67
70
|
- test/perf_object.rb
|
68
71
|
- test/perf_saj.rb
|
69
72
|
- test/perf_scp.rb
|
@@ -83,6 +86,7 @@ files:
|
|
83
86
|
- test/sample/shape.rb
|
84
87
|
- test/sample/text.rb
|
85
88
|
- test/sample_json.rb
|
89
|
+
- test/struct.rb
|
86
90
|
- test/test_compat.rb
|
87
91
|
- test/test_fast.rb
|
88
92
|
- test/test_gc.rb
|
@@ -94,6 +98,7 @@ files:
|
|
94
98
|
- test/test_strict.rb
|
95
99
|
- test/test_writer.rb
|
96
100
|
- test/tests.rb
|
101
|
+
- test/x.rb
|
97
102
|
homepage: http://www.ohler.com/oj
|
98
103
|
licenses:
|
99
104
|
- MIT
|
@@ -123,3 +128,4 @@ signing_key:
|
|
123
128
|
specification_version: 4
|
124
129
|
summary: A fast JSON parser and serializer.
|
125
130
|
test_files: []
|
131
|
+
has_rdoc: true
|
data/test/perf1.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby -wW1
|
2
|
-
# encoding: UTF-8
|
3
|
-
|
4
|
-
$: << File.join(File.dirname(__FILE__), "../lib")
|
5
|
-
$: << File.join(File.dirname(__FILE__), "../ext")
|
6
|
-
|
7
|
-
#require 'test/unit'
|
8
|
-
require 'optparse'
|
9
|
-
require 'oj'
|
10
|
-
require 'ox'
|
11
|
-
|
12
|
-
$indent = 2
|
13
|
-
|
14
|
-
opts = OptionParser.new
|
15
|
-
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
16
|
-
files = opts.parse(ARGV)
|
17
|
-
|
18
|
-
iter = 100000
|
19
|
-
s = %{
|
20
|
-
{ "class": "Foo::Bar",
|
21
|
-
"attr1": [ true, [false, [12345, null], 3.967, ["something", false], null]],
|
22
|
-
"attr2": { "one": 1 }
|
23
|
-
}
|
24
|
-
}
|
25
|
-
#s = File.read('sample.json')
|
26
|
-
|
27
|
-
Oj.default_options = { :indent => 0 }
|
28
|
-
|
29
|
-
obj = Oj.load(s)
|
30
|
-
xml = Ox.dump(obj, :indent => 0)
|
31
|
-
|
32
|
-
puts xml
|
33
|
-
|
34
|
-
start = Time.now
|
35
|
-
iter.times do
|
36
|
-
Oj.load(s)
|
37
|
-
end
|
38
|
-
dt = Time.now - start
|
39
|
-
puts "%d Oj.load()s in %0.3f seconds or %0.1f loads/msec" % [iter, dt, iter/dt/1000.0]
|
40
|
-
|
41
|
-
start = Time.now
|
42
|
-
iter.times do
|
43
|
-
Ox.load(xml)
|
44
|
-
end
|
45
|
-
dt = Time.now - start
|
46
|
-
puts "%d Ox.load()s in %0.3f seconds or %0.1f loads/msec" % [iter, dt, iter/dt/1000.0]
|
47
|
-
|
48
|
-
puts
|
49
|
-
|
50
|
-
start = Time.now
|
51
|
-
iter.times do
|
52
|
-
Oj.dump(obj)
|
53
|
-
end
|
54
|
-
dt = Time.now - start
|
55
|
-
puts "%d Oj.dump()s in %0.3f seconds or %0.1f dumps/msec" % [iter, dt, iter/dt/1000.0]
|
56
|
-
|
57
|
-
start = Time.now
|
58
|
-
iter.times do
|
59
|
-
Ox.dump(obj)
|
60
|
-
end
|
61
|
-
dt = Time.now - start
|
62
|
-
puts "%d Ox.dump()s in %0.3f seconds or %0.1f dumps/msec" % [iter, dt, iter/dt/1000.0]
|
63
|
-
|
64
|
-
puts
|
data/test/perf2.rb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby -wW1
|
2
|
-
# encoding: UTF-8
|
3
|
-
|
4
|
-
$: << File.join(File.dirname(__FILE__), "../lib")
|
5
|
-
$: << File.join(File.dirname(__FILE__), "../ext")
|
6
|
-
|
7
|
-
#require 'test/unit'
|
8
|
-
require 'optparse'
|
9
|
-
require 'yajl'
|
10
|
-
require 'oj'
|
11
|
-
|
12
|
-
$indent = 2
|
13
|
-
|
14
|
-
opts = OptionParser.new
|
15
|
-
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
16
|
-
files = opts.parse(ARGV)
|
17
|
-
|
18
|
-
class Foo
|
19
|
-
def initialize()
|
20
|
-
@x = true
|
21
|
-
@y = 58
|
22
|
-
end
|
23
|
-
def to_json()
|
24
|
-
%{{"x":#{@x},"y":#{@y}}}
|
25
|
-
end
|
26
|
-
def to_hash()
|
27
|
-
{ 'x' => @x, 'y' => @y }
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
iter = 100000
|
32
|
-
s = %{
|
33
|
-
{ "class": "Foo::Bar",
|
34
|
-
"attr1": [ true, [false, [12345, null], 3.967, ["something", false], null]],
|
35
|
-
"attr2": { "one": 1 }
|
36
|
-
}
|
37
|
-
}
|
38
|
-
|
39
|
-
obj = Oj.load(s)
|
40
|
-
obj["foo"] = Foo.new()
|
41
|
-
|
42
|
-
Oj.default_options = { :indent => 0, :effort => :internal }
|
43
|
-
|
44
|
-
puts
|
45
|
-
|
46
|
-
start = Time.now
|
47
|
-
iter.times do
|
48
|
-
Oj.load(s)
|
49
|
-
end
|
50
|
-
dt = Time.now - start
|
51
|
-
puts "%d Oj.load()s in %0.3f seconds or %0.1f loads/msec" % [iter, dt, iter/dt/1000.0]
|
52
|
-
|
53
|
-
start = Time.now
|
54
|
-
iter.times do
|
55
|
-
Yajl::Parser.parse(s)
|
56
|
-
end
|
57
|
-
dt = Time.now - start
|
58
|
-
puts "%d Yajl::Parser.parse()s in %0.3f seconds or %0.1f parses/msec" % [iter, dt, iter/dt/1000.0]
|
59
|
-
|
60
|
-
puts
|
61
|
-
|
62
|
-
start = Time.now
|
63
|
-
iter.times do
|
64
|
-
Oj.dump(obj)
|
65
|
-
end
|
66
|
-
dt = Time.now - start
|
67
|
-
puts "%d Oj.dump()s in %0.3f seconds or %0.1f dumps/msec" % [iter, dt, iter/dt/1000.0]
|
68
|
-
|
69
|
-
start = Time.now
|
70
|
-
iter.times do
|
71
|
-
Yajl::Encoder.encode(obj)
|
72
|
-
end
|
73
|
-
dt = Time.now - start
|
74
|
-
puts "%d Yajl::Encoder.encode()s in %0.3f seconds or %0.1f encodes/msec" % [iter, dt, iter/dt/1000.0]
|
75
|
-
|
76
|
-
puts
|
data/test/perf_obj_old.rb
DELETED
@@ -1,213 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby -wW1
|
2
|
-
|
3
|
-
$: << '.'
|
4
|
-
$: << '..'
|
5
|
-
$: << '../lib'
|
6
|
-
$: << '../ext'
|
7
|
-
|
8
|
-
if __FILE__ == $0
|
9
|
-
if (i = ARGV.index('-I'))
|
10
|
-
x,path = ARGV.slice!(i, 2)
|
11
|
-
$: << path
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
require 'optparse'
|
16
|
-
require 'ox'
|
17
|
-
require 'oj'
|
18
|
-
require 'perf'
|
19
|
-
require 'sample'
|
20
|
-
require 'files'
|
21
|
-
|
22
|
-
$verbose = 0
|
23
|
-
$circular = false
|
24
|
-
$indent = 0
|
25
|
-
|
26
|
-
do_sample = false
|
27
|
-
do_files = false
|
28
|
-
|
29
|
-
do_load = false
|
30
|
-
do_dump = false
|
31
|
-
do_read = false
|
32
|
-
do_write = false
|
33
|
-
$iter = 1000
|
34
|
-
|
35
|
-
opts = OptionParser.new
|
36
|
-
opts.on("-v", "increase verbosity") { $verbose += 1 }
|
37
|
-
|
38
|
-
opts.on("-c", "circular options") { $circular = true }
|
39
|
-
|
40
|
-
opts.on("-s", "load and dump as sample Ruby object") { do_sample = true }
|
41
|
-
opts.on("-f", "load and dump as files Ruby object") { do_files = true }
|
42
|
-
|
43
|
-
opts.on("-l", "load") { do_load = true }
|
44
|
-
opts.on("-d", "dump") { do_dump = true }
|
45
|
-
opts.on("-r", "read") { do_read = true }
|
46
|
-
opts.on("-w", "write") { do_write = true }
|
47
|
-
opts.on("-a", "load, dump, read and write") { do_load = true; do_dump = true; do_read = true; do_write = true }
|
48
|
-
|
49
|
-
opts.on("-i", "--iterations [Int]", Integer, "iterations") { |i| $iter = i }
|
50
|
-
|
51
|
-
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
52
|
-
files = opts.parse(ARGV)
|
53
|
-
|
54
|
-
if files.empty?
|
55
|
-
data = []
|
56
|
-
obj = do_sample ? sample_doc(2) : files('..')
|
57
|
-
mars = Marshal.dump(obj)
|
58
|
-
xml = Ox.dump(obj, :indent => $indent, circular: $circular)
|
59
|
-
json = Oj.dump(obj, :indent => $indent, circular: $circular)
|
60
|
-
File.open('sample.xml', 'w') { |f| f.write(xml) }
|
61
|
-
File.open('sample.json', 'w') { |f| f.write(json) }
|
62
|
-
File.open('sample.marshal', 'w') { |f| f.write(mars) }
|
63
|
-
data << { :file => 'sample.xml', :obj => obj, :xml => xml, :marshal => mars, :json => json }
|
64
|
-
else
|
65
|
-
puts "loading and parsing #{files}\n\n"
|
66
|
-
# TBD change to allow xml and json
|
67
|
-
data = files.map do |f|
|
68
|
-
xml = File.read(f)
|
69
|
-
obj = Ox.load(xml);
|
70
|
-
mars = Marshal.dump(obj)
|
71
|
-
json = Oj.dump(obj, :indent => $indent, circular: $circular)
|
72
|
-
{ :file => f, :obj => obj, :xml => xml, :marshal => mars, :json => json }
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
$ox_load_time = 0
|
77
|
-
$mars_load_time = 0
|
78
|
-
$ox_dump_time = 0
|
79
|
-
$oj_dump_time = 0
|
80
|
-
$mars_dump_time = 0
|
81
|
-
|
82
|
-
def perf_load(d)
|
83
|
-
filename = d[:file]
|
84
|
-
marshal_filename = 'sample.marshal'
|
85
|
-
xml = d[:xml]
|
86
|
-
mars = d[:marshal]
|
87
|
-
json = d[:json]
|
88
|
-
|
89
|
-
if 0 < $verbose
|
90
|
-
obj = Ox.load(xml, :mode => :object, :trace => $verbose)
|
91
|
-
return
|
92
|
-
end
|
93
|
-
start = Time.now
|
94
|
-
(1..$iter).each do
|
95
|
-
obj = Ox.load(xml, :mode => :object)
|
96
|
-
end
|
97
|
-
$ox_load_time = Time.now - start
|
98
|
-
puts "Parsing #{$iter} times with Ox took #{$ox_load_time} seconds."
|
99
|
-
|
100
|
-
start = Time.now
|
101
|
-
(1..$iter).each do
|
102
|
-
obj = Oj.load(json, :mode => :object)
|
103
|
-
end
|
104
|
-
$oj_load_time = Time.now - start
|
105
|
-
puts "Parsing #{$iter} times with Oj took #{$oj_load_time} seconds."
|
106
|
-
|
107
|
-
start = Time.now
|
108
|
-
(1..$iter).each do
|
109
|
-
obj = Marshal.load(mars)
|
110
|
-
end
|
111
|
-
$mars_load_time = Time.now - start
|
112
|
-
puts "Marshalling #{$iter} times took #{$mars_load_time} seconds."
|
113
|
-
puts ">>> Ox is %0.1f faster than Marshal loading.\n\n" % [$mars_load_time/$ox_load_time]
|
114
|
-
end
|
115
|
-
|
116
|
-
def perf_dump(d)
|
117
|
-
obj = d[:obj]
|
118
|
-
|
119
|
-
start = Time.now
|
120
|
-
(1..$iter).each do
|
121
|
-
xml = Ox.dump(obj, :indent => $indent, :circular => $circular)
|
122
|
-
#puts "*** ox:\n#{xml}"
|
123
|
-
end
|
124
|
-
$ox_dump_time = Time.now - start
|
125
|
-
puts "Ox dumping #{$iter} times with ox took #{$ox_dump_time} seconds."
|
126
|
-
|
127
|
-
Oj.default_options = {:indent => $indent}
|
128
|
-
start = Time.now
|
129
|
-
(1..$iter).each do
|
130
|
-
json = Oj.dump(obj)
|
131
|
-
end
|
132
|
-
$oj_dump_time = Time.now - start
|
133
|
-
puts "Oj dumping #{$iter} times with oj took #{$oj_dump_time} seconds."
|
134
|
-
|
135
|
-
obj = d[:obj]
|
136
|
-
start = Time.now
|
137
|
-
(1..$iter).each do
|
138
|
-
m = Marshal.dump(obj)
|
139
|
-
end
|
140
|
-
$mars_dump_time = Time.now - start
|
141
|
-
puts "Marshal dumping #{$iter} times took #{$mars_dump_time} seconds."
|
142
|
-
puts ">>> Ox is %0.1f faster than Marshal dumping.\n\n" % [$mars_dump_time/$ox_dump_time]
|
143
|
-
end
|
144
|
-
|
145
|
-
def perf_read(d)
|
146
|
-
ox_read_time = 0
|
147
|
-
mars_read_time = 0
|
148
|
-
|
149
|
-
filename = d[:file]
|
150
|
-
marshal_filename = 'sample.marshal'
|
151
|
-
xml = d[:xml]
|
152
|
-
mars = d[:marshal]
|
153
|
-
|
154
|
-
# now load from the file
|
155
|
-
start = Time.now
|
156
|
-
(1..$iter).each do
|
157
|
-
obj = Ox.load_file(filename, :mode => :object)
|
158
|
-
end
|
159
|
-
ox_read_time = Time.now - start
|
160
|
-
puts "Loading and parsing #{$iter} times with ox took #{ox_read_time} seconds."
|
161
|
-
|
162
|
-
start = Time.now
|
163
|
-
(1..$iter).each do
|
164
|
-
m = File.read(marshal_filename)
|
165
|
-
obj = Marshal.load(m)
|
166
|
-
end
|
167
|
-
mars_read_time = Time.now - start
|
168
|
-
puts "Reading and marshalling #{$iter} times took #{mars_read_time} seconds."
|
169
|
-
puts ">>> Ox is %0.1f faster than Marshal loading and parsing.\n\n" % [mars_read_time/ox_read_time]
|
170
|
-
|
171
|
-
end
|
172
|
-
|
173
|
-
def perf_write(d)
|
174
|
-
ox_write_time = 0
|
175
|
-
mars_write_time = 0
|
176
|
-
|
177
|
-
ox_filename = 'out.xml'
|
178
|
-
marshal_filename = 'out.marshal'
|
179
|
-
obj = d[:obj]
|
180
|
-
|
181
|
-
start = Time.now
|
182
|
-
(1..$iter).each do
|
183
|
-
xml = Ox.to_file(ox_filename, obj, :indent => $indent)
|
184
|
-
end
|
185
|
-
ox_write_time = Time.now - start
|
186
|
-
puts "Ox dumping #{$iter} times with ox took #{ox_write_time} seconds."
|
187
|
-
|
188
|
-
start = Time.now
|
189
|
-
(1..$iter).each do
|
190
|
-
m = Marshal.dump(obj, circular: $circular)
|
191
|
-
File.open(marshal_filename, "w") { |f| f.write(m) }
|
192
|
-
end
|
193
|
-
mars_write_time = Time.now - start
|
194
|
-
puts "Marshal dumping and writing #{$iter} times took #{mars_write_time} seconds."
|
195
|
-
puts ">>> Ox is %0.1f faster than Marshal dumping.\n\n" % [mars_write_time/ox_write_time]
|
196
|
-
|
197
|
-
end
|
198
|
-
|
199
|
-
#if do_sample or do_files
|
200
|
-
data.each do |d|
|
201
|
-
puts "Using file #{d[:file]}."
|
202
|
-
|
203
|
-
perf_load(d) if do_load
|
204
|
-
perf_dump(d) if do_dump
|
205
|
-
if do_load and do_dump
|
206
|
-
puts ">>> Ox is %0.1f faster than Marshal dumping and loading.\n\n" % [($mars_load_time + $mars_dump_time)/($ox_load_time + $ox_dump_time)] unless 0 == $mars_load_time
|
207
|
-
end
|
208
|
-
|
209
|
-
perf_read(d) if do_read
|
210
|
-
perf_write(d) if do_write
|
211
|
-
|
212
|
-
end
|
213
|
-
#end
|