multi_json-1.8.0/0000755000004100000410000000000012220127643013732 5ustar www-datawww-datamulti_json-1.8.0/checksums.yaml.gz.sig0000444000004100000410000000040012220127643017773 0ustar www-datawww-data[]O/Wf~)>2-Ȉb '`Vz%m._ܱH-mY-.{Ȱ|h+yOVk<-Eľm!,AI|}O[]Dc-cf gsG\[c6/VozY3seC$x6L|_ElM3t[{{ޏc2>K\Ϙm X˚X"DQ^l& 9sW 8;3"<Vmulti_json-1.8.0/multi_json.gemspec0000644000004100000410000000247012220127643017465 0ustar www-datawww-data# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'multi_json/version' Gem::Specification.new do |spec| spec.add_development_dependency 'bundler', '~> 1.0' spec.authors = ["Michael Bleigh", "Josh Kalderimis", "Erik Michaels-Ober", "Pavel Pravosud"] spec.cert_chain = %w(certs/rwz.pem) spec.description = %q{A common interface to multiple JSON libraries, including Oj, Yajl, the JSON gem (with C-extensions), the pure-Ruby JSON gem, NSJSONSerialization, gson.rb, JrJackson, and OkJson.} spec.email = ['michael@intridea.com', 'josh.kalderimis@gmail.com', 'sferik@gmail.com'] spec.files = Dir['.yardopts', 'CHANGELOG.md', 'CONTRIBUTING.md', 'LICENSE.md', 'README.md', 'Rakefile', 'multi_json.gemspec', 'Gemfile', '.document', '.rspec', '.travis.yml' ,'spec/**/*', 'lib/**/*'] spec.homepage = 'http://github.com/intridea/multi_json' spec.licenses = ['MIT'] spec.name = 'multi_json' spec.require_paths = ['lib'] spec.required_rubygems_version = '>= 1.3.5' spec.signing_key = File.expand_path("~/.gem/private_key.pem") if $0 =~ /gem\z/ spec.summary = %q{A common interface to multiple JSON libraries.} spec.test_files = Dir['spec/**/*'] spec.version = MultiJson::Version end multi_json-1.8.0/.travis.yml0000644000004100000410000000024012220127643016037 0ustar www-datawww-databundler_args: --without development language: ruby rvm: - rbx-18mode - rbx-19mode - jruby-18mode - jruby-19mode - 1.8.7 - 1.9.2 - 1.9.3 - 2.0.0 multi_json-1.8.0/CONTRIBUTING.md0000644000004100000410000000337612220127643016174 0ustar www-datawww-data## Contributing In the spirit of [free software][free-sw], **everyone** is encouraged to help improve this project. [free-sw]: http://www.fsf.org/licensing/essays/free-sw.html Here are some ways *you* can contribute: * by using alpha, beta, and prerelease versions * by reporting bugs * by suggesting new features * by writing or editing documentation * by writing specifications * by writing code (**no patch is too small**: fix typos, add comments, clean up inconsistent whitespace) * by refactoring code * by closing [issues][] * by reviewing patches [issues]: https://github.com/intridea/multi_json/issues ## Submitting an Issue We use the [GitHub issue tracker][issues] to track bugs and features. Before submitting a bug report or feature request, check to make sure it hasn't already been submitted. When submitting a bug report, please include a [Gist][] that includes a stack trace and any details that may be necessary to reproduce the bug, including your gem version, Ruby version, and operating system. Ideally, a bug report should include a pull request with failing specs. [gist]: https://gist.github.com/ ## Submitting a Pull Request 1. [Fork the repository.][fork] 2. [Create a topic branch.][branch] 3. Add specs for your unimplemented feature or bug fix. 4. Run `bundle exec rake spec`. If your specs pass, return to step 3. 5. Implement your feature or bug fix. 6. Run `bundle exec rake spec`. If your specs fail, return to step 5. 7. Run `open coverage/index.html`. If your changes are not completely covered by your tests, return to step 3. 8. Add, commit, and push your changes. 9. [Submit a pull request.][pr] [fork]: http://help.github.com/fork-a-repo/ [branch]: http://learn.github.com/p/branching.html [pr]: http://help.github.com/send-pull-requests/ multi_json-1.8.0/README.md0000644000004100000410000001144412220127643015215 0ustar www-datawww-data# MultiJSON [![Gem Version](https://badge.fury.io/rb/multi_json.png)][gem] [![Build Status](https://secure.travis-ci.org/intridea/multi_json.png?branch=master)][travis] [![Dependency Status](https://gemnasium.com/intridea/multi_json.png?travis)][gemnasium] [![Code Climate](https://codeclimate.com/github/intridea/multi_json.png)][codeclimate] [![Coverage Status](https://coveralls.io/repos/intridea/multi_json/badge.png?branch=master)][coveralls] [gem]: https://rubygems.org/gems/multi_json [travis]: http://travis-ci.org/intridea/multi_json [gemnasium]: https://gemnasium.com/intridea/multi_json [codeclimate]: https://codeclimate.com/github/intridea/multi_json [coveralls]: https://coveralls.io/r/intridea/multi_json Lots of Ruby libraries parse JSON and everyone has their favorite JSON coder. Instead of choosing a single JSON coder and forcing users of your library to be stuck with it, you can use MultiJSON instead, which will simply choose the fastest available JSON coder. Here's how to use it: ```ruby require 'multi_json' MultiJson.load('{"abc":"def"}') #=> {"abc" => "def"} MultiJson.load('{"abc":"def"}', :symbolize_keys => true) #=> {:abc => "def"} MultiJson.dump({:abc => 'def'}) # convert Ruby back to JSON MultiJson.dump({:abc => 'def'}, :pretty => true) # encoded in a pretty form (if supported by the coder) ``` When loading invalid JSON, multiJSON will throw a `MultiJson::LoadError`. `MultiJson::DecodeError` is an alias for backwards compatibility. ```ruby MultiJson.load('invalid json') #=> MultiJson::LoadError ``` The `use` method, which sets the MultiJson adapter, takes either a symbol or a class (to allow for custom JSON parsers) that responds to both `.load` and `.dump` at the class level. MultiJSON tries to have intelligent defaulting. That is, if you have any of the supported engines already loaded, it will utilize them before attempting to load any. When loading, libraries are ordered by speed. First Oj, then Yajl, then the JSON gem, then JSON pure. If no other JSON library is available, MultiJSON falls back to [OkJson][], a simple, vendorable JSON parser. [okjson]: https://github.com/kr/okjson ## Supported JSON Engines * [Oj](https://github.com/ohler55/oj) Optimized JSON by Peter Ohler * [Yajl](https://github.com/brianmario/yajl-ruby) Yet Another JSON Library by Brian Lopez * [JSON](https://github.com/flori/json) The default JSON gem with C-extensions (ships with Ruby 1.9) * [JSON Pure](https://github.com/flori/json) A Ruby variant of the JSON gem * [NSJSONSerialization](https://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html) Wrapper for Apple's NSJSONSerialization in the Cocoa Framework (MacRuby only) * [gson.rb](https://github.com/avsej/gson.rb) A Ruby wrapper for google-gson library (JRuby only) * [JrJackson](https://github.com/guyboertje/jrjackson) JRuby wrapper for Jackson (JRuby only) * [OkJson][okjson] A simple, vendorable JSON parser ## Supported Ruby Versions This library aims to support and is [tested against][travis] the following Ruby implementations: * Ruby 1.8.7 * Ruby 1.9.2 * Ruby 1.9.3 * Ruby 2.0.0 * [JRuby][] * [Rubinius][] * [MacRuby][] (not tested on Travis CI) [jruby]: http://www.jruby.org/ [rubinius]: http://rubini.us/ [macruby]: http://www.macruby.org/ If something doesn't work on one of these interpreters, it's a bug. This library may inadvertently work (or seem to work) on other Ruby implementations, however support will only be provided for the versions listed above. If you would like this library to support another Ruby version, you may volunteer to be a maintainer. Being a maintainer entails making sure all tests run and pass on that implementation. When something breaks on your implementation, you will be responsible for providing patches in a timely fashion. If critical issues for a particular implementation exist at the time of a major release, support for that Ruby version may be dropped. ## Versioning This library aims to adhere to [Semantic Versioning 2.0.0][semver]. Violations of this scheme should be reported as bugs. Specifically, if a minor or patch version is released that breaks backward compatibility, that version should be immediately yanked and/or a new version should be immediately released that restores compatibility. Breaking changes to the public API will only be introduced with new major versions. As a result of this policy, you can (and should) specify a dependency on this gem using the [Pessimistic Version Constraint][pvc] with two digits of precision. For example: ```ruby spec.add_dependency 'multi_json', '~> 1.0' ``` [semver]: http://semver.org/ [pvc]: http://docs.rubygems.org/read/chapter/16#page74 ## Copyright Copyright (c) 2010-2013 Michael Bleigh, Josh Kalderimis, Erik Michaels-Ober, and Pavel Pravosud. See [LICENSE][] for details. [license]: LICENSE.md multi_json-1.8.0/Rakefile0000644000004100000410000000132412220127643015377 0ustar www-datawww-datarequire 'bundler' Bundler::GemHelper.install_tasks require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:base_spec) do |task| task.pattern = 'spec/multi_json_spec.rb' end namespace :adapters do Dir['spec/*_adapter_spec.rb'].each do |adapter_spec| adapter_name = adapter_spec[/(\w+)_adapter_spec/, 1] desc "Run #{adapter_name} adapter specs" RSpec::Core::RakeTask.new(adapter_name) do |task| task.pattern = adapter_spec end end end task :spec => %w[base_spec adapters:oj adapters:yajl adapters:json_gem adapters:json_pure adapters:ok_json adapters:gson adapters:jr_jackson adapters:nsjsonserialization] task :default => :spec task :test => :spec require 'yard' YARD::Rake::YardocTask.new multi_json-1.8.0/spec/0000755000004100000410000000000012220127643014664 5ustar www-datawww-datamulti_json-1.8.0/spec/shared/0000755000004100000410000000000012220127643016132 5ustar www-datawww-datamulti_json-1.8.0/spec/shared/options.rb0000644000004100000410000000614112220127643020154 0ustar www-datawww-datashared_examples_for 'has options' do |object| if object.respond_to?(:call) subject{ object.call } else subject{ object } end describe "dump options" do before do subject.dump_options = nil end after do subject.dump_options = nil end it 'returns default options if not set' do expect(subject.dump_options).to eq(subject.default_dump_options) end it 'allows hashes' do subject.dump_options = {:foo => 'bar'} expect(subject.dump_options).to eq(:foo => 'bar') end it 'allows objects that implement #to_hash' do value = Class.new do def to_hash {:foo => 'bar'} end end.new subject.dump_options = value expect(subject.dump_options).to eq(:foo => 'bar') end it 'evaluates lambda returning options (with args)' do subject.dump_options = lambda{ |a1, a2| { a1 => a2 }} expect(subject.dump_options('1', '2')).to eq('1' => '2') end it 'evaluates lambda returning options (with no args)' do subject.dump_options = lambda{{:foo => 'bar'}} expect(subject.dump_options).to eq(:foo => 'bar') end it 'returns empty hash in all other cases' do subject.dump_options = true expect(subject.dump_options).to eq(subject.default_dump_options) subject.dump_options = false expect(subject.dump_options).to eq(subject.default_dump_options) subject.dump_options = 10 expect(subject.dump_options).to eq(subject.default_dump_options) subject.dump_options = nil expect(subject.dump_options).to eq(subject.default_dump_options) end end describe "load options" do before do subject.load_options = nil end after do subject.load_options = nil end it 'returns default options if not set' do expect(subject.load_options).to eq(subject.default_load_options) end it 'allows hashes' do subject.load_options = {:foo => 'bar'} expect(subject.load_options).to eq(:foo => 'bar') end it 'allows objects that implement #to_hash' do value = Class.new do def to_hash {:foo => 'bar'} end end.new subject.load_options = value expect(subject.load_options).to eq(:foo => 'bar') end it 'evaluates lambda returning options (with args)' do subject.load_options = lambda{ |a1, a2| { a1 => a2 }} expect(subject.load_options('1', '2')).to eq('1' => '2') end it 'evaluates lambda returning options (with no args)' do subject.load_options = lambda{{:foo => 'bar'}} expect(subject.load_options).to eq(:foo => 'bar') end it 'returns empty hash in all other cases' do subject.load_options = true expect(subject.load_options).to eq(subject.default_load_options) subject.load_options = false expect(subject.load_options).to eq(subject.default_load_options) subject.load_options = 10 expect(subject.load_options).to eq(subject.default_load_options) subject.load_options = nil expect(subject.load_options).to eq(subject.default_load_options) end end end multi_json-1.8.0/spec/shared/adapter.rb0000644000004100000410000001513012220127643020077 0ustar www-datawww-data# encoding: UTF-8 require 'shared/options' shared_examples_for 'an adapter' do |adapter| before{ MultiJson.use adapter } it_behaves_like 'has options', adapter it 'does not modify argument hashes' do options = { :symbolize_keys => true, :pretty => false, :adapter => :ok_json } expect{MultiJson.load('{}', options)}.to_not change{options} expect{MultiJson.dump([42], options)}.to_not change{options} end describe '.dump' do describe '#dump_options' do before{ MultiJson.dump_options = MultiJson.adapter.dump_options = {} } after do expect(MultiJson.adapter.instance).to receive(:dump).with(1, :foo => 'bar', :fizz => 'buzz') MultiJson.dump(1, :fizz => 'buzz') MultiJson.dump_options = MultiJson.adapter.dump_options = nil end it 'respects global dump options' do MultiJson.dump_options = {:foo => 'bar'} end it 'respects per-adapter dump options' do MultiJson.adapter.dump_options = {:foo => 'bar'} end it 'adapter-specific are overridden by global options' do MultiJson.adapter.dump_options = {:foo => 'foo'} MultiJson.dump_options = {:foo => 'bar'} end end it 'writes decodable JSON' do [ {'abc' => 'def'}, [1, 2, 3, '4', true, false, nil] ].each do |example| expect(MultiJson.load(MultiJson.dump(example))).to eq example end end unless 'json_pure' == adapter || 'json_gem' == adapter it 'dumps time in correct format' do time = Time.at(1355218745).utc dumped_json = MultiJson.dump(time) expected = if RUBY_VERSION > '1.9' '2012-12-11 09:39:05 UTC' else 'Tue Dec 11 09:39:05 UTC 2012' end expect(MultiJson.load(dumped_json)).to eq expected end end it 'dumps symbol and fixnum keys as strings' do [ [ {:foo => {:bar => 'baz'}}, {'foo' => {'bar' => 'baz'}}, ], [ [{:foo => {:bar => 'baz'}}], [{'foo' => {'bar' => 'baz'}}], ], [ {:foo => [{:bar => 'baz'}]}, {'foo' => [{'bar' => 'baz'}]}, ], [ {1 => {2 => {3 => 'bar'}}}, {'1' => {'2' => {'3' => 'bar'}}} ] ].each do |example, expected| dumped_json = MultiJson.dump(example) expect(MultiJson.load(dumped_json)).to eq expected end end it 'dumps rootless JSON' do expect(MultiJson.dump('random rootless string')).to eq '"random rootless string"' expect(MultiJson.dump(123)).to eq '123' end it 'passes options to the adapter' do expect(MultiJson.adapter).to receive(:dump).with('foo', {:bar => :baz}) MultiJson.dump('foo', :bar => :baz) end # This behavior is currently not supported by gson.rb # See discussion at https://github.com/intridea/multi_json/pull/71 unless adapter.name == 'MultiJson::Adapters::Gson' it 'dumps custom objects that implement to_json' do klass = Class.new do def to_json(*) '"foobar"' end end expect(MultiJson.dump(klass.new)).to eq '"foobar"' end end it 'allows to dump JSON values' do expect(MultiJson.dump(42)).to eq '42' end it 'allows to dump JSON with UTF-8 characters' do expect(MultiJson.dump({'color' => 'żółć'})).to eq('{"color":"żółć"}') end end describe '.load' do describe '#load_options' do before{ MultiJson.load_options = MultiJson.adapter.load_options = {} } after do expect(MultiJson.adapter.instance).to receive(:load).with('1', :foo => 'bar', :fizz => 'buzz') MultiJson.load('1', :fizz => 'buzz') MultiJson.load_options = MultiJson.adapter.load_options = nil end it 'respects global load options' do MultiJson.load_options = {:foo => 'bar'} end it 'respects per-adapter load options' do MultiJson.adapter.load_options = {:foo => 'bar'} end it 'adapter-specific are overridden by global options' do MultiJson.adapter.load_options = {:foo => 'foo'} MultiJson.load_options = {:foo => 'bar'} end end it 'does not modify input' do input = %Q{\n\n {"foo":"bar"} \n\n\t} expect{ MultiJson.load(input) }.to_not change{ input } end # Ruby 1.8 doesn't support String encodings if RUBY_VERSION > '1.9' it 'does not modify input encoding' do input = '[123]' input.force_encoding('iso-8859-1') expect{ MultiJson.load(input) }.to_not change{ input.encoding } end end it 'properly loads valid JSON' do expect(MultiJson.load('{"abc":"def"}')).to eq({'abc' => 'def'}) end it 'raises MultiJson::LoadError on invalid JSON' do expect{MultiJson.load('{"abc"}')}.to raise_error(MultiJson::LoadError) end it 'raises MultiJson::LoadError on blank input' do [nil, ' ', "\t\t\t", "\n"].each do |input| expect{MultiJson.load(input)}.to raise_error(MultiJson::LoadError) end end it 'raises MultiJson::LoadError with data on invalid JSON' do data = '{invalid}' begin MultiJson.load(data) rescue MultiJson::LoadError => le expect(le.data).to eq data end end it 'catches MultiJson::DecodeError for legacy support' do data = '{invalid}' begin MultiJson.load(data) rescue MultiJson::DecodeError => de expect(de.data).to eq data end end it 'stringifys symbol keys when encoding' do dumped_json = MultiJson.dump(:a => 1, :b => {:c => 2}) loaded_json = MultiJson.load(dumped_json) expect(loaded_json).to eq({'a' => 1, 'b' => {'c' => 2}}) end it 'properly loads valid JSON in StringIOs' do json = StringIO.new('{"abc":"def"}') expect(MultiJson.load(json)).to eq({'abc' => 'def'}) end it 'allows for symbolization of keys' do [ [ '{"abc":{"def":"hgi"}}', {:abc => {:def => 'hgi'}}, ], [ '[{"abc":{"def":"hgi"}}]', [{:abc => {:def => 'hgi'}}], ], [ '{"abc":[{"def":"hgi"}]}', {:abc => [{:def => 'hgi'}]}, ], ].each do |example, expected| expect(MultiJson.load(example, :symbolize_keys => true)).to eq expected end end it 'allows to load JSON values' do expect(MultiJson.load('42')).to eq 42 end it 'allows to load JSON with UTF-8 characters' do expect(MultiJson.load('{"color":"żółć"}')).to eq({'color' => 'żółć'}) end end end multi_json-1.8.0/spec/shared/json_common_adapter.rb0000644000004100000410000000163612220127643022506 0ustar www-datawww-datashared_examples_for 'JSON-like adapter' do |adapter| before{ MultiJson.use adapter } describe '.dump' do before{ MultiJson.dump_options = MultiJson.adapter.dump_options = nil } describe 'with :pretty option set to true' do it 'passes default pretty options' do object = 'foo' expect(object).to receive(:to_json).with(JSON::PRETTY_STATE_PROTOTYPE.to_h) MultiJson.dump(object, :pretty => true) end end describe 'with :indent option' do it 'passes it on dump' do object = 'foo' expect(object).to receive(:to_json).with(:indent => "\t") MultiJson.dump(object, :indent => "\t") end end end describe '.load' do it 'passes :quirks_mode option' do expect(::JSON).to receive(:parse).with('[123]', {:quirks_mode => false, :create_additions => false}) MultiJson.load('[123]', :quirks_mode => false) end end end multi_json-1.8.0/spec/oj_adapter_spec.rb0000644000004100000410000000027612220127643020340 0ustar www-datawww-datarequire 'spec_helper' exit true if jruby? require 'shared/adapter' require 'multi_json/adapters/oj' describe MultiJson::Adapters::Oj do it_behaves_like 'an adapter', described_class endmulti_json-1.8.0/spec/json_pure_adapter_spec.rb0000644000004100000410000000042112220127643021724 0ustar www-datawww-datarequire 'spec_helper' require 'shared/adapter' require 'shared/json_common_adapter' require 'multi_json/adapters/json_pure' describe MultiJson::Adapters::JsonPure do it_behaves_like 'an adapter', described_class it_behaves_like 'JSON-like adapter', described_class endmulti_json-1.8.0/spec/yajl_adapter_spec.rb0000644000004100000410000000030212220127643020655 0ustar www-datawww-datarequire 'spec_helper' exit true if jruby? require 'shared/adapter' require 'multi_json/adapters/yajl' describe MultiJson::Adapters::Yajl do it_behaves_like 'an adapter', described_class endmulti_json-1.8.0/spec/multi_json_spec.rb0000644000004100000410000001414612220127643020414 0ustar www-datawww-datarequire 'spec_helper' require 'shared/options' describe MultiJson do before(:all) do # make sure all available libs are required MultiJson::REQUIREMENT_MAP.each do |library, adapter| begin require library rescue ::LoadError next end end end context 'when no other json implementations are available' do around do |example| simulate_no_adapters{ example.call } end it 'defaults to ok_json if no other json implementions are available' do silence_warnings do expect(MultiJson.default_adapter).to eq(:ok_json) end end it 'prints a warning' do expect(Kernel).to receive(:warn).with(/warning/i) MultiJson.default_adapter end end context 'caching' do before{ MultiJson.use adapter } let(:adapter){ MultiJson::Adapters::JsonGem } let(:json_string){ '{"abc":"def"}' } it 'busts caches on global options change' do MultiJson.load_options = { :symbolize_keys => true } expect(MultiJson.load(json_string)).to eq(:abc => 'def') MultiJson.load_options = nil expect(MultiJson.load(json_string)).to eq('abc' => 'def') end it 'busts caches on per-adapter options change' do adapter.load_options = { :symbolize_keys => true } expect(MultiJson.load(json_string)).to eq(:abc => 'def') adapter.load_options = nil expect(MultiJson.load(json_string)).to eq('abc' => 'def') end end it 'defaults to the best available gem' do # Clear cache variable already set by previous tests MultiJson.send(:remove_instance_variable, :@adapter) if MultiJson.instance_variable_defined?(:@adapter) if jruby? expect(MultiJson.adapter.to_s).to eq('MultiJson::Adapters::JrJackson') else expect(MultiJson.adapter.to_s).to eq('MultiJson::Adapters::Oj') end end it 'looks for adapter even if @adapter variable is nil' do MultiJson.send(:instance_variable_set, :@adapter, nil) expect(MultiJson).to receive(:default_adapter).and_return(:ok_json) expect(MultiJson.adapter).to eq(MultiJson::Adapters::OkJson) end it 'is settable via a symbol' do MultiJson.use :json_gem expect(MultiJson.adapter).to eq(MultiJson::Adapters::JsonGem) end it 'is settable via a class' do adapter = Class.new MultiJson.use adapter expect(MultiJson.adapter).to eq(adapter) end it 'is settable via a module' do adapter = Module.new MultiJson.use adapter expect(MultiJson.adapter).to eq(adapter) end it 'throws ArgumentError on bad input' do expect{ MultiJson.use 'bad adapter' }.to raise_error(ArgumentError) end context 'using one-shot parser' do before do expect(MultiJson::Adapters::JsonPure).to receive(:dump).once.and_return('dump_something') expect(MultiJson::Adapters::JsonPure).to receive(:load).once.and_return('load_something') end it 'should use the defined parser just for the call' do MultiJson.use :json_gem expect(MultiJson.dump('', :adapter => :json_pure)).to eq('dump_something') expect(MultiJson.load('', :adapter => :json_pure)).to eq('load_something') expect(MultiJson.adapter).to eq(MultiJson::Adapters::JsonGem) end end it 'can set adapter for a block' do MultiJson.use :ok_json MultiJson.with_adapter(:json_pure) do MultiJson.with_engine(:json_gem) do expect(MultiJson.adapter).to eq(MultiJson::Adapters::JsonGem) end expect(MultiJson.adapter).to eq(MultiJson::Adapters::JsonPure) end expect(MultiJson.adapter).to eq(MultiJson::Adapters::OkJson) end it 'JSON gem does not create symbols on parse' do MultiJson.with_engine(:json_gem) do MultiJson.load('{"json_class":"ZOMG"}') rescue nil expect{ MultiJson.load('{"json_class":"OMG"}') rescue nil }.to_not change{Symbol.all_symbols.count} end end unless jruby? it 'Oj does not create symbols on parse' do MultiJson.with_engine(:oj) do MultiJson.load('{"json_class":"ZOMG"}') rescue nil expect{ MultiJson.load('{"json_class":"OMG"}') rescue nil }.to_not change{Symbol.all_symbols.count} end end context 'with Oj.default_settings' do around do |example| options = Oj.default_options Oj.default_options = { :symbol_keys => true } MultiJson.with_engine(:oj){ example.call } Oj.default_options = options end it 'ignores global settings' do MultiJson.with_engine(:oj) do example = '{"a": 1, "b": 2}' expected = { 'a' => 1, 'b' => 2 } expect(MultiJson.load(example)).to eq(expected) end end end end describe 'default options' do after(:all){ MultiJson.load_options = MultiJson.dump_options = nil } it 'is deprecated' do expect(Kernel).to receive(:warn).with(/deprecated/i) silence_warnings{ MultiJson.default_options = {:foo => 'bar'} } end it 'sets both load and dump options' do expect(MultiJson).to receive(:dump_options=).with(:foo => 'bar') expect(MultiJson).to receive(:load_options=).with(:foo => 'bar') silence_warnings{ MultiJson.default_options = {:foo => 'bar'} } end end it_behaves_like 'has options', MultiJson # %w(gson jr_jackson json_gem json_pure nsjsonserialization oj ok_json yajl).each do |adapter| # next if !jruby? && %w(gson jr_jackson).include?(adapter) # next if !macruby? && adapter == 'nsjsonserialization' # next if jruby? && %w(oj yajl).include?(adapter) # context adapter do # it_behaves_like 'an adapter', adapter # end # end # %w(json_gem json_pure).each do |adapter| # context adapter do # it_behaves_like 'JSON-like adapter', adapter # end # end describe 'aliases' do if jruby? describe 'jrjackson' do after{ expect(MultiJson.adapter).to eq(MultiJson::Adapters::JrJackson) } it 'allows jrjackson alias as symbol' do expect{ MultiJson.use :jrjackson }.not_to raise_error end it 'allows jrjackson alias as string' do expect{ MultiJson.use 'jrjackson' }.not_to raise_error end end end end end multi_json-1.8.0/spec/ok_json_adapter_spec.rb0000644000004100000410000000026112220127643021364 0ustar www-datawww-datarequire 'spec_helper' require 'shared/adapter' require 'multi_json/adapters/ok_json' describe MultiJson::Adapters::OkJson do it_behaves_like 'an adapter', described_class endmulti_json-1.8.0/spec/gson_adapter_spec.rb0000644000004100000410000000030612220127643020670 0ustar www-datawww-datarequire 'spec_helper' exit true unless jruby? require 'shared/adapter' require 'multi_json/adapters/gson' describe MultiJson::Adapters::Gson do it_behaves_like 'an adapter', described_class endmulti_json-1.8.0/spec/nsjsonserialization_adapter_spec.rb0000644000004100000410000000034612220127643024036 0ustar www-datawww-datarequire 'spec_helper' exit true unless macruby? require 'shared/adapter' require 'multi_json/adapters/nsjsonserialization' describe MultiJson::Adapters::Nsjsonserialization do it_behaves_like 'an adapter', described_class endmulti_json-1.8.0/spec/spec_helper.rb0000644000004100000410000000264312220127643017507 0ustar www-datawww-datarequire 'simplecov' # require 'coveralls' # SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[ # SimpleCov::Formatter::HTMLFormatter, # Coveralls::SimpleCov::Formatter # ] # SimpleCov.start do # add_filter 'spec' # add_filter 'vendor' # end require 'multi_json' require 'rspec' RSpec.configure do |config| config.expect_with :rspec do |c| c.syntax = :expect end end def silence_warnings old_verbose, $VERBOSE = $VERBOSE, nil yield ensure $VERBOSE = old_verbose end def macruby? defined?(RUBY_ENGINE) && RUBY_ENGINE == 'macruby' end def jruby? defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' end def undefine_constants(*consts) values = {} consts.each do |const| if Object.const_defined?(const) values[const] = Object.const_get(const) Object.send :remove_const, const end end yield ensure values.each do |const, value| Object.const_set const, value end end def break_requirements requirements = MultiJson::REQUIREMENT_MAP MultiJson::REQUIREMENT_MAP.each_with_index do |(library, adapter), index| MultiJson::REQUIREMENT_MAP[index] = ["foo/#{library}", adapter] end yield ensure requirements.each_with_index do |(library, adapter), index| MultiJson::REQUIREMENT_MAP[index] = [library, adapter] end end def simulate_no_adapters break_requirements do undefine_constants :JSON, :Oj, :Yajl, :Gson, :JrJackson do yield end end endmulti_json-1.8.0/spec/json_gem_adapter_spec.rb0000644000004100000410000000041712220127643021526 0ustar www-datawww-datarequire 'spec_helper' require 'shared/adapter' require 'shared/json_common_adapter' require 'multi_json/adapters/json_gem' describe MultiJson::Adapters::JsonGem do it_behaves_like 'an adapter', described_class it_behaves_like 'JSON-like adapter', described_class endmulti_json-1.8.0/spec/jr_jackson_adapter_spec.rb0000644000004100000410000000032112220127643022042 0ustar www-datawww-datarequire 'spec_helper' exit true unless jruby? require 'shared/adapter' require 'multi_json/adapters/jr_jackson' describe MultiJson::Adapters::JrJackson do it_behaves_like 'an adapter', described_class endmulti_json-1.8.0/.rspec0000644000004100000410000000004312220127643015044 0ustar www-datawww-data--color --fail-fast --order random multi_json-1.8.0/checksums.yaml.gz0000444000004100000410000000041412220127643017217 0ustar www-datawww-data$,Re)V@ }O L:dW"Evy{z쇗?~m1*^ - !ruby/object:Gem::Version version: '1.0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '1.0' description: A common interface to multiple JSON libraries, including Oj, Yajl, the JSON gem (with C-extensions), the pure-Ruby JSON gem, NSJSONSerialization, gson.rb, JrJackson, and OkJson. email: - michael@intridea.com - josh.kalderimis@gmail.com - sferik@gmail.com executables: [] extensions: [] extra_rdoc_files: [] files: - .yardopts - CHANGELOG.md - CONTRIBUTING.md - LICENSE.md - README.md - Rakefile - multi_json.gemspec - Gemfile - .document - .rspec - .travis.yml - spec/gson_adapter_spec.rb - spec/jr_jackson_adapter_spec.rb - spec/json_gem_adapter_spec.rb - spec/json_pure_adapter_spec.rb - spec/multi_json_spec.rb - spec/nsjsonserialization_adapter_spec.rb - spec/oj_adapter_spec.rb - spec/ok_json_adapter_spec.rb - spec/shared/adapter.rb - spec/shared/json_common_adapter.rb - spec/shared/options.rb - spec/spec_helper.rb - spec/yajl_adapter_spec.rb - lib/multi_json/adapter.rb - lib/multi_json/adapters/gson.rb - lib/multi_json/adapters/jr_jackson.rb - lib/multi_json/adapters/json_common.rb - lib/multi_json/adapters/json_gem.rb - lib/multi_json/adapters/json_pure.rb - lib/multi_json/adapters/nsjsonserialization.rb - lib/multi_json/adapters/oj.rb - lib/multi_json/adapters/ok_json.rb - lib/multi_json/adapters/yajl.rb - lib/multi_json/convertible_hash_keys.rb - lib/multi_json/load_error.rb - lib/multi_json/options.rb - lib/multi_json/vendor/okjson.rb - lib/multi_json/version.rb - lib/multi_json.rb homepage: http://github.com/intridea/multi_json licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 1.3.5 requirements: [] rubyforge_project: rubygems_version: 2.0.7 signing_key: specification_version: 4 summary: A common interface to multiple JSON libraries. test_files: - spec/gson_adapter_spec.rb - spec/jr_jackson_adapter_spec.rb - spec/json_gem_adapter_spec.rb - spec/json_pure_adapter_spec.rb - spec/multi_json_spec.rb - spec/nsjsonserialization_adapter_spec.rb - spec/oj_adapter_spec.rb - spec/ok_json_adapter_spec.rb - spec/shared/adapter.rb - spec/shared/json_common_adapter.rb - spec/shared/options.rb - spec/spec_helper.rb - spec/yajl_adapter_spec.rb has_rdoc: multi_json-1.8.0/metadata.gz.sig0000444000004100000410000000040012220127643016625 0ustar www-datawww-datahתB`^!_}HP1լMr#O啩xu )x/ 5`3DdUۉZJy9Ԟ:Dky'kpȦ2Ŷ(Hu{AwHk.= CPFS$@4LahZԆMH!PJ.s5{iۑXz7A~ɣPn6>a?}ž.l8NO5V'm$|U#ӟ[EDHle엘multi_json-1.8.0/.yardopts0000644000004100000410000000010612220127643015575 0ustar www-datawww-data--markup markdown - CHANGELOG.md CONTRIBUTING.md LICENSE.md README.md multi_json-1.8.0/CHANGELOG.md0000644000004100000410000002154112220127643015546 0ustar www-datawww-data1.7.8 ----- * [Reorder JrJackson before json_gem](https://github.com/intridea/multi_json/commit/315b6e460b6e4dcdb6c82e04e4be8ee975d395da) * [Update vendored OkJson to version 43](https://github.com/intridea/multi_json/commit/99a6b662f6ef4036e3ee94d7eb547fa72fb2ab50) 1.7.7 ----- * [Fix options caching issues](https://github.com/intridea/multi_json/commit/a3f14c3661688c5927638fa6088c7b46a67e875e) 1.7.6 ----- * [Bring back MultiJson::VERSION constant](https://github.com/intridea/multi_json/commit/31b990c2725e6673bf8ce57540fe66b57a751a72) 1.7.5 ----- * [Fix warning '*' interpreted as argument prefix](https://github.com/intridea/multi_json/commit/b698962c7f64430222a1f06430669706a47aff89) * [Remove stdlib warning](https://github.com/intridea/multi_json/commit/d06eec6b7996ac8b4ff0e2229efd835379b0c30f) 1.7.4 ----- * [Cache options for better performance](https://github.com/intridea/multi_json/commit/8a26ee93140c4bed36194ed9fb887a1b6919257b) 1.7.3 ----- * [Require json/ext to ensure extension version gets loaded for json_gem](https://github.com/intridea/multi_json/commit/942686f7e8597418c6f90ee69e1d45242fac07b1) * [Rename JrJackson](https://github.com/intridea/multi_json/commit/078de7ba8b6035343c3e96b4767549e9ec43369a) * [Prefer JrJackson to JSON gem if present](https://github.com/intridea/multi_json/commit/af8bd9799a66855f04b3aff1c488485950cec7bf) * [Print a warning if outdated gem versions are used](https://github.com/intridea/multi_json/commit/e7438e7ba2be0236cfa24c2bb9ad40ee821286d1) * [Loosen required_rubygems_version for compatibility with Ubuntu 10.04](https://github.com/intridea/multi_json/commit/59fad014e8fe41dbc6f09485ea0dc21fc42fd7a7) 1.7.2 ----- * [Rename Jrjackson adapter to JrJackson](https://github.com/intridea/multi_json/commit/b36dc915fc0e6548cbad06b5db6f520e040c9c8b) * [Implement jrjackson -> jr_jackson alias for back-compatability](https://github.com/intridea/multi_json/commit/aa50ab8b7bb646b8b75d5d65dfeadae8248a4f10) * [Update vendored OkJson module](https://github.com/intridea/multi_json/commit/30a3f474e17dd86a697c3fab04f468d1a4fd69d7) 1.7.1 ----- * [Fix capitalization of JrJackson class](https://github.com/intridea/multi_json/commit/5373a5e38c647f02427a0477cb8e0e0dafad1b8d) 1.7.0 ----- * [Add load_options/dump_options to MultiJson](https://github.com/intridea/multi_json/commit/a153956be6b0df06ea1705ce3c1ff0b5b0e27ea5) * [MultiJson does not modify arguments](https://github.com/intridea/multi_json/commit/58525b01c4c2f6635ba2ac13d6fd987b79f3962f) * [Enable quirks_mode by default for json_gem/json_pure adapters](https://github.com/intridea/multi_json/commit/1fd4e6635c436515b7d7d5a0bee4548de8571520) * [Add JrJackson adapter](https://github.com/intridea/multi_json/commit/4dd86fa96300aaaf6d762578b9b31ea82adb056d) * [Raise ArgumentError on bad adapter input](https://github.com/intridea/multi_json/commit/911a3756bdff2cb5ac06497da3fa3e72199cb7ad) 1.6.1 ----- * [Revert "Use JSON.generate instead of #to_json"](https://github.com/intridea/multi_json/issues/86) 1.6.0 ----- * [Add gson.rb support](https://github.com/intridea/multi_json/pull/71) * [Add MultiJson.default_options](https://github.com/intridea/multi_json/pull/70) * [Add MultiJson.with_adapter](https://github.com/intridea/multi_json/pull/67) * [Stringify all possible keys for ok_json](https://github.com/intridea/multi_json/pull/66) * [Use JSON.generate instead of #to_json](https://github.com/intridea/multi_json/issues/73) * [Alias `MultiJson::DecodeError` to `MultiJson::LoadError`](https://github.com/intridea/multi_json/pull/79) 1.5.1 ----- * [Do not allow Oj or JSON to create symbols by searching for classes](https://github.com/intridea/multi_json/commit/193e28cf4dc61b6e7b7b7d80f06f74c76df65c41) 1.5.0 ----- * [Add `MultiJson.with_adapter` method](https://github.com/intridea/multi_json/commit/d14c5d28cae96557a0421298621b9499e1f28104) * [Stringify all possible keys for `ok_json`](https://github.com/intridea/multi_json/commit/73998074058e1e58c557ffa7b9541d486d6041fa) 1.4.0 ----- * [Allow `load`/`dump` of JSON fragments](https://github.com/intridea/multi_json/commit/707aae7d48d39c85b38febbd2c210ba87f6e4a36) 1.3.7 ----- * [Fix rescue clause for MagLev](https://github.com/intridea/multi_json/commit/39abdf50199828c50e85b2ce8f8ba31fcbbc9332) * [Remove unnecessary check for string version of options key](https://github.com/intridea/multi_json/commit/660101b70e962b3c007d0b90d45944fa47d13ec4) * [Explicitly set default adapter when adapter is set to `nil` or `false`](https://github.com/intridea/multi_json/commit/a9e587d5a63eafb4baee9fb211265e4dd96a26bc) * [Fix Oj `ParseError` mapping for Oj 1.4.0](https://github.com/intridea/multi_json/commit/7d9045338cc9029401c16f3c409d54ce97f275e2) 1.3.6 ----- * [Allow adapter-specific options to be passed through to Oj](https://github.com/intridea/multi_json/commit/d0e5feeebcba0bc69400dd203a295f5c30971223) 1.3.5 ----- * [Add pretty support to Oj adapter](https://github.com/intridea/multi_json/commit/0c8f75f03020c53bcf4c6be258faf433d24b2c2b) 1.3.4 ----- * [Use `class << self` instead of `module_function` to create aliases](https://github.com/intridea/multi_json/commit/ba1451c4c48baa297e049889be241a424cb05980) 1.3.3 ----- * [Remove deprecation warnings](https://github.com/intridea/multi_json/commit/36b524e71544eb0186826a891bcc03b2820a008f) 1.3.2 ----- * [Add ability to use adapter per call](https://github.com/intridea/multi_json/commit/106bbec469d5d0a832bfa31fffcb8c0f0cdc9bd3) * [Add and deprecate `default_engine` method](https://github.com/intridea/multi_json/commit/fc3df0c7a3e2ab9ce0c2c7e7617a4da97dd13f6e) 1.3.1 ----- * [Only warn once for each instance a deprecated method is called](https://github.com/intridea/multi_json/commit/e21d6eb7da74b3f283995c1d27d5880e75f0ae84) 1.3.0 ----- * [Implement `load`/`dump`; deprecate `decode`/`encode`](https://github.com/intridea/multi_json/commit/e90fd6cb1b0293eb0c73c2f4eb0f7a1764370216) * [Rename engines to adapters](https://github.com/intridea/multi_json/commit/ae7fd144a7949a9c221dcaa446196ec23db908df) 1.2.0 ----- * [Add support for Oj](https://github.com/intridea/multi_json/commit/acd06b233edabe6c44f226873db7b49dab560c60) 1.1.0 ----- * [`NSJSONSerialization` support for MacRuby](https://github.com/intridea/multi_json/commit/f862e2fc966cac8867fe7da3997fc76e8a6cf5d4) 1.0.4 ----- * [Set data context to `DecodeError` exception](https://github.com/intridea/multi_json/commit/19ddafd44029c6681f66fae2a0f6eabfd0f85176) * [Allow `ok_json` to fallback to `to_json`](https://github.com/intridea/multi_json/commit/c157240b1193b283d06d1bd4d4b5b06bcf3761f8) * [Add warning when using `ok_json`](https://github.com/intridea/multi_json/commit/dd4b68810c84f826fb98f9713bfb29ab96888d57) * [Options can be passed to an engine on encode](https://github.com/intridea/multi_json/commit/e0a7ff5d5ff621ffccc61617ed8aeec5816e81f7) 1.0.3 ----- * [`Array` support for `stringify_keys`](https://github.com/intridea/multi_json/commit/644d1c5c7c7f6a27663b11668527b346094e38b9) * [`Array` support for `symbolize_keys`](https://github.com/intridea/multi_json/commit/c885377d47a2aa39cb0d971fea78db2d2fa479a7) 1.0.2 ----- * [Allow encoding of rootless JSON when `ok_json` is used](https://github.com/intridea/multi_json/commit/d1cde7de97cb0f6152aef8daf14037521cdce8c6) 1.0.1 ----- * [Correct an issue with `ok_json` not being returned as the default engine](https://github.com/intridea/multi_json/commit/d33c141619c54cccd770199694da8fd1bd8f449d) 1.0.0 ----- * [Remove `ActiveSupport::JSON` support](https://github.com/intridea/multi_json/commit/c2f4140141d785a24b3f56e58811b0e561b37f6a) * [Fix `@engine` ivar warning](https://github.com/intridea/multi_json/commit/3b978a8995721a8dffedc3b75a7f49e5494ec553) * [Only `rescue` from parsing errors during decoding, not any `StandardError`](https://github.com/intridea/multi_json/commit/391d00b5e85294d42d41347605d8d46b4a7f66cc) * [Rename `okjson` engine and vendored lib to `ok_json`](https://github.com/intridea/multi_json/commit/5bd1afc977a8208ddb0443e1d57cb79665c019f1) * [Add `StringIO` support to `json` gem and `ok_json`](https://github.com/intridea/multi_json/commit/1706b11568db7f50af451fce5f4d679aeb3bbe8f) 0.0.5 ----- * [Trap all JSON decoding errors; raise `MultiJson::DecodeError`](https://github.com/intridea/multi_json/commit/dea9a1aef6dd1212aa1e5a37ab1669f9b045b732) 0.0.4 ----- * [Fix default_engine check for `json` gem](https://github.com/intridea/multi_json/commit/caced0c4e8c795922a109ebc00c3c4fa8635bed8) * [Make requirement mapper an `Array` to preserve order in Ruby versions < 1.9](https://github.com/intridea/multi_json/commit/526f5f29a42131574a088ad9bbb43d7f48439b2c) 0.0.3 ----- * [Improve defaulting and documentation](https://github.com/sferik/twitter/commit/3a0e41b9e4b0909201045fa47704b78c9d949b73) 0.0.2 ----- * [Rename to `multi_json`](https://github.com/sferik/twitter/commit/461ab89ce071c8c9fabfc183581e0ec523788b62) 0.0.1 ----- * [Initial commit](https://github.com/sferik/twitter/commit/518c21ab299c500527491e6c049ab2229e22a805) multi_json-1.8.0/Gemfile0000644000004100000410000000116712220127643015232 0ustar www-datawww-datasource 'https://rubygems.org' gem 'rake', '>= 0.9' gem 'yard', '>= 0.8' gem 'json', '~> 1.4', :require => nil gem 'json_pure', '~> 1.4', :require => nil platforms :ruby, :mswin, :mingw do gem 'oj', '~> 2.0', :require => nil gem 'yajl-ruby', '~> 1.0', :require => nil end platforms :jruby do gem 'gson', '>= 0.6', :require => nil gem 'jrjackson', '~> 0.1.1', :require => nil end group :development do gem 'kramdown', '>= 0.14' gem 'pry' gem 'pry-debugger', :platforms => :mri end group :test do gem 'coveralls', :require => false gem 'rspec', '>= 2.14' gem 'simplecov', :require => false end gemspec multi_json-1.8.0/data.tar.gz.sig0000444000004100000410000000040012220127643016543 0ustar www-datawww-data D;TͶ+^ A#LBHP+-,-g:d5ĘlB}|m\0N;}rϜW!E->{'fP,t !US8^TD:cg;3(D| K4 2/̺K-:HJ6_wEz魝s)p[: P Ht(<&Fypm,=5Ǟ(4~"bWzmulti_json-1.8.0/lib/0000755000004100000410000000000012220127643014500 5ustar www-datawww-datamulti_json-1.8.0/lib/multi_json/0000755000004100000410000000000012220127643016663 5ustar www-datawww-datamulti_json-1.8.0/lib/multi_json/version.rb0000644000004100000410000000065712220127643020705 0ustar www-datawww-datamodule MultiJson class Version MAJOR = 1 unless defined? MultiJson::Version::MAJOR MINOR = 8 unless defined? MultiJson::Version::MINOR PATCH = 0 unless defined? MultiJson::Version::PATCH PRE = nil unless defined? MultiJson::Version::PRE class << self # @return [String] def to_s [MAJOR, MINOR, PATCH, PRE].compact.join('.') end end end VERSION = Version.to_s.freeze end multi_json-1.8.0/lib/multi_json/options.rb0000644000004100000410000000173712220127643020713 0ustar www-datawww-datamodule MultiJson module Options def load_options=(options) MultiJson.reset_cached_options! @load_options = options end def dump_options=(options) MultiJson.reset_cached_options! @dump_options = options end def load_options(*args) get_options :load_options, *args end def dump_options(*args) get_options :dump_options, *args end def default_load_options @default_load_options ||= {} end def default_dump_options @default_dump_options ||= {} end private def get_options(ivar, *args) defaults = send("default_#{ivar}") return defaults unless instance_variable_defined?("@#{ivar}") value = instance_variable_get("@#{ivar}") if value.respond_to?(:call) and value.arity value.arity == 0 ? value[] : value[*args] elsif Hash === value or value.respond_to?(:to_hash) value.to_hash else defaults end end end end multi_json-1.8.0/lib/multi_json/vendor/0000755000004100000410000000000012220127643020160 5ustar www-datawww-datamulti_json-1.8.0/lib/multi_json/vendor/okjson.rb0000644000004100000410000003551212220127643022016 0ustar www-datawww-data# encoding: UTF-8 # # Copyright 2011, 2012 Keith Rarick # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # See https://github.com/kr/okjson for updates. require 'stringio' module MultiJson # Some parts adapted from # http://golang.org/src/pkg/json/decode.go and # http://golang.org/src/pkg/utf8/utf8.go module OkJson Upstream = '43' extend self # Decodes a json document in string s and # returns the corresponding ruby value. # String s must be valid UTF-8. If you have # a string in some other encoding, convert # it first. # # String values in the resulting structure # will be UTF-8. def decode(s) ts = lex(s) v, ts = textparse(ts) if ts.length > 0 raise Error, 'trailing garbage' end v end # Encodes x into a json text. It may contain only # Array, Hash, String, Numeric, true, false, nil. # (Note, this list excludes Symbol.) # X itself must be an Array or a Hash. # No other value can be encoded, and an error will # be raised if x contains any other value, such as # Nan, Infinity, Symbol, and Proc, or if a Hash key # is not a String. # Strings contained in x must be valid UTF-8. def encode(x) case x when Hash then objenc(x) when Array then arrenc(x) else raise Error, 'root value must be an Array or a Hash' end end def valenc(x) case x when Hash then objenc(x) when Array then arrenc(x) when String then strenc(x) when Numeric then numenc(x) when true then "true" when false then "false" when nil then "null" else if x.respond_to?(:to_json) x.to_json else raise Error, "cannot encode #{x.class}: #{x.inspect}" end end end private # Parses a "json text" in the sense of RFC 4627. # Returns the parsed value and any trailing tokens. # Note: this is almost the same as valparse, # except that it does not accept atomic values. def textparse(ts) if ts.length <= 0 raise Error, 'empty' end typ, _, val = ts[0] case typ when '{' then objparse(ts) when '[' then arrparse(ts) else raise Error, "unexpected #{val.inspect}" end end # Parses a "value" in the sense of RFC 4627. # Returns the parsed value and any trailing tokens. def valparse(ts) if ts.length <= 0 raise Error, 'empty' end typ, _, val = ts[0] case typ when '{' then objparse(ts) when '[' then arrparse(ts) when :val,:str then [val, ts[1..-1]] else raise Error, "unexpected #{val.inspect}" end end # Parses an "object" in the sense of RFC 4627. # Returns the parsed value and any trailing tokens. def objparse(ts) ts = eat('{', ts) obj = {} if ts[0][0] == '}' return obj, ts[1..-1] end k, v, ts = pairparse(ts) obj[k] = v if ts[0][0] == '}' return obj, ts[1..-1] end loop do ts = eat(',', ts) k, v, ts = pairparse(ts) obj[k] = v if ts[0][0] == '}' return obj, ts[1..-1] end end end # Parses a "member" in the sense of RFC 4627. # Returns the parsed values and any trailing tokens. def pairparse(ts) (typ, _, k), ts = ts[0], ts[1..-1] if typ != :str raise Error, "unexpected #{k.inspect}" end ts = eat(':', ts) v, ts = valparse(ts) [k, v, ts] end # Parses an "array" in the sense of RFC 4627. # Returns the parsed value and any trailing tokens. def arrparse(ts) ts = eat('[', ts) arr = [] if ts[0][0] == ']' return arr, ts[1..-1] end v, ts = valparse(ts) arr << v if ts[0][0] == ']' return arr, ts[1..-1] end loop do ts = eat(',', ts) v, ts = valparse(ts) arr << v if ts[0][0] == ']' return arr, ts[1..-1] end end end def eat(typ, ts) if ts[0][0] != typ raise Error, "expected #{typ} (got #{ts[0].inspect})" end ts[1..-1] end # Scans s and returns a list of json tokens, # excluding white space (as defined in RFC 4627). def lex(s) ts = [] while s.length > 0 typ, lexeme, val = tok(s) if typ == nil raise Error, "invalid character at #{s[0,10].inspect}" end if typ != :space ts << [typ, lexeme, val] end s = s[lexeme.length..-1] end ts end # Scans the first token in s and # returns a 3-element list, or nil # if s does not begin with a valid token. # # The first list element is one of # '{', '}', ':', ',', '[', ']', # :val, :str, and :space. # # The second element is the lexeme. # # The third element is the value of the # token for :val and :str, otherwise # it is the lexeme. def tok(s) case s[0] when ?{ then ['{', s[0,1], s[0,1]] when ?} then ['}', s[0,1], s[0,1]] when ?: then [':', s[0,1], s[0,1]] when ?, then [',', s[0,1], s[0,1]] when ?[ then ['[', s[0,1], s[0,1]] when ?] then [']', s[0,1], s[0,1]] when ?n then nulltok(s) when ?t then truetok(s) when ?f then falsetok(s) when ?" then strtok(s) when Spc, ?\t, ?\n, ?\r then [:space, s[0,1], s[0,1]] else numtok(s) end end def nulltok(s); s[0,4] == 'null' ? [:val, 'null', nil] : [] end def truetok(s); s[0,4] == 'true' ? [:val, 'true', true] : [] end def falsetok(s); s[0,5] == 'false' ? [:val, 'false', false] : [] end def numtok(s) m = /-?([1-9][0-9]+|[0-9])([.][0-9]+)?([eE][+-]?[0-9]+)?/.match(s) if m && m.begin(0) == 0 if !m[2] && !m[3] [:val, m[0], Integer(m[0])] elsif m[2] [:val, m[0], Float(m[0])] else [:val, m[0], Integer(m[1])*(10**Integer(m[3][1..-1]))] end else [] end end def strtok(s) m = /"([^"\\]|\\["\/\\bfnrt]|\\u[0-9a-fA-F]{4})*"/.match(s) if ! m raise Error, "invalid string literal at #{abbrev(s)}" end [:str, m[0], unquote(m[0])] end def abbrev(s) t = s[0,10] p = t['`'] t = t[0,p] if p t = t + '...' if t.length < s.length '`' + t + '`' end # Converts a quoted json string literal q into a UTF-8-encoded string. # The rules are different than for Ruby, so we cannot use eval. # Unquote will raise an error if q contains control characters. def unquote(q) q = q[1...-1] a = q.dup # allocate a big enough string # In ruby >= 1.9, a[w] is a codepoint, not a byte. if rubydoesenc? a.force_encoding('UTF-8') end r, w = 0, 0 while r < q.length c = q[r] if c == ?\\ r += 1 if r >= q.length raise Error, "string literal ends with a \"\\\": \"#{q}\"" end case q[r] when ?",?\\,?/,?' a[w] = q[r] r += 1 w += 1 when ?b,?f,?n,?r,?t a[w] = Unesc[q[r]] r += 1 w += 1 when ?u r += 1 uchar = begin hexdec4(q[r,4]) rescue RuntimeError => e raise Error, "invalid escape sequence \\u#{q[r,4]}: #{e}" end r += 4 if surrogate? uchar if q.length >= r+6 uchar1 = hexdec4(q[r+2,4]) uchar = subst(uchar, uchar1) if uchar != Ucharerr # A valid pair; consume. r += 6 end end end if rubydoesenc? a[w] = '' << uchar w += 1 else w += ucharenc(a, w, uchar) end else raise Error, "invalid escape char #{q[r]} in \"#{q}\"" end elsif c == ?" || c < Spc raise Error, "invalid character in string literal \"#{q}\"" else # Copy anything else byte-for-byte. # Valid UTF-8 will remain valid UTF-8. # Invalid UTF-8 will remain invalid UTF-8. # In ruby >= 1.9, c is a codepoint, not a byte, # in which case this is still what we want. a[w] = c r += 1 w += 1 end end a[0,w] end # Encodes unicode character u as UTF-8 # bytes in string a at position i. # Returns the number of bytes written. def ucharenc(a, i, u) if u <= Uchar1max a[i] = (u & 0xff).chr 1 elsif u <= Uchar2max a[i+0] = (Utag2 | ((u>>6)&0xff)).chr a[i+1] = (Utagx | (u&Umaskx)).chr 2 elsif u <= Uchar3max a[i+0] = (Utag3 | ((u>>12)&0xff)).chr a[i+1] = (Utagx | ((u>>6)&Umaskx)).chr a[i+2] = (Utagx | (u&Umaskx)).chr 3 else a[i+0] = (Utag4 | ((u>>18)&0xff)).chr a[i+1] = (Utagx | ((u>>12)&Umaskx)).chr a[i+2] = (Utagx | ((u>>6)&Umaskx)).chr a[i+3] = (Utagx | (u&Umaskx)).chr 4 end end def hexdec4(s) if s.length != 4 raise Error, 'short' end (nibble(s[0])<<12) | (nibble(s[1])<<8) | (nibble(s[2])<<4) | nibble(s[3]) end def subst(u1, u2) if Usurr1 <= u1 && u1 < Usurr2 && Usurr2 <= u2 && u2 < Usurr3 return ((u1-Usurr1)<<10) | (u2-Usurr2) + Usurrself end return Ucharerr end def surrogate?(u) Usurr1 <= u && u < Usurr3 end def nibble(c) if ?0 <= c && c <= ?9 then c.ord - ?0.ord elsif ?a <= c && c <= ?z then c.ord - ?a.ord + 10 elsif ?A <= c && c <= ?Z then c.ord - ?A.ord + 10 else raise Error, "invalid hex code #{c}" end end def objenc(x) '{' + x.map{|k,v| keyenc(k) + ':' + valenc(v)}.join(',') + '}' end def arrenc(a) '[' + a.map{|x| valenc(x)}.join(',') + ']' end def keyenc(k) case k when String then strenc(k) else raise Error, "Hash key is not a string: #{k.inspect}" end end def strenc(s) t = StringIO.new t.putc(?") r = 0 while r < s.length case s[r] when ?" then t.print('\\"') when ?\\ then t.print('\\\\') when ?\b then t.print('\\b') when ?\f then t.print('\\f') when ?\n then t.print('\\n') when ?\r then t.print('\\r') when ?\t then t.print('\\t') else c = s[r] # In ruby >= 1.9, s[r] is a codepoint, not a byte. if rubydoesenc? begin # c.ord will raise an error if c is invalid UTF-8 if c.ord < Spc.ord c = "\\u%04x" % [c.ord] end t.write(c) rescue t.write(Ustrerr) end elsif c < Spc t.write("\\u%04x" % c) elsif Spc <= c && c <= ?~ t.putc(c) else n = ucharcopy(t, s, r) # ensure valid UTF-8 output r += n - 1 # r is incremented below end end r += 1 end t.putc(?") t.string end def numenc(x) if ((x.nan? || x.infinite?) rescue false) raise Error, "Numeric cannot be represented: #{x}" end "#{x}" end # Copies the valid UTF-8 bytes of a single character # from string s at position i to I/O object t, and # returns the number of bytes copied. # If no valid UTF-8 char exists at position i, # ucharcopy writes Ustrerr and returns 1. def ucharcopy(t, s, i) n = s.length - i raise Utf8Error if n < 1 c0 = s[i].ord # 1-byte, 7-bit sequence? if c0 < Utagx t.putc(c0) return 1 end raise Utf8Error if c0 < Utag2 # unexpected continuation byte? raise Utf8Error if n < 2 # need continuation byte c1 = s[i+1].ord raise Utf8Error if c1 < Utagx || Utag2 <= c1 # 2-byte, 11-bit sequence? if c0 < Utag3 raise Utf8Error if ((c0&Umask2)<<6 | (c1&Umaskx)) <= Uchar1max t.putc(c0) t.putc(c1) return 2 end # need second continuation byte raise Utf8Error if n < 3 c2 = s[i+2].ord raise Utf8Error if c2 < Utagx || Utag2 <= c2 # 3-byte, 16-bit sequence? if c0 < Utag4 u = (c0&Umask3)<<12 | (c1&Umaskx)<<6 | (c2&Umaskx) raise Utf8Error if u <= Uchar2max t.putc(c0) t.putc(c1) t.putc(c2) return 3 end # need third continuation byte raise Utf8Error if n < 4 c3 = s[i+3].ord raise Utf8Error if c3 < Utagx || Utag2 <= c3 # 4-byte, 21-bit sequence? if c0 < Utag5 u = (c0&Umask4)<<18 | (c1&Umaskx)<<12 | (c2&Umaskx)<<6 | (c3&Umaskx) raise Utf8Error if u <= Uchar3max t.putc(c0) t.putc(c1) t.putc(c2) t.putc(c3) return 4 end raise Utf8Error rescue Utf8Error t.write(Ustrerr) return 1 end def rubydoesenc? ::String.method_defined?(:force_encoding) end class Utf8Error < ::StandardError end class Error < ::StandardError end Utagx = 0b1000_0000 Utag2 = 0b1100_0000 Utag3 = 0b1110_0000 Utag4 = 0b1111_0000 Utag5 = 0b1111_1000 Umaskx = 0b0011_1111 Umask2 = 0b0001_1111 Umask3 = 0b0000_1111 Umask4 = 0b0000_0111 Uchar1max = (1<<7) - 1 Uchar2max = (1<<11) - 1 Uchar3max = (1<<16) - 1 Ucharerr = 0xFFFD # unicode "replacement char" Ustrerr = "\xef\xbf\xbd" # unicode "replacement char" Usurrself = 0x10000 Usurr1 = 0xd800 Usurr2 = 0xdc00 Usurr3 = 0xe000 Spc = ' '[0] Unesc = {?b=>?\b, ?f=>?\f, ?n=>?\n, ?r=>?\r, ?t=>?\t} end end multi_json-1.8.0/lib/multi_json/adapters/0000755000004100000410000000000012220127643020466 5ustar www-datawww-datamulti_json-1.8.0/lib/multi_json/adapters/yajl.rb0000644000004100000410000000066112220127643021755 0ustar www-datawww-datarequire 'yajl' require 'multi_json/adapter' module MultiJson module Adapters # Use the Yajl-Ruby library to dump/load. class Yajl < Adapter ParseError = ::Yajl::ParseError def load(string, options={}) ::Yajl::Parser.new(:symbolize_keys => options[:symbolize_keys]).parse(string) end def dump(object, options={}) ::Yajl::Encoder.encode(object, options) end end end end multi_json-1.8.0/lib/multi_json/adapters/jr_jackson.rb0000644000004100000410000000070312220127643023136 0ustar www-datawww-datarequire 'jrjackson' unless defined?(::JrJackson) require 'multi_json/adapter' module MultiJson module Adapters # Use the jrjackson.rb library to dump/load. class JrJackson < Adapter ParseError = ::JrJackson::ParseError def load(string, options={}) #:nodoc: ::JrJackson::Json.load(string, options) end def dump(object, options={}) #:nodoc: ::JrJackson::Json.dump(object) end end end end multi_json-1.8.0/lib/multi_json/adapters/oj.rb0000644000004100000410000000121012220127643021415 0ustar www-datawww-datarequire 'oj' require 'multi_json/adapter' module MultiJson module Adapters # Use the Oj library to dump/load. class Oj < Adapter defaults :load, :mode => :strict, :symbolize_keys => false defaults :dump, :mode => :compat, :time_format => :ruby ParseError = defined?(::Oj::ParseError) ? ::Oj::ParseError : SyntaxError def load(string, options={}) options[:symbol_keys] = options.delete(:symbolize_keys) ::Oj.load(string, options) end def dump(object, options={}) options.merge!(:indent => 2) if options[:pretty] ::Oj.dump(object, options) end end end end multi_json-1.8.0/lib/multi_json/adapters/json_gem.rb0000644000004100000410000000033612220127643022616 0ustar www-datawww-datarequire 'json/ext' require 'multi_json/adapters/json_common' module MultiJson module Adapters # Use the JSON gem to dump/load. class JsonGem < JsonCommon ParseError = ::JSON::ParserError end end end multi_json-1.8.0/lib/multi_json/adapters/json_common.rb0000644000004100000410000000127212220127643023336 0ustar www-datawww-datarequire 'multi_json/adapter' module MultiJson module Adapters class JsonCommon < Adapter defaults :load, :create_additions => false, :quirks_mode => true def load(string, options={}) string = string.read if string.respond_to?(:read) if string.respond_to?(:force_encoding) string = string.dup.force_encoding(::Encoding::ASCII_8BIT) end options[:symbolize_names] = true if options.delete(:symbolize_keys) ::JSON.parse(string, options) end def dump(object, options={}) options.merge!(::JSON::PRETTY_STATE_PROTOTYPE.to_h) if options.delete(:pretty) object.to_json(options) end end end end multi_json-1.8.0/lib/multi_json/adapters/json_pure.rb0000644000004100000410000000033512220127643023020 0ustar www-datawww-datarequire 'json/pure' require 'multi_json/adapters/json_common' module MultiJson module Adapters # Use JSON pure to dump/load. class JsonPure < JsonCommon ParseError = ::JSON::ParserError end end end multi_json-1.8.0/lib/multi_json/adapters/gson.rb0000644000004100000410000000062212220127643021761 0ustar www-datawww-datarequire 'gson' require 'multi_json/adapter' module MultiJson module Adapters # Use the gson.rb library to dump/load. class Gson < Adapter ParseError = ::Gson::DecodeError def load(string, options={}) ::Gson::Decoder.new(options).decode(string) end def dump(object, options={}) ::Gson::Encoder.new(options).encode(object) end end end end multi_json-1.8.0/lib/multi_json/adapters/ok_json.rb0000644000004100000410000000114112220127643022452 0ustar www-datawww-datarequire 'multi_json/adapter' require 'multi_json/convertible_hash_keys' require 'multi_json/vendor/okjson' module MultiJson module Adapters class OkJson < Adapter include ConvertibleHashKeys ParseError = ::MultiJson::OkJson::Error def load(string, options={}) string = string.read if string.respond_to?(:read) result = ::MultiJson::OkJson.decode("[#{string}]").first options[:symbolize_keys] ? symbolize_keys(result) : result end def dump(object, options={}) ::MultiJson::OkJson.valenc(stringify_keys(object)) end end end end multi_json-1.8.0/lib/multi_json/adapters/nsjsonserialization.rb0000644000004100000410000000221612220127643025124 0ustar www-datawww-dataframework 'Foundation' require 'multi_json/adapters/ok_json' module MultiJson module Adapters class Nsjsonserialization < MultiJson::Adapters::OkJson ParseError = ::MultiJson::OkJson::Error def load(string, options={}) string = string.read if string.respond_to?(:read) data = string.dataUsingEncoding(NSUTF8StringEncoding) object = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves, error: nil) if object object = symbolize_keys(object) if options[:symbolize_keys] object else super(string, options={}) end end def dump(object, options={}) pretty = options[:pretty] ? NSJSONWritingPrettyPrinted : 0 object = object.as_json if object.respond_to?(:as_json) if NSJSONSerialization.isValidJSONObject(object) data = NSJSONSerialization.dataWithJSONObject(object, options: pretty, error: nil) NSMutableString.alloc.initWithData(data, encoding: NSUTF8StringEncoding) else super(object, options) end end end end end multi_json-1.8.0/lib/multi_json/load_error.rb0000644000004100000410000000040712220127643021341 0ustar www-datawww-datamodule MultiJson class LoadError < StandardError attr_reader :data def initialize(message='', backtrace=[], data='') super(message) self.set_backtrace(backtrace) @data = data end end DecodeError = LoadError # Legacy support endmulti_json-1.8.0/lib/multi_json/convertible_hash_keys.rb0000644000004100000410000000201212220127643023555 0ustar www-datawww-datamodule MultiJson module ConvertibleHashKeys private def symbolize_keys(object) prepare_object(object) do |key| key.respond_to?(:to_sym) ? key.to_sym : key end end def stringify_keys(object) prepare_object(object) do |key| key.respond_to?(:to_s) ? key.to_s : key end end def prepare_object(object, &key_modifier) return object unless block_given? case object when Array object.map do |value| prepare_object(value, &key_modifier) end when Hash object.inject({}) do |result, (key, value)| new_key = key_modifier.call(key) new_value = prepare_object(value, &key_modifier) result.merge! new_key => new_value end when String, Numeric, true, false, nil object else if object.respond_to?(:to_json) object elsif object.respond_to?(:to_s) object.to_s else object end end end end end multi_json-1.8.0/lib/multi_json/adapter.rb0000644000004100000410000000247112220127643020634 0ustar www-datawww-datarequire 'singleton' require 'multi_json/options' module MultiJson class Adapter extend Options include Singleton class << self def defaults(action, value) metaclass = class << self; self; end metaclass.instance_eval do define_method("default_#{action}_options"){ value } end end def load(string, options={}) raise self::ParseError if blank?(string) instance.load(string, collect_load_options(options).clone) end def dump(object, options={}) instance.dump(object, collect_dump_options(options).clone) end protected def collect_load_options(options) cache('load', options){ collect_options(:load_options, options).merge(options) } end def collect_dump_options(options) cache('dump', options){ collect_options(:dump_options, options).merge(options) } end def collect_options(method, *args) global, local = *[MultiJson, self].map{ |r| r.send(method, *args) } local.merge(global) end def cache(method, options) cache_key = [self, options].map(&:hash).join + method MultiJson.cached_options[cache_key] ||= yield end private def blank?(input) input.nil? || /\A\s*\z/ === input end end end end multi_json-1.8.0/lib/multi_json.rb0000644000004100000410000000774012220127643017220 0ustar www-datawww-datarequire 'multi_json/options' require 'multi_json/version' require 'multi_json/load_error' module MultiJson include Options extend self class << self def cached_options @cached_options ||= {} end def reset_cached_options! @cached_options = {} end end # Since `default_options` is deprecated, the # reader is aliased to `dump_options` and the # writer sets both `dump_options` and `load_options` alias default_options dump_options def default_options=(value) Kernel.warn "MultiJson.default_options setter is deprecated\n" + "Use MultiJson.load_options and MultiJson.dump_options instead" self.load_options = self.dump_options = value end ALIASES = { 'jrjackson' => :jr_jackson } REQUIREMENT_MAP = [ ['oj', :oj], ['yajl', :yajl], ['jrjackson', :jr_jackson], ['json/ext', :json_gem], ['gson', :gson], ['json/pure', :json_pure] ] # The default adapter based on what you currently # have loaded and installed. First checks to see # if any adapters are already loaded, then checks # to see which are installed if none are loaded. def default_adapter return :oj if defined?(::Oj) return :yajl if defined?(::Yajl) return :jr_jackson if defined?(::JrJackson) return :json_gem if defined?(::JSON::JSON_LOADED) return :gson if defined?(::Gson) REQUIREMENT_MAP.each do |library, adapter| begin require library return adapter rescue ::LoadError next end end Kernel.warn '[WARNING] MultiJson is using the default adapter (ok_json).' + 'We recommend loading a different JSON library to improve performance.' :ok_json end alias default_engine default_adapter # Get the current adapter class. def adapter return @adapter if defined?(@adapter) && @adapter self.use nil # load default adapter @adapter end alias engine adapter # Set the JSON parser utilizing a symbol, string, or class. # Supported by default are: # # * :oj # * :json_gem # * :json_pure # * :ok_json # * :yajl # * :nsjsonserialization (MacRuby only) # * :gson (JRuby only) # * :jr_jackson (JRuby only) def use(new_adapter) @adapter = load_adapter(new_adapter) end alias adapter= use alias engine= use def load_adapter(new_adapter) case new_adapter when String, Symbol load_adapter_from_string_name new_adapter.to_s when NilClass, FalseClass load_adapter default_adapter when Class, Module new_adapter else raise ::LoadError end rescue ::LoadError raise ArgumentError, 'Did not recognize your adapter specification.' end # Decode a JSON string into Ruby. # # Options # # :symbolize_keys :: If true, will use symbols instead of strings for the keys. # :adapter :: If set, the selected adapter will be used for this call. def load(string, options={}) adapter = current_adapter(options) begin adapter.load(string, options) rescue adapter::ParseError => exception raise LoadError.new(exception.message, exception.backtrace, string) end end alias decode load def current_adapter(options={}) if new_adapter = options[:adapter] load_adapter(new_adapter) else adapter end end # Encodes a Ruby object as JSON. def dump(object, options={}) current_adapter(options).dump(object, options) end alias encode dump # Executes passed block using specified adapter. def with_adapter(new_adapter) old_adapter, self.adapter = adapter, new_adapter yield ensure self.adapter = old_adapter end alias with_engine with_adapter private def load_adapter_from_string_name(name) name = ALIASES.fetch(name, name) require "multi_json/adapters/#{name}" klass_name = name.to_s.split('_').map(&:capitalize) * '' MultiJson::Adapters.const_get(klass_name) end end multi_json-1.8.0/LICENSE.md0000644000004100000410000000213412220127643015336 0ustar www-datawww-dataCopyright (c) 2010-2013 Michael Bleigh, Josh Kalderimis, Erik Michaels-Ober, Pavel Pravosud Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.