oj 2.0.9 → 2.0.10
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 -10
- data/ext/oj/dump.c +38 -46
- data/ext/oj/extconf.rb +1 -1
- data/ext/oj/fast.c +11 -4
- data/ext/oj/oj.c +34 -16
- data/ext/oj/oj.h +16 -2
- data/lib/oj/version.rb +1 -1
- data/test/mj.rb +48 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 027c673b279c8afd3bfe19993fd495522b7e7193
|
4
|
+
data.tar.gz: a007b49197ff05ebfa1de0b6f154cd9dbbaac632
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a391978b9e3bd73832878cf081a532814b1ed7cb7e4ca1c6279f63d15326715c28759992eddb4e224dc59f5804957bf5c88c35b38efa6f19f810a2f68b5b0ae
|
7
|
+
data.tar.gz: c5db0d98e3d96cb0c2ffa0e4fe57d5cd017a38d3d991f45487669f0d86dfcbfca5f275da220dafe5622dc3467ce614f9060c1dc9cf5c7d744f153d415cd2366e
|
data/README.md
CHANGED
@@ -32,20 +32,15 @@ A fast JSON parser and Object marshaller as a Ruby gem.
|
|
32
32
|
|
33
33
|
## <a name="release">Release Notes</a>
|
34
34
|
|
35
|
-
### Release 2.0.
|
36
|
-
|
37
|
-
- Fixed problem with INFINITY with CentOS and Ruby 2.0.0. There are some header file conflicts so a different INFINITY was used.
|
35
|
+
### Release 2.0.10
|
38
36
|
|
39
|
-
|
37
|
+
- Tweaked dump calls by reducing preallocation. Speeds are now several times faster for smaller objects.
|
40
38
|
|
41
|
-
-
|
42
|
-
Floats. This is useful if precision is important.
|
39
|
+
- Fixed Windows compile error with Ruby 2.0.0.
|
43
40
|
|
44
|
-
|
45
|
-
course that creates a loop and blows the stack. Oj ignores the as_json() for any object that returns itself and
|
46
|
-
instead encodes the object as it sees fit which is usually what is expected.
|
41
|
+
### Release 2.0.9
|
47
42
|
|
48
|
-
-
|
43
|
+
- Fixed problem with INFINITY with CentOS and Ruby 2.0.0. There are some header file conflicts so a different INFINITY was used.
|
49
44
|
|
50
45
|
## <a name="description">Description</a>
|
51
46
|
|
data/ext/oj/dump.c
CHANGED
@@ -50,19 +50,6 @@
|
|
50
50
|
|
51
51
|
typedef unsigned long ulong;
|
52
52
|
|
53
|
-
typedef struct _Out {
|
54
|
-
char *buf;
|
55
|
-
char *end;
|
56
|
-
char *cur;
|
57
|
-
Cache8 circ_cache;
|
58
|
-
slot_t circ_cnt;
|
59
|
-
int indent;
|
60
|
-
int depth; // used by dump_hash
|
61
|
-
Options opts;
|
62
|
-
uint32_t hash_cnt;
|
63
|
-
} *Out;
|
64
|
-
|
65
|
-
static void dump_obj_to_json(VALUE obj, Options copts, Out out);
|
66
53
|
static void raise_strict(VALUE obj);
|
67
54
|
static void dump_val(VALUE obj, int depth, Out out);
|
68
55
|
static void dump_nil(Out out);
|
@@ -108,7 +95,6 @@ static void grow(Out out, size_t len);
|
|
108
95
|
static size_t hibit_friendly_size(const uint8_t *str, size_t len);
|
109
96
|
static size_t ascii_friendly_size(const uint8_t *str, size_t len);
|
110
97
|
|
111
|
-
static void dump_leaf_to_json(Leaf leaf, Options copts, Out out);
|
112
98
|
static void dump_leaf(Leaf leaf, int depth, Out out);
|
113
99
|
static void dump_leaf_str(Leaf leaf, Out out);
|
114
100
|
static void dump_leaf_fixnum(Leaf leaf, Out out);
|
@@ -215,8 +201,14 @@ grow(Out out, size_t len) {
|
|
215
201
|
if (size <= len * 2 + pos) {
|
216
202
|
size += len;
|
217
203
|
}
|
218
|
-
|
219
|
-
|
204
|
+
if (out->allocated) {
|
205
|
+
buf = REALLOC_N(out->buf, char, (size + 10));
|
206
|
+
} else {
|
207
|
+
buf = ALLOC_N(char, (size + 10));
|
208
|
+
out->allocated = 1;
|
209
|
+
memcpy(buf, out->buf, out->end - out->buf);
|
210
|
+
}
|
211
|
+
if (0 == buf) {
|
220
212
|
rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
|
221
213
|
}
|
222
214
|
out->buf = buf;
|
@@ -1650,10 +1642,13 @@ dump_val(VALUE obj, int depth, Out out) {
|
|
1650
1642
|
}
|
1651
1643
|
}
|
1652
1644
|
|
1653
|
-
|
1654
|
-
|
1655
|
-
out->buf
|
1656
|
-
|
1645
|
+
void
|
1646
|
+
oj_dump_obj_to_json(VALUE obj, Options copts, Out out) {
|
1647
|
+
if (0 == out->buf) {
|
1648
|
+
out->buf = ALLOC_N(char, 4096);
|
1649
|
+
out->end = out->buf + 4085; // 1 less than end plus extra for possible errors
|
1650
|
+
out->allocated = 1;
|
1651
|
+
}
|
1657
1652
|
out->cur = out->buf;
|
1658
1653
|
out->circ_cnt = 0;
|
1659
1654
|
out->opts = copts;
|
@@ -1668,22 +1663,17 @@ dump_obj_to_json(VALUE obj, Options copts, Out out) {
|
|
1668
1663
|
}
|
1669
1664
|
}
|
1670
1665
|
|
1671
|
-
char*
|
1672
|
-
oj_write_obj_to_str(VALUE obj, Options copts) {
|
1673
|
-
struct _Out out;
|
1674
|
-
|
1675
|
-
dump_obj_to_json(obj, copts, &out);
|
1676
|
-
|
1677
|
-
return out.buf;
|
1678
|
-
}
|
1679
|
-
|
1680
1666
|
void
|
1681
1667
|
oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
1668
|
+
char buf[4096];
|
1682
1669
|
struct _Out out;
|
1683
1670
|
size_t size;
|
1684
1671
|
FILE *f;
|
1685
1672
|
|
1686
|
-
|
1673
|
+
out.buf = buf;
|
1674
|
+
out.end = buf + sizeof(buf) - 10;
|
1675
|
+
out.allocated = 0;
|
1676
|
+
oj_dump_obj_to_json(obj, copts, &out);
|
1687
1677
|
size = out.cur - out.buf;
|
1688
1678
|
if (0 == (f = fopen(path, "w"))) {
|
1689
1679
|
rb_raise(rb_eIOError, "%s\n", strerror(errno));
|
@@ -1693,7 +1683,9 @@ oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
|
1693
1683
|
|
1694
1684
|
rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err));
|
1695
1685
|
}
|
1696
|
-
|
1686
|
+
if (out.allocated) {
|
1687
|
+
xfree(out.buf);
|
1688
|
+
}
|
1697
1689
|
fclose(f);
|
1698
1690
|
}
|
1699
1691
|
|
@@ -1872,10 +1864,13 @@ dump_leaf(Leaf leaf, int depth, Out out) {
|
|
1872
1864
|
}
|
1873
1865
|
}
|
1874
1866
|
|
1875
|
-
|
1876
|
-
|
1877
|
-
out->buf
|
1878
|
-
|
1867
|
+
void
|
1868
|
+
oj_dump_leaf_to_json(Leaf leaf, Options copts, Out out) {
|
1869
|
+
if (0 == out->buf) {
|
1870
|
+
out->buf = ALLOC_N(char, 4096);
|
1871
|
+
out->end = out->buf + 4085; // 1 less than end plus extra for possible errors
|
1872
|
+
out->allocated = 1;
|
1873
|
+
}
|
1879
1874
|
out->cur = out->buf;
|
1880
1875
|
out->circ_cnt = 0;
|
1881
1876
|
out->opts = copts;
|
@@ -1884,22 +1879,17 @@ dump_leaf_to_json(Leaf leaf, Options copts, Out out) {
|
|
1884
1879
|
dump_leaf(leaf, 0, out);
|
1885
1880
|
}
|
1886
1881
|
|
1887
|
-
char*
|
1888
|
-
oj_write_leaf_to_str(Leaf leaf, Options copts) {
|
1889
|
-
struct _Out out;
|
1890
|
-
|
1891
|
-
dump_leaf_to_json(leaf, copts, &out);
|
1892
|
-
|
1893
|
-
return out.buf;
|
1894
|
-
}
|
1895
|
-
|
1896
1882
|
void
|
1897
1883
|
oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts) {
|
1884
|
+
char buf[4096];
|
1898
1885
|
struct _Out out;
|
1899
1886
|
size_t size;
|
1900
1887
|
FILE *f;
|
1901
1888
|
|
1902
|
-
|
1889
|
+
out.buf = buf;
|
1890
|
+
out.end = buf + sizeof(buf) - 10;
|
1891
|
+
out.allocated = 0;
|
1892
|
+
oj_dump_leaf_to_json(leaf, copts, &out);
|
1903
1893
|
size = out.cur - out.buf;
|
1904
1894
|
if (0 == (f = fopen(path, "w"))) {
|
1905
1895
|
rb_raise(rb_eIOError, "%s\n", strerror(errno));
|
@@ -1909,6 +1899,8 @@ oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts) {
|
|
1909
1899
|
|
1910
1900
|
rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err));
|
1911
1901
|
}
|
1912
|
-
|
1902
|
+
if (out.allocated) {
|
1903
|
+
xfree(out.buf);
|
1904
|
+
}
|
1913
1905
|
fclose(f);
|
1914
1906
|
}
|
data/ext/oj/extconf.rb
CHANGED
@@ -20,7 +20,7 @@ dflags = {
|
|
20
20
|
'RUBY_VERSION_MAJOR' => version[0],
|
21
21
|
'RUBY_VERSION_MINOR' => version[1],
|
22
22
|
'RUBY_VERSION_MICRO' => version[2],
|
23
|
-
'HAS_RB_TIME_TIMESPEC' => ('ruby' == type && ('1.9.3' == RUBY_VERSION || '2' <= version[0])) ? 1 : 0,
|
23
|
+
'HAS_RB_TIME_TIMESPEC' => (!is_windows && 'ruby' == type && ('1.9.3' == RUBY_VERSION || '2' <= version[0])) ? 1 : 0,
|
24
24
|
'HAS_ENCODING_SUPPORT' => (('ruby' == type || 'rubinius' == type) &&
|
25
25
|
(('1' == version[0] && '9' == version[1]) || '2' <= version[0])) ? 1 : 0,
|
26
26
|
'HAS_NANO_TIME' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 1 : 0,
|
data/ext/oj/fast.c
CHANGED
@@ -1571,13 +1571,20 @@ doc_dump(int argc, VALUE *argv, VALUE self) {
|
|
1571
1571
|
}
|
1572
1572
|
}
|
1573
1573
|
if (0 != (leaf = get_doc_leaf(doc, path))) {
|
1574
|
-
char *json;
|
1575
1574
|
VALUE rjson;
|
1576
1575
|
|
1577
1576
|
if (0 == filename) {
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1577
|
+
char buf[4096];
|
1578
|
+
struct _Out out;
|
1579
|
+
|
1580
|
+
out.buf = buf;
|
1581
|
+
out.end = buf + sizeof(buf) - 10;
|
1582
|
+
out.allocated = 0;
|
1583
|
+
oj_dump_leaf_to_json(leaf, &oj_default_options, &out);
|
1584
|
+
rjson = rb_str_new2(out.buf);
|
1585
|
+
if (out.allocated) {
|
1586
|
+
xfree(out.buf);
|
1587
|
+
}
|
1581
1588
|
} else {
|
1582
1589
|
oj_write_leaf_to_file(leaf, filename, &oj_default_options);
|
1583
1590
|
rjson = Qnil;
|
data/ext/oj/oj.c
CHANGED
@@ -573,22 +573,28 @@ strict_load(VALUE self, VALUE doc) {
|
|
573
573
|
*/
|
574
574
|
static VALUE
|
575
575
|
dump(int argc, VALUE *argv, VALUE self) {
|
576
|
-
char
|
576
|
+
char buf[4096];
|
577
|
+
struct _Out out;
|
577
578
|
struct _Options copts = oj_default_options;
|
578
579
|
VALUE rstr;
|
579
580
|
|
580
581
|
if (2 == argc) {
|
581
582
|
parse_options(argv[1], &copts);
|
582
583
|
}
|
583
|
-
|
584
|
+
out.buf = buf;
|
585
|
+
out.end = buf + sizeof(buf) - 10;
|
586
|
+
out.allocated = 0;
|
587
|
+
oj_dump_obj_to_json(*argv, &copts, &out);
|
588
|
+
if (0 == out.buf) {
|
584
589
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
585
590
|
}
|
586
|
-
rstr = rb_str_new2(
|
591
|
+
rstr = rb_str_new2(out.buf);
|
587
592
|
#if HAS_ENCODING_SUPPORT
|
588
593
|
rb_enc_associate(rstr, oj_utf8_encoding);
|
589
594
|
#endif
|
590
|
-
|
591
|
-
|
595
|
+
if (out.allocated) {
|
596
|
+
xfree(out.buf);
|
597
|
+
}
|
592
598
|
return rstr;
|
593
599
|
}
|
594
600
|
|
@@ -698,14 +704,19 @@ saj_parse(int argc, VALUE *argv, VALUE self) {
|
|
698
704
|
|
699
705
|
static VALUE
|
700
706
|
mimic_dump(int argc, VALUE *argv, VALUE self) {
|
701
|
-
char
|
707
|
+
char buf[4096];
|
708
|
+
struct _Out out;
|
702
709
|
struct _Options copts = oj_default_options;
|
703
710
|
VALUE rstr;
|
704
711
|
|
705
|
-
|
712
|
+
out.buf = buf;
|
713
|
+
out.end = buf + sizeof(buf) - 10;
|
714
|
+
out.allocated = 0;
|
715
|
+
oj_dump_obj_to_json(*argv, &copts, &out);
|
716
|
+
if (0 == out.buf) {
|
706
717
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
707
718
|
}
|
708
|
-
rstr = rb_str_new2(
|
719
|
+
rstr = rb_str_new2(out.buf);
|
709
720
|
#if HAS_ENCODING_SUPPORT
|
710
721
|
rb_enc_associate(rstr, oj_utf8_encoding);
|
711
722
|
#endif
|
@@ -717,8 +728,9 @@ mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
717
728
|
rb_funcall2(io, oj_write_id, 1, args);
|
718
729
|
rstr = io;
|
719
730
|
}
|
720
|
-
|
721
|
-
|
731
|
+
if (out.allocated) {
|
732
|
+
xfree(out.buf);
|
733
|
+
}
|
722
734
|
return rstr;
|
723
735
|
}
|
724
736
|
|
@@ -786,9 +798,13 @@ mimic_dump_load(int argc, VALUE *argv, VALUE self) {
|
|
786
798
|
|
787
799
|
static VALUE
|
788
800
|
mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
789
|
-
char
|
790
|
-
|
801
|
+
char buf[4096];
|
802
|
+
struct _Out out;
|
803
|
+
VALUE rstr;
|
791
804
|
|
805
|
+
out.buf = buf;
|
806
|
+
out.end = buf + sizeof(buf) - 10;
|
807
|
+
out.allocated = 0;
|
792
808
|
if (2 == argc && Qnil != argv[1]) {
|
793
809
|
struct _DumpOpts dump_opts;
|
794
810
|
VALUE ropts = argv[1];
|
@@ -841,15 +857,17 @@ mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
841
857
|
// :allow_nan is not supported as Oj always allows_nan
|
842
858
|
// :max_nesting is always set to 100
|
843
859
|
}
|
844
|
-
|
860
|
+
oj_dump_obj_to_json(*argv, copts, &out);
|
861
|
+
if (0 == out.buf) {
|
845
862
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
846
863
|
}
|
847
|
-
rstr = rb_str_new2(
|
864
|
+
rstr = rb_str_new2(out.buf);
|
848
865
|
#if HAS_ENCODING_SUPPORT
|
849
866
|
rb_enc_associate(rstr, oj_utf8_encoding);
|
850
867
|
#endif
|
851
|
-
|
852
|
-
|
868
|
+
if (out.allocated) {
|
869
|
+
xfree(out.buf);
|
870
|
+
}
|
853
871
|
return rstr;
|
854
872
|
}
|
855
873
|
|
data/ext/oj/oj.h
CHANGED
@@ -50,6 +50,7 @@ extern "C" {
|
|
50
50
|
#include <pthread.h>
|
51
51
|
#endif
|
52
52
|
#include "cache.h"
|
53
|
+
#include "cache8.h"
|
53
54
|
|
54
55
|
#ifdef RUBINIUS_RUBY
|
55
56
|
#undef T_RATIONAL
|
@@ -116,6 +117,19 @@ typedef struct _Options {
|
|
116
117
|
DumpOpts dump_opts;
|
117
118
|
} *Options;
|
118
119
|
|
120
|
+
typedef struct _Out {
|
121
|
+
char *buf;
|
122
|
+
char *end;
|
123
|
+
char *cur;
|
124
|
+
Cache8 circ_cache;
|
125
|
+
slot_t circ_cnt;
|
126
|
+
int indent;
|
127
|
+
int depth; // used by dump_hash
|
128
|
+
Options opts;
|
129
|
+
uint32_t hash_cnt;
|
130
|
+
int allocated;
|
131
|
+
} *Out;
|
132
|
+
|
119
133
|
typedef struct _Odd {
|
120
134
|
VALUE clas; // Ruby class
|
121
135
|
VALUE create_obj;
|
@@ -149,9 +163,9 @@ typedef struct _Leaf {
|
|
149
163
|
extern VALUE oj_parse(char *json, Options options);
|
150
164
|
extern void oj_saj_parse(VALUE handler, char *json);
|
151
165
|
|
152
|
-
extern
|
166
|
+
extern void oj_dump_obj_to_json(VALUE obj, Options copts, Out out);
|
153
167
|
extern void oj_write_obj_to_file(VALUE obj, const char *path, Options copts);
|
154
|
-
extern
|
168
|
+
extern void oj_dump_leaf_to_json(Leaf leaf, Options copts, Out out);
|
155
169
|
extern void oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts);
|
156
170
|
|
157
171
|
extern void _oj_raise_error(const char *msg, const char *xml, const char *current, const char* file, int line);
|
data/lib/oj/version.rb
CHANGED
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}"
|
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.0.
|
4
|
+
version: 2.0.10
|
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-03-
|
11
|
+
date: 2013-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: 'The fastest JSON parser and object serializer. '
|
14
14
|
email: peter@ohler.com
|
@@ -39,6 +39,7 @@ files:
|
|
39
39
|
- test/a.rb
|
40
40
|
- test/bug.rb
|
41
41
|
- test/files.rb
|
42
|
+
- test/mj.rb
|
42
43
|
- test/perf.rb
|
43
44
|
- test/perf1.rb
|
44
45
|
- test/perf2.rb
|