oj 2.10.3 → 2.10.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 305f46dd63f131a124b3716a4d884f5dc355b80e
4
- data.tar.gz: bcb452a3c8ca23658bd5f3362434fdb57c2fc5c8
3
+ metadata.gz: 30d74e96259d1e3ef85ebc6c587f0f0b1f2d155a
4
+ data.tar.gz: 0471ab90473ecbd13760d4942edf3461fdf9403d
5
5
  SHA512:
6
- metadata.gz: 8c52c779973b9e6af3d5cfcd32236070a431fd16e79f204737179e00025c66c212c934c68e8a9d3c1a4838f1d9239c210ed85efe10996fd19baf63736d1a7550
7
- data.tar.gz: ea85ed66665d3c10cb8b2ae96d014530cae2bed32bd1c1168a1b4e8c96308827f5032d78f5ced787aa225b9f72b1558ecc5f4282fa47ee47593919b7833cb5ff
6
+ metadata.gz: 04e8cae819f240f2449e19d5673c040f84e1bfb6ea6820126a862f0b1e930437542400c7af5ec4cc0472cd17ed1b5904565c8dd20eee8f69762b05407fb6e6ef
7
+ data.tar.gz: 7666bec8a2682042e317dc4d8ca36200a06800e59a667f71ce1b1eb34eb855481f863d0f867111290d655a5c41ae68d93e626afcadcb95dc29a736708c1f8d20
data/README.md CHANGED
@@ -26,7 +26,15 @@ 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.10.3
29
+ ### Current Release 2.10.4
30
+
31
+ - Fixed Range encoding in compat mode to not use the object mode encoding.
32
+
33
+ - Fixed serialization problem with timestamps.
34
+
35
+ - Fixed compat parser to accept NaN and Infinity.
36
+
37
+ ### Release 2.10.3
30
38
 
31
39
  - Using the xmlschema option with :object mode now saves time as a string and
32
40
  preserves the timezone.
@@ -167,33 +175,3 @@ parsing.
167
175
  [Need for Speed](http://www.ohler.com/dev/need_for_speed/need_for_speed.html) for an overview of how Oj::Doc was designed.
168
176
 
169
177
  *OjC, a C JSON parser*: https://www.ohler.com/ojc also at https://github.com/ohler55/ojc
170
-
171
- ### License:
172
-
173
- Copyright (c) 2012, Peter Ohler
174
- All rights reserved.
175
-
176
- Redistribution and use in source and binary forms, with or without
177
- modification, are permitted provided that the following conditions are met:
178
-
179
- - Redistributions of source code must retain the above copyright notice, this
180
- list of conditions and the following disclaimer.
181
-
182
- - Redistributions in binary form must reproduce the above copyright notice,
183
- this list of conditions and the following disclaimer in the documentation
184
- and/or other materials provided with the distribution.
185
-
186
- - Neither the name of Peter Ohler nor the names of its contributors may be
187
- used to endorse or promote products derived from this software without
188
- specific prior written permission.
189
-
190
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
191
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
192
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
193
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
194
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
195
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
196
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
197
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
198
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
199
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -84,11 +84,44 @@ end_hash(struct _ParseInfo *pi) {
84
84
  }
85
85
  }
86
86
 
87
+ static VALUE
88
+ calc_hash_key(ParseInfo pi, Val parent) {
89
+ volatile VALUE rkey = parent->key_val;
90
+
91
+ if (Qundef == rkey) {
92
+ rkey = rb_str_new(parent->key, parent->klen);
93
+ }
94
+ rkey = oj_encode(rkey);
95
+ if (Yes == pi->options.sym_key) {
96
+ rkey = rb_str_intern(rkey);
97
+ }
98
+ return rkey;
99
+ }
100
+
101
+ static void
102
+ add_num(ParseInfo pi, NumInfo ni) {
103
+ pi->stack.head->val = oj_num_as_value(ni);
104
+ }
105
+
106
+ static void
107
+ hash_set_num(struct _ParseInfo *pi, Val parent, NumInfo ni) {
108
+ rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), oj_num_as_value(ni));
109
+ }
110
+
111
+ static void
112
+ array_append_num(ParseInfo pi, NumInfo ni) {
113
+ rb_ary_push(stack_peek(&pi->stack)->val, oj_num_as_value(ni));
114
+ }
115
+
116
+
87
117
  void
88
118
  oj_set_compat_callbacks(ParseInfo pi) {
89
119
  oj_set_strict_callbacks(pi);
90
120
  pi->end_hash = end_hash;
91
121
  pi->hash_set_cstr = hash_set_cstr;
122
+ pi->add_num = add_num;
123
+ pi->hash_set_num = hash_set_num;
124
+ pi->array_append_num = array_append_num;
92
125
  }
93
126
 
94
127
  VALUE
@@ -1169,8 +1169,6 @@ dump_data_null(VALUE obj, Out out) {
1169
1169
 
1170
1170
  static void
1171
1171
  dump_data_comp(VALUE obj, int depth, Out out) {
1172
- volatile VALUE o2;
1173
-
1174
1172
  if (rb_respond_to(obj, oj_to_hash_id)) {
1175
1173
  volatile VALUE h = rb_funcall(obj, oj_to_hash_id, 0);
1176
1174
 
@@ -1178,8 +1176,18 @@ dump_data_comp(VALUE obj, int depth, Out out) {
1178
1176
  rb_raise(rb_eTypeError, "%s.to_hash() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
1179
1177
  }
1180
1178
  dump_hash(h, Qundef, depth, out->opts->mode, out);
1181
- } else if (rb_respond_to(obj, oj_as_json_id) && obj != (o2 = rb_funcall(obj, oj_as_json_id, 0))) {
1182
- dump_val(o2, depth, out);
1179
+ } else if (Yes == out->opts->to_json && rb_respond_to(obj, oj_as_json_id)) {
1180
+ volatile VALUE aj = rb_funcall(obj, oj_as_json_id, 0);
1181
+
1182
+ // Catch the obvious brain damaged recursive dumping.
1183
+ if (aj == obj) {
1184
+ volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
1185
+
1186
+ dump_cstr(rb_string_value_ptr((VALUE*)&rstr), RSTRING_LEN(rstr), 0, 0, out);
1187
+ } else {
1188
+ dump_val(aj, depth, out);
1189
+ }
1190
+
1183
1191
  } else if (Yes == out->opts->to_json && rb_respond_to(obj, oj_to_json_id)) {
1184
1192
  volatile VALUE rs;
1185
1193
  const char *s;
@@ -1272,7 +1280,16 @@ dump_obj_comp(VALUE obj, int depth, Out out) {
1272
1280
  }
1273
1281
  dump_hash(h, Qundef, depth, out->opts->mode, out);
1274
1282
  } else if (Yes == out->opts->to_json && rb_respond_to(obj, oj_as_json_id)) {
1275
- dump_val(rb_funcall(obj, oj_as_json_id, 0), depth, out);
1283
+ volatile VALUE aj = rb_funcall(obj, oj_as_json_id, 0);
1284
+
1285
+ // Catch the obvious brain damaged recursive dumping.
1286
+ if (aj == obj) {
1287
+ volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
1288
+
1289
+ dump_cstr(rb_string_value_ptr((VALUE*)&rstr), RSTRING_LEN(rstr), 0, 0, out);
1290
+ } else {
1291
+ dump_val(aj, depth, out);
1292
+ }
1276
1293
  } else if (Yes == out->opts->to_json && rb_respond_to(obj, oj_to_json_id)) {
1277
1294
  volatile VALUE rs;
1278
1295
  const char *s;
@@ -1592,7 +1609,7 @@ dump_struct_comp(VALUE obj, int depth, Out out) {
1592
1609
  rb_raise(rb_eTypeError, "%s.to_hash() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
1593
1610
  }
1594
1611
  dump_hash(h, Qundef, depth, out->opts->mode, out);
1595
- } else if (rb_respond_to(obj, oj_to_json_id)) {
1612
+ } else if (Yes == out->opts->to_json && rb_respond_to(obj, oj_to_json_id)) {
1596
1613
  volatile VALUE rs = rb_funcall(obj, oj_to_json_id, 0);
1597
1614
  const char *s;
1598
1615
  int len;
@@ -1605,7 +1622,9 @@ dump_struct_comp(VALUE obj, int depth, Out out) {
1605
1622
  memcpy(out->cur, s, len);
1606
1623
  out->cur += len;
1607
1624
  } else {
1608
- dump_struct_obj(obj, depth, out);
1625
+ volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
1626
+
1627
+ dump_cstr(rb_string_value_ptr((VALUE*)&rstr), RSTRING_LEN(rstr), 0, 0, out);
1609
1628
  }
1610
1629
  }
1611
1630
 
@@ -1734,7 +1753,7 @@ dump_val(VALUE obj, int depth, Out out) {
1734
1753
  if (MAX_DEPTH < depth) {
1735
1754
  rb_raise(rb_eNoMemError, "Too deeply nested.\n");
1736
1755
  }
1737
- switch (rb_type(obj)) {
1756
+ switch (type) {
1738
1757
  case T_NIL: dump_nil(out); break;
1739
1758
  case T_TRUE: dump_true(out); break;
1740
1759
  case T_FALSE: dump_false(out); break;
@@ -1856,11 +1875,11 @@ oj_dump_obj_to_json(VALUE obj, Options copts, Out out) {
1856
1875
  case '}':
1857
1876
  grow(out, 1);
1858
1877
  *out->cur++ = '\n';
1859
- *out->cur = '\0';
1860
1878
  default:
1861
1879
  break;
1862
1880
  }
1863
1881
  }
1882
+ *out->cur = '\0';
1864
1883
  if (Yes == copts->circular) {
1865
1884
  oj_cache8_delete(out->circ_cache);
1866
1885
  }
@@ -164,9 +164,6 @@ hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
164
164
  #else
165
165
  parent->val = rb_time_new(ni->i, (long)(nsec / 1000));
166
166
  #endif
167
- // TBD if there is an exponent then if not gmt_offset
168
- // add gmt_offset and then getgmt()
169
- // if not 0 then getlocal(offset)
170
167
  }
171
168
  break;
172
169
  case 'i': // circular index
@@ -166,7 +166,7 @@ struct _Options oj_default_options = {
166
166
  UnixTime, // time_format
167
167
  Yes, // bigdec_as_num
168
168
  AutoDec, // bigdec_load
169
- No, // to_json
169
+ Yes, // to_json
170
170
  No, // nilnil
171
171
  json_class, // create_id
172
172
  10, // create_id_len
@@ -1734,12 +1734,17 @@ mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
1734
1734
  char buf[4096];
1735
1735
  struct _Out out;
1736
1736
  VALUE rstr;
1737
-
1737
+ struct _Options copts = oj_default_options;
1738
+
1738
1739
  out.buf = buf;
1739
1740
  out.end = buf + sizeof(buf) - 10;
1740
1741
  out.allocated = 0;
1742
+ // Have to turn off to_json to avoid the Active Support recursion problem.
1743
+ copts.to_json = No;
1744
+ // To be strict the mimic_object_to_json_options should be used but people
1745
+ // seem to prefer the option of changing that.
1741
1746
  //oj_dump_obj_to_json(self, &mimic_object_to_json_options, &out);
1742
- oj_dump_obj_to_json(self, &oj_default_options, &out);
1747
+ oj_dump_obj_to_json(self, &copts, &out);
1743
1748
  if (0 == out.buf) {
1744
1749
  rb_raise(rb_eNoMemError, "Not enough memory.");
1745
1750
  }
@@ -1846,6 +1851,7 @@ define_mimic_json(int argc, VALUE *argv, VALUE self) {
1846
1851
  }
1847
1852
 
1848
1853
  oj_default_options = mimic_object_to_json_options;
1854
+ oj_default_options.to_json = Yes;
1849
1855
 
1850
1856
  return mimic;
1851
1857
  }
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '2.10.3'
4
+ VERSION = '2.10.4'
5
5
  end
@@ -7,6 +7,26 @@ require 'helper'
7
7
  Oj.mimic_JSON
8
8
  require 'rails/all'
9
9
 
10
+ require 'active_model'
11
+ require 'active_model_serializers'
12
+ require 'active_support/json'
13
+
14
+ class Category
15
+ include ActiveModel::Model
16
+ include ActiveModel::SerializerSupport
17
+
18
+ attr_accessor :id, :name
19
+
20
+ def initialize(id, name)
21
+ @id = id
22
+ @name = name
23
+ end
24
+ end
25
+
26
+ class CategorySerializer < ActiveModel::Serializer
27
+ attributes :id, :name
28
+ end
29
+
10
30
  class MimicRails < Minitest::Test
11
31
 
12
32
  def test_mimic_exception
@@ -42,4 +62,26 @@ class MimicRails < Minitest::Test
42
62
  }, json)
43
63
  end
44
64
 
65
+ def test_dump_range
66
+ Oj.default_options= {:indent => 2} # JSON this will not change anything
67
+ json = ActiveSupport::JSON.encode([1, true, '01'..'12'])
68
+ assert_equal(%{[
69
+ 1,
70
+ true,
71
+ "01..12"
72
+ ]
73
+ }, json)
74
+ end
75
+
76
+ def test_dump_object
77
+ Oj.default_options= {:indent => 2}
78
+ category = Category.new(1, 'test')
79
+ serializer = CategorySerializer.new(category)
80
+
81
+ json = serializer.to_json()
82
+ json = serializer.as_json()
83
+ json = JSON.dump(serializer)
84
+ end
85
+
86
+
45
87
  end # MimicRails
@@ -1,5 +1,3 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  #!/usr/bin/env ruby
4
2
  # encoding: UTF-8
5
3
 
@@ -7,47 +5,60 @@ $: << File.dirname(__FILE__)
7
5
 
8
6
  require 'helper'
9
7
 
10
- class Handler
11
- def initialize
12
- @state = []
13
- end
14
-
15
- def hash_start
16
- @state << {}
17
- @state.last
18
- end
19
-
20
- def hash_end
21
- @state.pop
22
- end
23
-
24
- def hash_set(h,k,v)
25
- h.store(k,v)
26
- end
27
-
28
- def array_start
29
- @state << []
30
- @state.last
31
- end
32
-
8
+ require 'oj'
9
+ require 'securerandom'
33
10
 
34
- def array_end
35
- @state.pop
11
+ class Handler
12
+ def hash_start() {} end
13
+ def hash_set(h,k,v) h.store(k,v) end
14
+ def array_start() [] end
15
+ def array_append(a,v) a << v end
16
+ def error(message, line, column)
17
+ raise Exception.new(message, line, column)
36
18
  end
19
+ end
37
20
 
38
- def array_append(a,v)
39
- a << v
21
+ json = Oj.dump({"this"=>"object"})
22
+
23
+ if true
24
+ name = "/tmp/#{SecureRandom.uuid}"
25
+ `mkfifo #{name}`
26
+ if fork
27
+ open(name, 'r+') do |read_io|
28
+ p "start reading #{read_io.stat.ftype}"
29
+ Oj.sc_parse(Handler.new, read_io) {|v| p v}
30
+ p "stop reading"
31
+ end
32
+ else
33
+ open(name, 'w+') do |write_io|
34
+ p "start writing #{write_io.stat.ftype} autoclose: #{write_io.autoclose?}"
35
+ write_io.write json
36
+ write_io.write json
37
+ p "stop writing"
38
+ end
39
+ sleep(1) # make it obvious that there are two threads
40
+ open(name, 'w+') do |write_io|
41
+ p "start writing #{write_io.stat.ftype}"
42
+ write_io.write json
43
+ write_io.write json
44
+ p "stop writing"
45
+ end
40
46
  end
41
-
42
- def add_value(v)
43
- p v
47
+ else
48
+ IO.pipe do |read_io, write_io|
49
+ if fork
50
+ write_io.close
51
+ p "start reading #{read_io.stat.ftype}"
52
+ Oj.sc_parse(Handler.new, read_io) {|v| p v}
53
+ p "stop reading"
54
+ read_io.close
55
+ else
56
+ read_io.close
57
+ p "start writing #{write_io.stat.ftype}"
58
+ write_io.write json
59
+ write_io.write json
60
+ p "stop writing"
61
+ write_io.close
62
+ end
44
63
  end
45
-
46
- def error(message, line, column); p "ERROR: #{message}" end
47
64
  end
48
-
49
- $handler = Handler.new
50
-
51
- IO.popen("cat tst") { |p| puts Oj.sc_parse($handler, p) }
52
-
53
- #File.open('tst', 'r') { |file| Oj.sc_parse($handler, file) }
@@ -26,6 +26,15 @@ class SharedMimicTest < Minitest::Test
26
26
 
27
27
  def setup
28
28
  @default_options = Oj.default_options
29
+ @time = Time.at(1400000000).utc
30
+ @expected_time_string =
31
+ if defined?(Rails)
32
+ %{"2014-05-13T16:53:20.000Z"}
33
+ elsif RUBY_VERSION.start_with?('1.8')
34
+ %{"Tue May 13 16:53:20 UTC 2014"}
35
+ else
36
+ %{"2014-05-13 16:53:20 UTC"}
37
+ end
29
38
  end
30
39
 
31
40
  def teardown
@@ -46,26 +55,27 @@ class SharedMimicTest < Minitest::Test
46
55
 
47
56
  # dump
48
57
  def test_dump_string
49
- json = JSON.dump([1, true, nil])
50
- assert_equal(%{[1,true,null]}, json)
58
+ json = JSON.dump([1, true, nil, @time])
59
+ assert_equal(%{[1,true,null,#{@expected_time_string}]}, json)
51
60
  end
52
61
 
53
62
  def test_dump_with_options
54
63
  Oj.default_options= {:indent => 2} # JSON this will not change anything
55
- json = JSON.dump([1, true, nil])
64
+ json = JSON.dump([1, true, nil, @time])
56
65
  assert_equal(%{[
57
66
  1,
58
67
  true,
59
- null
68
+ null,
69
+ #{@expected_time_string}
60
70
  ]
61
71
  }, json)
62
72
  end
63
73
 
64
74
  def test_dump_io
65
75
  s = StringIO.new()
66
- json = JSON.dump([1, true, nil], s)
76
+ json = JSON.dump([1, true, nil, @time], s)
67
77
  assert_equal(s, json)
68
- assert_equal(%{[1,true,null]}, s.string)
78
+ assert_equal(%{[1,true,null,#{@expected_time_string}]}, s.string)
69
79
  end
70
80
  # TBD options
71
81
 
@@ -0,0 +1,64 @@
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
@@ -0,0 +1,76 @@
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
@@ -0,0 +1,213 @@
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
@@ -1,16 +1,19 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: UTF-8
3
3
 
4
+ $VERBOSE = true
5
+
4
6
  %w(lib ext test).each do |dir|
5
7
  $LOAD_PATH.unshift File.expand_path("../../#{dir}", __FILE__)
6
8
  end
7
9
 
10
+ require 'rubygems' if RUBY_VERSION.start_with?('1.8.')
8
11
  require 'oj'
9
12
 
13
+ Oj.mimic_JSON
14
+
15
+ #puts Oj.default_options
16
+
17
+ range = ("01".."12")
10
18
 
11
- Thread.new do
12
- string_io = StringIO.new('{"foo":"bar"}')
13
- Oj.load(string_io)
14
- string_io.rewind
15
- puts string_io.read
16
- end.join
19
+ puts Oj.dump(range)
@@ -398,11 +398,7 @@ class Juice < Minitest::Test
398
398
  sign = '-'
399
399
  tz = -tz
400
400
  end
401
- if RUBY_VERSION.start_with?('1.8')
402
- assert_equal(%{"2012-01-05T23:58:07%sZ"} % [sign], json)
403
- else
404
- assert_equal(%{"2012-01-05T23:58:07%s%02d:%02d"} % [sign, tz / 3600, tz / 60 % 60], json)
405
- end
401
+ assert_equal(%{"2012-01-05T23:58:07%s%02d:%02d"} % [sign, tz / 3600, tz / 60 % 60], json)
406
402
  end
407
403
  end
408
404
  def test_xml_time_compat_precision
@@ -440,11 +436,7 @@ class Juice < Minitest::Test
440
436
  sign = '-'
441
437
  tz = -tz
442
438
  end
443
- if RUBY_VERSION.start_with?('1.8')
444
- assert_equal(%{"2012-01-05T23:58:08%sZ"} % [sign], json)
445
- else
446
- assert_equal(%{"2012-01-05T23:58:08%s%02d:%02d"} % [sign, tz / 3600, tz / 60 % 60], json)
447
- end
439
+ assert_equal(%{"2012-01-05T23:58:08%s%02d:%02d"} % [sign, tz / 3600, tz / 60 % 60], json)
448
440
  end
449
441
  end
450
442
  def test_xml_time_compat_zulu
@@ -914,12 +906,8 @@ class Juice < Minitest::Test
914
906
  rescue Oj::ParseError
915
907
  assert(true)
916
908
  end
917
- begin
918
- Oj.load('Infinity', :mode => :compat)
919
- fail()
920
- rescue Oj::ParseError
921
- assert(true)
922
- end
909
+ x = Oj.load('Infinity', :mode => :compat)
910
+ assert_equal('Infinity', x.to_s)
923
911
 
924
912
  end
925
913
 
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.10.3
4
+ version: 2.10.4
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-10-04 00:00:00.000000000 Z
11
+ date: 2014-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -60,7 +60,6 @@ extensions:
60
60
  extra_rdoc_files:
61
61
  - README.md
62
62
  files:
63
- - LICENSE
64
63
  - README.md
65
64
  - ext/oj/buf.h
66
65
  - ext/oj/cache8.c
@@ -103,10 +102,8 @@ files:
103
102
  - lib/oj/version.rb
104
103
  - test/_test_mimic_rails.rb
105
104
  - test/bug.rb
106
- - test/bug2.rb
107
105
  - test/files.rb
108
106
  - test/helper.rb
109
- - test/io.rb
110
107
  - test/isolated/shared.rb
111
108
  - test/isolated/test_mimic_after.rb
112
109
  - test/isolated/test_mimic_alone.rb
@@ -114,11 +111,13 @@ files:
114
111
  - test/isolated/test_mimic_define.rb
115
112
  - test/isolated/test_mimic_rails_after.rb
116
113
  - test/isolated/test_mimic_rails_before.rb
117
- - test/mod.rb
118
114
  - test/perf.rb
115
+ - test/perf1.rb
116
+ - test/perf2.rb
119
117
  - test/perf_compat.rb
120
118
  - test/perf_fast.rb
121
119
  - test/perf_file.rb
120
+ - test/perf_obj_old.rb
122
121
  - test/perf_object.rb
123
122
  - test/perf_saj.rb
124
123
  - test/perf_scp.rb
@@ -138,24 +137,21 @@ files:
138
137
  - test/sample/shape.rb
139
138
  - test/sample/text.rb
140
139
  - test/sample_json.rb
141
- - test/struct.rb
142
140
  - test/test_compat.rb
143
141
  - test/test_debian.rb
144
142
  - test/test_fast.rb
145
143
  - test/test_file.rb
146
144
  - test/test_gc.rb
147
145
  - test/test_object.rb
146
+ - test/test_range.rb
148
147
  - test/test_saj.rb
149
148
  - test/test_scp.rb
150
149
  - test/test_strict.rb
151
150
  - test/test_various.rb
152
151
  - test/test_writer.rb
153
- - test/write_timebars.rb
154
- - test/zip.rb
155
152
  homepage: http://www.ohler.com/oj
156
153
  licenses:
157
154
  - MIT
158
- - GPL-3.0
159
155
  metadata: {}
160
156
  post_install_message:
161
157
  rdoc_options:
@@ -181,4 +177,3 @@ signing_key:
181
177
  specification_version: 4
182
178
  summary: A fast JSON parser and serializer.
183
179
  test_files: []
184
- has_rdoc: true
data/LICENSE DELETED
@@ -1,27 +0,0 @@
1
- Copyright (c) 2012, Peter Ohler
2
- All rights reserved.
3
-
4
- Redistribution and use in source and binary forms, with or without
5
- modification, are permitted provided that the following conditions are met:
6
-
7
- - Redistributions of source code must retain the above copyright notice, this
8
- list of conditions and the following disclaimer.
9
-
10
- - Redistributions in binary form must reproduce the above copyright notice,
11
- this list of conditions and the following disclaimer in the documentation
12
- and/or other materials provided with the distribution.
13
-
14
- - Neither the name of Peter Ohler nor the names of its contributors may be
15
- used to endorse or promote products derived from this software without
16
- specific prior written permission.
17
-
18
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- #!/usr/bin/env ruby
4
- # encoding: UTF-8
5
-
6
- $: << File.dirname(__FILE__)
7
-
8
- require 'helper'
9
-
10
-
data/test/io.rb DELETED
@@ -1,48 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
-
4
- $: << File.dirname(__FILE__)
5
-
6
- require 'helper'
7
-
8
- class Handler
9
- def initialize
10
- @state = []
11
- end
12
-
13
- def hash_start
14
- @state << {}
15
- @state.last
16
- end
17
-
18
- def hash_end
19
- @state.pop
20
- end
21
-
22
- def hash_set(h,k,v)
23
- h.store(k,v)
24
- end
25
-
26
- def array_start
27
- @state << []
28
- @state.last
29
- end
30
-
31
-
32
- def array_end
33
- @state.pop
34
- end
35
-
36
- def array_append(a,v)
37
- a << v
38
- end
39
-
40
- def error(message, line, column); p "ERROR: #{message}" end
41
- end
42
-
43
- handler = Handler.new
44
- def handler.add_value(v)
45
- p v
46
- end
47
-
48
- Oj.sc_parse(handler, StringIO.new('{"a":"b","c":[1,2,{"d":"e"}]}[4,5,6]'))
@@ -1,29 +0,0 @@
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
@@ -1,31 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
-
4
- %w(lib ext).each do |dir|
5
- $LOAD_PATH.unshift File.expand_path("../../#{dir}", __FILE__)
6
- end
7
-
8
- require 'stringio'
9
- require 'oj'
10
-
11
-
12
- filename = File.join(File.dirname(__FILE__), 'day.json')
13
- File.open(filename, "w") do |f|
14
- w = Oj::StreamWriter.new(f, :indent => -1)
15
- 390.times do |i|
16
- w.push_object()
17
- w.push_value(12, 'msgType')
18
- w.push_value(1, 'version')
19
- w.push_value(1_400_074_200 + i * 60, 'bar')
20
- w.push_value('TBC', 'source')
21
- w.push_array('timebars')
22
- w.push_object()
23
- w.push_value('aapl_24', 'asset')
24
- w.push_value(91.87, 'close')
25
- w.pop()
26
- w.pop()
27
- w.pop()
28
- end
29
- f.write("\n")
30
- end
31
-
@@ -1,34 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
-
4
- $: << File.dirname(__FILE__)
5
-
6
- require 'helper'
7
-
8
- require 'zlib'
9
-
10
- File.open('test.json.gz', 'r') do |file|
11
- Zlib::GzipReader.wrap(file) do |f2|
12
- puts "*** f2: #{f2}"
13
- Oj.load(f2) do |val|
14
- puts val
15
- end
16
- end
17
- end
18
-
19
- =begin
20
- And a json file with the following contents (then gzipped):
21
-
22
- {"a":2}
23
- {"b":2}
24
- The output is:
25
-
26
- {"a"=>2}
27
- {"b"=>2}
28
- bin/test:8:in `load': undefined method `new' for #<EOFError: end of file reached> (NoMethodError)
29
- from bin/test:8:in `block (2 levels) in <main>'
30
- from bin/test:7:in `wrap'
31
- from bin/test:7:in `block in <main>'
32
- from bin/test:6:in `open'
33
- from bin/test:6:in `<main>'
34
- =end