Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 420 lines (324 sloc) 19.605 kb
6248665 ready for use with limitations
Peter Ohler authored
1 # Oj gem
2 A fast JSON parser and Object marshaller as a Ruby gem.
3
4 ## <a name="installation">Installation</a>
5 gem install oj
6
7 ## <a name="source">Source</a>
8
9 *GitHub* *repo*: https://github.com/ohler55/oj
10
11 *RubyGems* *repo*: https://rubygems.org/gems/oj
12
13 ## <a name="build_status">Build Status</a>
14
da0330c getting the travis image to show status
Peter Ohler authored
15 [![Build Status](https://secure.travis-ci.org/ohler55/oj.png?branch=master)](http://travis-ci.org/ohler55/oj)
6248665 ready for use with limitations
Peter Ohler authored
16
17 ## <a name="links">Links of Interest</a>
18
f5aae61 docs completed, ready for a release
Peter Ohler authored
19 [Need for Speed](http://www.ohler.com/software/thoughts/Blog/Entries/2012/3/13_Need_for_Speed.html) for an overview of how Oj::Doc was designed.
20
afe4e99 changed json object format
Peter Ohler authored
21 *Fast XML parser and marshaller on RubyGems*: https://rubygems.org/gems/ox
6248665 ready for use with limitations
Peter Ohler authored
22
db33462 @MSNexploder fixed ox GitHub link
MSNexploder authored
23 *Fast XML parser and marshaller on GitHub*: https://github.com/ohler55/ox
57afd74 fixed a few bugs and added options
Peter Ohler authored
24
afe4e99 changed json object format
Peter Ohler authored
25 ## <a name="release">Release Notes</a>
6248665 ready for use with limitations
Peter Ohler authored
26
836d74d updated README
Peter Ohler authored
27 ### Release 1.2.0
8711c85 serializes any Object now. Tests added as well.
Peter Ohler authored
28
836d74d updated README
Peter Ohler authored
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.
7f6d49e made UTF-8 the default encoding instead of the Ruby default encoding
Peter Ohler authored
30
100b871 making timespec compatible
Peter Ohler authored
31 - Time encoding in :object mode is faster and higher nanosecond precision.
32
6248665 ready for use with limitations
Peter Ohler authored
33 ## <a name="description">Description</a>
34
35 Optimized JSON (Oj), as the name implies was written to provide speed
36 optimized JSON handling. It was designed as a faster alternative to Yajl and
37 other the common Ruby JSON parsers. So far is has achieved that at about 2
38 time faster than Yajl for parsing and 3 or more times faster writing JSON.
39
8711c85 serializes any Object now. Tests added as well.
Peter Ohler authored
40 Oj has several dump or serialization modes which control how Objects are
41 converted to JSON. These modes are set with the :effort option in either the
e0fb1d3 updatings docs and notes
Peter Ohler authored
42 default options or as one of the options to the dump() method.
43
44 - :strict mode will only allow the 7 basic JSON types to be serialized. Any other Object
45 will raise and Exception.
46
47 - :null mode replaces any Object that is not one of the JSON types is replaced by a JSON null.
48
49 - :object mode will dump any Object as a JSON Object with keys that match the
50 Ruby Object's variable names without the '@' character. This is the highest
51 performance mode.
52
53 - :compat mode is is the compatible with other systems. It will serialize any
54 Object but will check to see if the Object implements a to_hash() or to_json()
55 method. If either exists that method is used for serializing the Object. The
56 to_hash() is more flexible and produces more consistent output so it has a
57 preference over the to_json() method. If neither the to_json() or to_hash()
58 methods exist then the Oj internal Object variable encoding is used.
8711c85 serializes any Object now. Tests added as well.
Peter Ohler authored
59
5b248cc added Bag class and auto_define flag
Peter Ohler authored
60 Oj is compatible with Ruby 1.8.7, 1.9.2, 1.9.3, JRuby, and RBX.
61
6669206 ready for 0.6.0 release
Peter Ohler authored
62 ## <a name="compare">Comparisons</a>
63
f5aae61 docs completed, ready for a release
Peter Ohler authored
64 ### Fast Oj::Doc parser comparisons
65
66 The fast Oj::Doc parser is compared to the Yajl and JSON::Pure parsers with
67 strict JSON documents. No object conversions are included, just simple JSON.
68
69 Since the Oj::Doc deviation from the conventional parsers comparisons of not
70 only parsing but data access is also included. These tests use the
71 perf_fast.rb test file. The first benchmark is for just parsing. The second is
72 for doing a get on every leaf value in the JSON data structure. The third
73 fetchs a value from a specific spot in the document. With Yajl and JSON this
74 is done with a set of calls to fetch() for each level in the document. For
75 Oj::Doc a single fetch with a path is used.
76
77 The benchmark results are:
78
79 > perf_fast.rb -g 1 -f
80 --------------------------------------------------------------------------------
81 Parse Performance
82 Oj::Doc.parse 100000 times in 0.164 seconds or 609893.696 parse/sec.
83 Yajl.parse 100000 times in 3.168 seconds or 31569.902 parse/sec.
84 JSON::Ext.parse 100000 times in 3.282 seconds or 30464.826 parse/sec.
85
86 Summary:
87 System time (secs) rate (ops/sec)
88 --------- ----------- --------------
89 Oj::Doc 0.164 609893.696
90 Yajl 3.168 31569.902
91 JSON::Ext 3.282 30464.826
92
93 Comparison Matrix
94 (performance factor, 2.0 row is means twice as fast as column)
95 Oj::Doc Yajl JSON::Ext
96 --------- --------- --------- ---------
97 Oj::Doc 1.00 19.32 20.02
98 Yajl 0.05 1.00 1.04
99 JSON::Ext 0.05 0.96 1.00
100
101 --------------------------------------------------------------------------------
102 Parse and get all values Performance
103 Oj::Doc.parse 100000 times in 0.417 seconds or 240054.540 parse/sec.
104 Yajl.parse 100000 times in 5.159 seconds or 19384.191 parse/sec.
105 JSON::Ext.parse 100000 times in 5.269 seconds or 18978.638 parse/sec.
106
107 Summary:
108 System time (secs) rate (ops/sec)
109 --------- ----------- --------------
110 Oj::Doc 0.417 240054.540
111 Yajl 5.159 19384.191
112 JSON::Ext 5.269 18978.638
113
114 Comparison Matrix
115 (performance factor, 2.0 row is means twice as fast as column)
116 Oj::Doc Yajl JSON::Ext
117 --------- --------- --------- ---------
118 Oj::Doc 1.00 12.38 12.65
119 Yajl 0.08 1.00 1.02
120 JSON::Ext 0.08 0.98 1.00
121
122 --------------------------------------------------------------------------------
123 fetch nested Performance
124 Oj::Doc.fetch 100000 times in 0.094 seconds or 1059995.760 fetch/sec.
125 Ruby.fetch 100000 times in 0.503 seconds or 198851.434 fetch/sec.
126
127 Summary:
128 System time (secs) rate (ops/sec)
129 ------- ----------- --------------
130 Oj::Doc 0.094 1059995.760
131 Ruby 0.503 198851.434
132
133 Comparison Matrix
134 (performance factor, 2.0 row is means twice as fast as column)
135 Oj::Doc Ruby
136 ------- ------- -------
137 Oj::Doc 1.00 5.33
138 Ruby 0.19 1.00
139
140 What the results mean are that for getting just a few values from a JSON
141 document Oj::Doc is 20 times faster than any other parser and for accessing
142 all values it is still over 12 times faster than any other Ruby JSON parser.
143
144 ### Conventional Oj parser comparisons
145
6669206 ready for 0.6.0 release
Peter Ohler authored
146 The following table shows the difference is speeds between several
f5aae61 docs completed, ready for a release
Peter Ohler authored
147 serialization packages compared to the more conventional Oj parser. The tests
148 had to be scaled back due to limitation of some of the gems. I finally gave up
149 trying to get JSON Pure to serialize without errors with Ruby 1.9.3. It had
150 internal errors on anything other than a simple JSON structure. The errors
151 encountered were:
6669206 ready for 0.6.0 release
Peter Ohler authored
152
153 - MessagePack fails to convert Bignum to JSON
154
e0fb1d3 updatings docs and notes
Peter Ohler authored
155 - JSON Pure fails to serialize any numbers or Objects with the to_json() method
6669206 ready for 0.6.0 release
Peter Ohler authored
156
e0fb1d3 updatings docs and notes
Peter Ohler authored
157 Options were added to the test/perf_strict.rb test to run the test without
158 Object encoding and without Bignums.
6669206 ready for 0.6.0 release
Peter Ohler authored
159
160 None of the packages except Oj were able to serialize Ruby Objects that did
161 not have a to_json() method or were of the 7 native JSON types.
162
5b248cc added Bag class and auto_define flag
Peter Ohler authored
163 A perf_obj.rb file was added for comparing different Object marshalling
164 packages.
165
6669206 ready for 0.6.0 release
Peter Ohler authored
166 It is also worth noting that although Oj is slightly behind MessagePack for
167 parsing, Oj serialization is much faster than MessagePack even though Oj uses
168 human readable JSON vs the binary MessagePack format.
169
f5aae61 docs completed, ready for a release
Peter Ohler authored
170 Oj supports circular references when in :object mode and when the :circular
6b22c57 finishing off circular reference implementation
Peter Ohler authored
171 flag is true. None of the other gems tested supported circular
172 references. They failed in the following manners when the input included
173 circular references.
174
175 - Yajl core dumps Ruby
176
177 - JSON fails and raises an Exception
178
179 - MessagePack fails and raises an Exception
180
181 The benchmark results are:
6669206 ready for 0.6.0 release
Peter Ohler authored
182
183 with Object and Bignum encoding:
184
53e3bbc added benchmarks
Peter Ohler authored
185 > perf_strict.rb
6234873 ready for a release
Peter Ohler authored
186 --------------------------------------------------------------------------------
187 Load/Parse Performance
53e3bbc added benchmarks
Peter Ohler authored
188 Oj:compat.load 100000 times in 1.481 seconds or 67513.146 load/sec.
189 Oj.load 100000 times in 1.066 seconds or 93796.400 load/sec.
190 JSON::Ext.parse 100000 times in 3.023 seconds or 33074.875 parse/sec.
191 JSON::Pure.parse 100000 times in 18.908 seconds or 5288.799 parse/sec.
192 Ox.load 100000 times in 1.240 seconds or 80671.900 load/sec.
6234873 ready for a release
Peter Ohler authored
193
194 Summary:
195 System time (secs) rate (ops/sec)
196 ---------- ----------- --------------
53e3bbc added benchmarks
Peter Ohler authored
197 Oj 1.066 93796.400
198 Ox 1.240 80671.900
199 Oj:compat 1.481 67513.146
200 JSON::Ext 3.023 33074.875
201 JSON::Pure 18.908 5288.799
6234873 ready for a release
Peter Ohler authored
202
203 Comparison Matrix
204 (performance factor, 2.0 row is means twice as fast as column)
53e3bbc added benchmarks
Peter Ohler authored
205 Oj Ox Oj:compat JSON::Ext JSON::Pure
6234873 ready for a release
Peter Ohler authored
206 ---------- ---------- ---------- ---------- ---------- ----------
53e3bbc added benchmarks
Peter Ohler authored
207 Oj 1.00 1.16 1.39 2.84 17.73
208 Ox 0.86 1.00 1.19 2.44 15.25
209 Oj:compat 0.72 0.84 1.00 2.04 12.77
210 JSON::Ext 0.35 0.41 0.49 1.00 6.25
211 JSON::Pure 0.06 0.07 0.08 0.16 1.00
6234873 ready for a release
Peter Ohler authored
212
213
214 --------------------------------------------------------------------------------
215 Dump/Encode/Generate Performance
53e3bbc added benchmarks
Peter Ohler authored
216 Oj:compat.dump 100000 times in 0.789 seconds or 126715.249 dump/sec.
217 Oj.dump 100000 times in 0.457 seconds or 218798.751 dump/sec.
218 JSON::Ext.generate 100000 times in 4.371 seconds or 22878.630 generate/sec.
219 Ox.dump 100000 times in 0.501 seconds or 199425.256 dump/sec.
6234873 ready for a release
Peter Ohler authored
220
221 Summary:
222 System time (secs) rate (ops/sec)
223 --------- ----------- --------------
53e3bbc added benchmarks
Peter Ohler authored
224 Oj 0.457 218798.751
225 Ox 0.501 199425.256
226 Oj:compat 0.789 126715.249
227 JSON::Ext 4.371 22878.630
6234873 ready for a release
Peter Ohler authored
228
229 Comparison Matrix
230 (performance factor, 2.0 row is means twice as fast as column)
53e3bbc added benchmarks
Peter Ohler authored
231 Oj Ox Oj:compat JSON::Ext
6234873 ready for a release
Peter Ohler authored
232 --------- --------- --------- --------- ---------
53e3bbc added benchmarks
Peter Ohler authored
233 Oj 1.00 1.10 1.73 9.56
234 Ox 0.91 1.00 1.57 8.72
235 Oj:compat 0.58 0.64 1.00 5.54
236 JSON::Ext 0.10 0.11 0.18 1.00
237
238
239 The following packages were not included for the reason listed
240 ***** MessagePack: RangeError: bignum too big to convert into `unsigned long long'
241 ***** Yajl: RuntimeError: Yajl parse and encode did not return the same object as the original.
242 ***** JSON::Pure: TypeError: wrong argument type JSON::Pure::Generator::State (expected Data)
6669206 ready for 0.6.0 release
Peter Ohler authored
243
53e3bbc added benchmarks
Peter Ohler authored
244 without Objects or numbers (for JSON Pure, Yajl, and Messagepack) JSON:
6669206 ready for 0.6.0 release
Peter Ohler authored
245
6234873 ready for a release
Peter Ohler authored
246 --------------------------------------------------------------------------------
247 Load/Parse Performance
53e3bbc added benchmarks
Peter Ohler authored
248 Oj:compat.load 100000 times in 0.806 seconds or 124051.164 load/sec.
249 Oj.load 100000 times in 0.810 seconds or 123384.587 load/sec.
250 Yajl.parse 100000 times in 1.441 seconds or 69385.996 parse/sec.
251 JSON::Ext.parse 100000 times in 1.567 seconds or 63797.848 parse/sec.
252 JSON::Pure.parse 100000 times in 13.500 seconds or 7407.247 parse/sec.
253 Ox.load 100000 times in 0.954 seconds or 104836.748 load/sec.
254 MessagePack.unpack 100000 times in 0.651 seconds or 153707.817 unpack/sec.
6234873 ready for a release
Peter Ohler authored
255
256 Summary:
257 System time (secs) rate (ops/sec)
258 ----------- ----------- --------------
53e3bbc added benchmarks
Peter Ohler authored
259 MessagePack 0.651 153707.817
260 Oj:compat 0.806 124051.164
261 Oj 0.810 123384.587
262 Ox 0.954 104836.748
263 Yajl 1.441 69385.996
264 JSON::Ext 1.567 63797.848
265 JSON::Pure 13.500 7407.247
6234873 ready for a release
Peter Ohler authored
266
267 Comparison Matrix
268 (performance factor, 2.0 row is means twice as fast as column)
53e3bbc added benchmarks
Peter Ohler authored
269 MessagePack Oj:compat Oj Ox Yajl JSON::Ext JSON::Pure
270 ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
271 MessagePack 1.00 1.24 1.25 1.47 2.22 2.41 20.75
272 Oj:compat 0.81 1.00 1.01 1.18 1.79 1.94 16.75
273 Oj 0.80 0.99 1.00 1.18 1.78 1.93 16.66
274 Ox 0.68 0.85 0.85 1.00 1.51 1.64 14.15
275 Yajl 0.45 0.56 0.56 0.66 1.00 1.09 9.37
276 JSON::Ext 0.42 0.51 0.52 0.61 0.92 1.00 8.61
277 JSON::Pure 0.05 0.06 0.06 0.07 0.11 0.12 1.00
6234873 ready for a release
Peter Ohler authored
278
279
280 --------------------------------------------------------------------------------
281 Dump/Encode/Generate Performance
53e3bbc added benchmarks
Peter Ohler authored
282 Oj:compat.dump 100000 times in 0.173 seconds or 578526.262 dump/sec.
283 Oj.dump 100000 times in 0.179 seconds or 558362.880 dump/sec.
284 Yajl.encode 100000 times in 0.776 seconds or 128794.279 encode/sec.
285 JSON::Ext.generate 100000 times in 3.511 seconds or 28483.812 generate/sec.
286 JSON::Pure.generate 100000 times in 7.389 seconds or 13533.717 generate/sec.
287 Ox.dump 100000 times in 0.196 seconds or 510589.629 dump/sec.
288 MessagePack.pack 100000 times in 0.317 seconds or 315307.220 pack/sec.
6234873 ready for a release
Peter Ohler authored
289
290 Summary:
291 System time (secs) rate (ops/sec)
292 ----------- ----------- --------------
53e3bbc added benchmarks
Peter Ohler authored
293 Oj:compat 0.173 578526.262
294 Oj 0.179 558362.880
295 Ox 0.196 510589.629
296 MessagePack 0.317 315307.220
297 Yajl 0.776 128794.279
298 JSON::Ext 3.511 28483.812
299 JSON::Pure 7.389 13533.717
6234873 ready for a release
Peter Ohler authored
300
301 Comparison Matrix
302 (performance factor, 2.0 row is means twice as fast as column)
53e3bbc added benchmarks
Peter Ohler authored
303 Oj:compat Oj Ox MessagePack Yajl JSON::Ext JSON::Pure
304 ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
305 Oj:compat 1.00 1.04 1.13 1.83 4.49 20.31 42.75
306 Oj 0.97 1.00 1.09 1.77 4.34 19.60 41.26
307 Ox 0.88 0.91 1.00 1.62 3.96 17.93 37.73
308 MessagePack 0.55 0.56 0.62 1.00 2.45 11.07 23.30
309 Yajl 0.22 0.23 0.25 0.41 1.00 4.52 9.52
310 JSON::Ext 0.05 0.05 0.06 0.09 0.22 1.00 2.10
311 JSON::Pure 0.02 0.02 0.03 0.04 0.11 0.48 1.00
6234873 ready for a release
Peter Ohler authored
312
6248665 ready for use with limitations
Peter Ohler authored
313 ### Simple JSON Writing and Parsing:
314
315 require 'oj'
316
317 h = { 'one' => 1, 'array' => [ true, false ] }
318 json = Oj.dump(h)
319
320 # json =
321 # {
322 # "one":1,
323 # "array":[
324 # true,
325 # false
326 # ]
327 # }
328
9b9a86f @sferik Fix typo
sferik authored
329 h2 = Oj.load(json)
6248665 ready for use with limitations
Peter Ohler authored
330 puts "Same? #{h == h2}"
331 # true
4d28d2c updated readme with message format for object encoding
Peter Ohler authored
332
333 ### Object JSON format:
334
335 In :object mode Oj generates JSON that follows conventions which allow Class
336 and other information such as Object IDs for circular reference detection. The
337 formating follows the following rules.
338
339 1. JSON native types, true, false, nil, String, Hash, Array, and Number are
340 encoded normally.
341
6b22c57 finishing off circular reference implementation
Peter Ohler authored
342 2. A Symbol is encoded as a JSON string with a preceeding `:` character.
4d28d2c updated readme with message format for object encoding
Peter Ohler authored
343
6b22c57 finishing off circular reference implementation
Peter Ohler authored
344 3. The `^` character denotes a special key value when in a JSON Object sequence.
4d28d2c updated readme with message format for object encoding
Peter Ohler authored
345
6b22c57 finishing off circular reference implementation
Peter Ohler authored
346 4. A Ruby String that starts with `:` or the sequence `^i` or `^r` are encoded by
347 excaping the first character so that it appears as `\u005e` or `\u003a` instead of
348 `:` or `^`.
4d28d2c updated readme with message format for object encoding
Peter Ohler authored
349
6b22c57 finishing off circular reference implementation
Peter Ohler authored
350 5. A `"^c"` JSON Object key indicates the value should be converted to a Ruby
351 class. The sequence `{"^c":"Oj::Bag"}` is read as the Oj::Bag class.
4d28d2c updated readme with message format for object encoding
Peter Ohler authored
352
6b22c57 finishing off circular reference implementation
Peter Ohler authored
353 6. A `"^t"` JSON Object key indicates the value should be converted to a Ruby
354 Time. The sequence `{"^t":1325775487.000000}` is read as Jan 5, 2012 at 23:58:07.
4d28d2c updated readme with message format for object encoding
Peter Ohler authored
355
6b22c57 finishing off circular reference implementation
Peter Ohler authored
356 87. A `"^o"` JSON Object key indicates the value should be converted to a Ruby
357 Object. The first entry in the JSON Object must be a class with the `"^o"`
4d28d2c updated readme with message format for object encoding
Peter Ohler authored
358 key. After that each entry is treated as a variable of the Object where the
6b22c57 finishing off circular reference implementation
Peter Ohler authored
359 key is the variable name without the preceeding `@`. An example is
360 `{"^o":"Oj::Bag","x":58,"y":"marbles"}`.
4d28d2c updated readme with message format for object encoding
Peter Ohler authored
361
6b22c57 finishing off circular reference implementation
Peter Ohler authored
362 8. A `"^u"` JSON Object key indicates the value should be converted to a Ruby
363 Struct. The first entry in the JSON Object must be a class with the `"^u"`
0dfa515 now dumping struct in the correct format. Loading still unimplemented
Peter Ohler authored
364 key. After that each entry is is given a numeric position in the struct and
6b22c57 finishing off circular reference implementation
Peter Ohler authored
365 that is used as the key in the JSON Object. An example is `{"^u":["Range",1,7,false]}`.
0dfa515 now dumping struct in the correct format. Loading still unimplemented
Peter Ohler authored
366
6b22c57 finishing off circular reference implementation
Peter Ohler authored
367 9. When encoding an Object, if the variable name does not begin with an `@`
368 character then the name preceeded by a `~` character. This occurs in the
369 Exception class. An example is `{"^o":"StandardError","~mesg":"A Message","~bt":[".\/tests.rb:345:in `test_exception'"]}`.
4d28d2c updated readme with message format for object encoding
Peter Ohler authored
370
6b22c57 finishing off circular reference implementation
Peter Ohler authored
371 10. If a Hash entry has a key that is not a String or Symbol then the entry is
372 encoded with a key of the form `"^#n"` where n is a hex number. The value that
4d28d2c updated readme with message format for object encoding
Peter Ohler authored
373 is an Array where the first element is the key in the Hash and the second is
6b22c57 finishing off circular reference implementation
Peter Ohler authored
374 the value. An example is `{"^#3":[2,5]}`.
4d28d2c updated readme with message format for object encoding
Peter Ohler authored
375
6b22c57 finishing off circular reference implementation
Peter Ohler authored
376 11. A `"^i"` JSON entry in either an Object or Array is the ID of the Ruby
4d28d2c updated readme with message format for object encoding
Peter Ohler authored
377 Object being encoded. It is used when the :circular flag is set. It can appear
6b22c57 finishing off circular reference implementation
Peter Ohler authored
378 in either a JSON Object or in a JSON Array. In an Object the `"^i"` key has a
fdacd8d added hash circular support
Peter Ohler authored
379 corresponding reference Fixnum. In an array the sequence will include an
380 embedded reference number. An example is
6b22c57 finishing off circular reference implementation
Peter Ohler authored
381 `{"^o":"Oj::Bag","^i":1,"x":["^i2",true],"me":"^r1"}`.
382
383 12. A `"^r"` JSON entry in an Object is a references to a Object or Array that
384 already appears in the JSON String. It must match up with a previous `"^i"`
385 ID. An example is `{"^o":"Oj::Bag","^i":1,"x":3,"me":"^r1"}`.
fdacd8d added hash circular support
Peter Ohler authored
386
6b22c57 finishing off circular reference implementation
Peter Ohler authored
387 13. If an Array element is a String and starts with `"^i"` then the first
388 character, the `^` is encoded as a hex character sequence. An example is
389 `["\u005ei37",3]`.
fdacd8d added hash circular support
Peter Ohler authored
390
6b22c57 finishing off circular reference implementation
Peter Ohler authored
391 ### License:
392
393 Copyright (c) 2012, Peter Ohler
394 All rights reserved.
395
396 Redistribution and use in source and binary forms, with or without
397 modification, are permitted provided that the following conditions are met:
398
399 - Redistributions of source code must retain the above copyright notice, this
400 list of conditions and the following disclaimer.
401
402 - Redistributions in binary form must reproduce the above copyright notice,
403 this list of conditions and the following disclaimer in the documentation
404 and/or other materials provided with the distribution.
405
406 - Neither the name of Peter Ohler nor the names of its contributors may be
407 used to endorse or promote products derived from this software without
408 specific prior written permission.
409
410 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
411 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
412 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
413 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
414 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
415 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
416 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
417 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
418 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
419 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Something went wrong with that request. Please try again.