diff --git a/cpp/src/msgpack/object.hpp b/cpp/src/msgpack/object.hpp index 96c026ef..cfcddc0d 100644 --- a/cpp/src/msgpack/object.hpp +++ b/cpp/src/msgpack/object.hpp @@ -1,7 +1,7 @@ // // MessagePack for C++ static resolution routine // -// Copyright (C) 2008-2009 FURUHASHI Sadayuki +// Copyright (C) 2008-2010 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -124,6 +124,16 @@ private: with_zone(); }; +class managed_object : public object, private zone { +public: + managed_object() { } + ~managed_object() { } +public: + zone& get_zone() { return *(zone*)this; } + const zone& get_zone() const { return *(const zone*)this; } +private: + managed_object(const managed_object&); +}; bool operator==(const object x, const object y); bool operator!=(const object x, const object y); diff --git a/ruby/AUTHORS b/ruby/AUTHORS deleted file mode 100644 index ababacb0..00000000 --- a/ruby/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -FURUHASHI Sadayuki diff --git a/ruby/ChangeLog b/ruby/ChangeLog deleted file mode 100644 index 4cb23883..00000000 --- a/ruby/ChangeLog +++ /dev/null @@ -1,34 +0,0 @@ - -2012-12-16 version 0.4.8: - - * Fixed compile error on Rubinius. Function prototype rb_gc_enable() is no - longer needed. - -2012-05-05 version 0.4.7: - - * Fixed serialization of double values on ARM OABI architectures - * Fixed byteorder problem on big-endian platforms - * Don't use MRI internals in the Ruby extension for Rubinius - * Detect whether st.h is present and don't use RUBY_VM as the condition for - Rubinius - -2011-08-08 version 0.4.6: - - * Fixed compile error problem on Mac OS X Lion - -2011-05-09 version 0.4.5: - - * Improves compatibility with JRuby - -2010-11-28 version 0.4.4: - - * Adds Unpacker#feed_each method - * Improves compatibility with Rubinius - * Improves compatibility with ruby-1.8.5 - * Encodings of String instances to UTF-8 on Ruby 1.9 - -2010-06-29 version 0.4.3: - - * Adds MessagePack::VERSION constant - * Fixes SEGV problem caused by GC bug at MessagePack_Unpacker_mark - diff --git a/ruby/README b/ruby/README deleted file mode 100644 index 051a769a..00000000 --- a/ruby/README +++ /dev/null @@ -1,37 +0,0 @@ - -= MessagePack - -== Description - -MessagePack is a binary-based efficient object serialization library. -It enables to exchange structured objects between many languages like JSON. -But unlike JSON, it is very fast and small. - -Simple usage is as follows: - - require 'msgpack' - msg = [1,2,3].to_msgpack #=> "\x93\x01\x02\x03" - MessagePack.unpack(msg) #=> [1,2,3] - -Use MessagePack::Unpacker for streaming deserialization. - - -== Installation - -=== Archive Installation - - ruby extconf.rb - make - make install - -=== Gem Installation - - gem install msgpack - - -== Copyright - -Author:: frsyuki -Copyright:: Copyright (c) 2008-2010 FURUHASHI Sadayuki -License:: Apache License, Version 2.0 - diff --git a/ruby/README.md b/ruby/README.md new file mode 100644 index 00000000..b69ab833 --- /dev/null +++ b/ruby/README.md @@ -0,0 +1 @@ +MessagePack for Ruby moved to https://github.com/msgpack/msgpack-ruby. diff --git a/ruby/bench.rb b/ruby/bench.rb deleted file mode 100644 index 3b0b2ae8..00000000 --- a/ruby/bench.rb +++ /dev/null @@ -1,70 +0,0 @@ -require 'rubygems' -require 'json' -require 'msgpack' - -def show10(str) - puts "#{str.length/1024} KB" - puts str[0, 10].unpack('C*').map{|x|"%02x"%x}.join(' ') + " ..." -end - -ary = [] -i = 0 -while i < (1<<24) - #ary << (1<<24) - ary << i - i += 1 -end - -GC.start - -puts "----" -puts "MessagePack" -a = Time.now -packed = MessagePack::pack(ary) -b = Time.now -show10(packed) -sec = b - a -puts "#{sec} sec." -puts "#{packed.length.to_f / sec / 1024 / 1024 * 8} Mbps" - -GC.start - -=begin -puts "----" -puts "JSON" -a = Time.now -json = ary.to_json -b = Time.now -show10(json) -puts "#{b-a} sec." - -ary = nil -GC.start -=end - - -puts "----" -puts "MessagePack" -a = Time.now -ary = MessagePack::unpack(packed) -b = Time.now -sec = b - a -puts "#{sec} sec." -puts "#{packed.length.to_f / sec / 1024 / 1024 * 8} Mbps" - -p ary.size -p (1<<24) - -ary = nil -GC.start - - -=begin -puts "----" -puts "JSON" -a = Time.now -ary = JSON::load(json) -b = Time.now -puts "#{b-a} sec." -=end - diff --git a/ruby/compat.h b/ruby/compat.h deleted file mode 100644 index 5d0f12f7..00000000 --- a/ruby/compat.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * MessagePack for Ruby - * - * Copyright (C) 2008-2010 FURUHASHI Sadayuki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef COMPAT_H__ -#define COMPAT_H__ - - -#ifdef HAVE_RUBY_ENCODING_H -#include "ruby/encoding.h" -#define COMPAT_HAVE_ENCODING -extern int s_enc_utf8; -extern int s_enc_ascii8bit; -extern int s_enc_usascii; -extern VALUE s_enc_utf8_value; -#endif - -/* MRI 1.9 */ -#if defined(RUBY_VM) -#define COMPAT_RERAISE rb_exc_raise(rb_errinfo()) - -/* JRuby */ -#elif defined(JRUBY) -#define COMPAT_RERAISE rb_exc_raise(rb_gv_get("$!")) - -/* MRI 1.8 and Rubinius */ -#else -#define COMPAT_RERAISE rb_exc_raise(ruby_errinfo) -#endif - - -#ifndef RBIGNUM_POSITIVE_P - -/* JRuby */ -#if defined(JRUBY) -#define RBIGNUM_POSITIVE_P(b) (rb_funcall(b, rb_intern(">="), 1, INT2FIX(0)) == Qtrue) -#define rb_big2ull(b) rb_num2ull(b) -/*#define rb_big2ll(b) rb_num2ll(b)*/ - -/* MRI 1.8 */ -#else -#define RBIGNUM_POSITIVE_P(b) (RBIGNUM(b)->sign) - -#endif -#endif - - -/* JRuby */ -#if defined(JRUBY) -static inline void rb_gc_enable() { return; } -static inline void rb_gc_disable() { return; } -#endif - - -/* MRI 1.8.5 */ -#ifndef RSTRING_PTR -#define RSTRING_PTR(s) (RSTRING(s)->ptr) -#endif - -/* MRI 1.8.5 */ -#ifndef RSTRING_LEN -#define RSTRING_LEN(s) (RSTRING(s)->len) -#endif - -/* MRI 1.8.5 */ -#ifndef RARRAY_PTR -#define RARRAY_PTR(s) (RARRAY(s)->ptr) -#endif - -/* MRI 1.8.5 */ -#ifndef RARRAY_LEN -#define RARRAY_LEN(s) (RARRAY(s)->len) -#endif - - -#endif /* compat.h */ - diff --git a/ruby/extconf.rb b/ruby/extconf.rb deleted file mode 100644 index 4865ac60..00000000 --- a/ruby/extconf.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'mkmf' -require './version.rb' -$CFLAGS << %[ -I.. -Wall -O3 -DMESSAGEPACK_VERSION=\\"#{MessagePack::VERSION}\\" -g] -have_header("ruby/st.h") -have_header("st.h") -create_makefile('msgpack') - diff --git a/ruby/makegem.sh b/ruby/makegem.sh deleted file mode 100755 index 6a99cfe9..00000000 --- a/ruby/makegem.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -mkdir -p ext -mkdir -p msgpack -cp extconf.rb ext/ -cp pack.c ext/ -cp pack.h ext/ -cp rbinit.c ext/ -cp unpack.c ext/ -cp unpack.h ext/ -cp compat.h ext/ -cp version.rb ext/ -cp ../msgpack/pack_define.h msgpack/ -cp ../msgpack/pack_template.h msgpack/ -cp ../msgpack/unpack_define.h msgpack/ -cp ../msgpack/unpack_template.h msgpack/ -cp ../msgpack/sysdep.h msgpack/ -cp ../test/cases.mpac test/ -cp ../test/cases_compact.mpac test/ -cp ../test/cases.json test/ - -gem build msgpack.gemspec - -rdoc rbinit.c pack.c unpack.c - -if [ $? -eq 0 ]; then - rm -rf ext msgpack test/msgpack_test.rb -fi - -# gem install gem-compile # on msys -# gem compile msgpack-$version.gem # on msys -# gem compile msgpack-$version.gem -p mswin32 # on msys -# gem push msgpack-$version.gem -# gem push msgpack-$version-x86-mingw32.gem -# gem push msgpack-$version-mswin32.gem - diff --git a/ruby/msgpack.gemspec b/ruby/msgpack.gemspec deleted file mode 100644 index 942c4bb0..00000000 --- a/ruby/msgpack.gemspec +++ /dev/null @@ -1,17 +0,0 @@ -require './version.rb' -Gem::Specification.new do |s| - s.platform = Gem::Platform::RUBY - s.name = "msgpack" - s.version = MessagePack::VERSION - s.summary = "MessagePack, a binary-based efficient data interchange format." - s.author = "FURUHASHI Sadayuki" - s.email = "frsyuki@users.sourceforge.jp" - s.homepage = "http://msgpack.org/" - s.rubyforge_project = "msgpack" - s.has_rdoc = true - s.rdoc_options = ["ext"] - s.require_paths = ["lib"] - s.files = Dir["ext/**/*", "msgpack/**/*", "test/**/*"] - s.test_files = Dir["test/test_*.rb"] - s.extensions = Dir["ext/**/extconf.rb"] -end diff --git a/ruby/pack.c b/ruby/pack.c deleted file mode 100644 index 6e3c964b..00000000 --- a/ruby/pack.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * MessagePack for Ruby packing routine - * - * Copyright (C) 2008-2010 FURUHASHI Sadayuki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#define RSTRING_NOT_MODIFIED -#include "ruby.h" -#include "compat.h" - -#include "msgpack/pack_define.h" - -static ID s_to_msgpack; -static ID s_append; - -#define msgpack_pack_inline_func(name) \ - static inline void msgpack_pack ## name - -#define msgpack_pack_inline_func_cint(name) \ - static inline void msgpack_pack ## name - -#define msgpack_pack_user VALUE - -#define msgpack_pack_append_buffer(user, buf, len) \ - ((TYPE(user) == T_STRING) ? \ - rb_str_buf_cat(user, (const void*)buf, len) : \ - rb_funcall(user, s_append, 1, rb_str_new((const void*)buf,len))) - -#include "msgpack/pack_template.h" - - -#if defined(HAVE_RUBY_ST_H) -#include "ruby/st.h" // ruby hash on Ruby 1.9 -#elif defined(HAVE_ST_H) -#include "st.h" // ruby hash on Ruby 1.8 -#endif - -#define ARG_BUFFER(name, argc, argv) \ - VALUE name; \ - if(argc == 1) { \ - name = argv[0]; \ - } else if(argc == 0) { \ - name = rb_str_buf_new(0); \ - } else { \ - rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); \ - } - - -/* - * Document-method: NilClass#to_msgpack - * - * call-seq: - * nil.to_msgpack(out = '') -> String - * - * Serializes the nil into raw bytes. - */ -static VALUE MessagePack_NilClass_to_msgpack(int argc, VALUE *argv, VALUE self) -{ - ARG_BUFFER(out, argc, argv); - msgpack_pack_nil(out); - return out; -} - - -/* - * Document-method: TrueClass#to_msgpack - * - * call-seq: - * true.to_msgpack(out = '') -> String - * - * Serializes the true into raw bytes. - */ -static VALUE MessagePack_TrueClass_to_msgpack(int argc, VALUE *argv, VALUE self) -{ - ARG_BUFFER(out, argc, argv); - msgpack_pack_true(out); - return out; -} - - -/* - * Document-method: FalseClass#to_msgpack - * - * call-seq: - * false.to_msgpack(out = '') -> String - * - * Serializes false into raw bytes. - */ -static VALUE MessagePack_FalseClass_to_msgpack(int argc, VALUE *argv, VALUE self) -{ - ARG_BUFFER(out, argc, argv); - msgpack_pack_false(out); - return out; -} - - -/* - * Document-method: Fixnum#to_msgpack - * - * call-seq: - * fixnum.to_msgpack(out = '') -> String - * - * Serializes the Fixnum into raw bytes. - */ -static VALUE MessagePack_Fixnum_to_msgpack(int argc, VALUE *argv, VALUE self) -{ - ARG_BUFFER(out, argc, argv); -#ifdef JRUBY - msgpack_pack_long(out, FIXNUM_P(self) ? FIX2LONG(self) : rb_num2ll(self)); -#else - msgpack_pack_long(out, FIX2LONG(self)); -#endif - return out; -} - - -/* - * Document-method: Bignum#to_msgpack - * - * call-seq: - * bignum.to_msgpack(out = '') -> String - * - * Serializes the Bignum into raw bytes. - */ -static VALUE MessagePack_Bignum_to_msgpack(int argc, VALUE *argv, VALUE self) -{ - ARG_BUFFER(out, argc, argv); - if(RBIGNUM_POSITIVE_P(self)) { - msgpack_pack_uint64(out, rb_big2ull(self)); - } else { - msgpack_pack_int64(out, rb_big2ll(self)); - } - return out; -} - - -/* - * Document-method: Float#to_msgpack - * - * call-seq: - * float.to_msgpack(out = '') -> String - * - * Serializes the Float into raw bytes. - */ -static VALUE MessagePack_Float_to_msgpack(int argc, VALUE *argv, VALUE self) -{ - ARG_BUFFER(out, argc, argv); - msgpack_pack_double(out, rb_num2dbl(self)); - return out; -} - - -/* - * Document-method: String#to_msgpack - * - * call-seq: - * string.to_msgpack(out = '') -> String - * - * Serializes the String into raw bytes. - */ -static VALUE MessagePack_String_to_msgpack(int argc, VALUE *argv, VALUE self) -{ - ARG_BUFFER(out, argc, argv); -#ifdef COMPAT_HAVE_ENCODING - int enc = ENCODING_GET(self); - if(enc != s_enc_utf8 && enc != s_enc_ascii8bit && enc != s_enc_usascii) { - if(!ENC_CODERANGE_ASCIIONLY(self)) { - self = rb_str_encode(self, s_enc_utf8_value, 0, Qnil); - } - } -#endif - msgpack_pack_raw(out, RSTRING_LEN(self)); - msgpack_pack_raw_body(out, RSTRING_PTR(self), RSTRING_LEN(self)); - return out; -} - - -/* - * Document-method: Symbol#to_msgpack - * - * call-seq: - * symbol.to_msgpack(out = '') -> String - * - * Serializes the Symbol into raw bytes. - */ -static VALUE MessagePack_Symbol_to_msgpack(int argc, VALUE *argv, VALUE self) -{ -#ifdef COMPAT_HAVE_ENCODING - return MessagePack_String_to_msgpack(argc, argv, rb_id2str(SYM2ID(self))); -#else - ARG_BUFFER(out, argc, argv); - const char* name = rb_id2name(SYM2ID(self)); - size_t len = strlen(name); - msgpack_pack_raw(out, len); - msgpack_pack_raw_body(out, name, len); - return out; -#endif -} - - -/* - * Document-method: Array#to_msgpack - * - * call-seq: - * array.to_msgpack(out = '') -> String - * - * Serializes the Array into raw bytes. - * This calls to_msgpack method reflectively for internal elements. - */ -static VALUE MessagePack_Array_to_msgpack(int argc, VALUE *argv, VALUE self) -{ - ARG_BUFFER(out, argc, argv); - // FIXME check sizeof(long) > sizeof(unsigned int) && RARRAY_LEN(self) > UINT_MAX - unsigned int ary_length = (unsigned int)RARRAY_LEN(self); - unsigned int i = 0; - msgpack_pack_array(out, ary_length); - for(; i < ary_length; ++i) { - VALUE p = rb_ary_entry(self, i); - rb_funcall(p, s_to_msgpack, 1, out); - } - return out; -} - - -#ifndef RHASH_SIZE // Ruby 1.8 -#define RHASH_SIZE(h) (RHASH(h)->tbl ? RHASH(h)->tbl->num_entries : 0) -#endif - -static int MessagePack_Hash_to_msgpack_foreach(VALUE key, VALUE value, VALUE out) -{ - if (key == Qundef) { return ST_CONTINUE; } - rb_funcall(key, s_to_msgpack, 1, out); - rb_funcall(value, s_to_msgpack, 1, out); - return ST_CONTINUE; -} - -/* - * Document-method: Hash#to_msgpack - * - * call-seq: - * hash.to_msgpack(out = '') -> String - * - * Serializes the Hash into raw bytes. - * This calls to_msgpack method reflectively for internal keys and values. - */ -static VALUE MessagePack_Hash_to_msgpack(int argc, VALUE *argv, VALUE self) -{ - ARG_BUFFER(out, argc, argv); - // FIXME check sizeof(st_index_t) > sizeof(unsigned int) && RARRAY_LEN(self) > UINT_MAX - msgpack_pack_map(out, (unsigned int)RHASH_SIZE(self)); - rb_hash_foreach(self, MessagePack_Hash_to_msgpack_foreach, out); - return out; -} - - -/** - * Document-method: MessagePack.pack - * - * call-seq: - * MessagePack.pack(object, out = '') -> String - * - * Serializes the object into raw bytes. The encoding of the string is ASCII-8BIT on Ruby 1.9. - * This method is same as object.to_msgpack(out = ''). - * - * _out_ is an object that implements *<<* method like String or IO. - */ -static VALUE MessagePack_pack(int argc, VALUE* argv, VALUE self) -{ - VALUE out; - if(argc == 1) { - out = rb_str_buf_new(0); - } else if(argc == 2) { - out = argv[1]; - } else { - rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc); - } - return rb_funcall(argv[0], s_to_msgpack, 1, out); -} - - -void Init_msgpack_pack(VALUE mMessagePack) -{ - s_to_msgpack = rb_intern("to_msgpack"); - s_append = rb_intern("<<"); - - rb_define_method(rb_cNilClass, "to_msgpack", MessagePack_NilClass_to_msgpack, -1); - rb_define_method(rb_cTrueClass, "to_msgpack", MessagePack_TrueClass_to_msgpack, -1); - rb_define_method(rb_cFalseClass, "to_msgpack", MessagePack_FalseClass_to_msgpack, -1); - rb_define_method(rb_cFixnum, "to_msgpack", MessagePack_Fixnum_to_msgpack, -1); - rb_define_method(rb_cBignum, "to_msgpack", MessagePack_Bignum_to_msgpack, -1); - rb_define_method(rb_cFloat, "to_msgpack", MessagePack_Float_to_msgpack, -1); - rb_define_method(rb_cString, "to_msgpack", MessagePack_String_to_msgpack, -1); - rb_define_method(rb_cArray, "to_msgpack", MessagePack_Array_to_msgpack, -1); - rb_define_method(rb_cHash, "to_msgpack", MessagePack_Hash_to_msgpack, -1); - rb_define_method(rb_cSymbol, "to_msgpack", MessagePack_Symbol_to_msgpack, -1); - - /** - * MessagePack module is defined in rbinit.c file. - * mMessagePack = rb_define_module("MessagePack"); - */ - rb_define_module_function(mMessagePack, "pack", MessagePack_pack, -1); -} - diff --git a/ruby/pack.h b/ruby/pack.h deleted file mode 100644 index f162a86d..00000000 --- a/ruby/pack.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * MessagePack for Ruby packing routine - * - * Copyright (C) 2008-2010 FURUHASHI Sadayuki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef PACK_H__ -#define PACK_H__ - -#include "ruby.h" - -void Init_msgpack_pack(VALUE mMessagePack); - -#endif /* pack.h */ - diff --git a/ruby/rbinit.c b/ruby/rbinit.c deleted file mode 100644 index 1d1cbc69..00000000 --- a/ruby/rbinit.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * MessagePack for Ruby - * - * Copyright (C) 2008-2010 FURUHASHI Sadayuki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "pack.h" -#include "unpack.h" -#include "compat.h" - -static VALUE mMessagePack; - -#ifdef COMPAT_HAVE_ENCODING -int s_enc_utf8; -int s_enc_ascii8bit; -int s_enc_usascii; -VALUE s_enc_utf8_value; -#endif - -/** - * Document-module: MessagePack - * - * MessagePack is a binary-based efficient object serialization library. - * It enables to exchange structured objects between many languages like JSON. - * But unlike JSON, it is very fast and small. - * - * You can install MessagePack with rubygems. - * - * gem install msgpack - * - * Simple usage is as follows: - * - * require 'msgpack' - * msg = [1,2,3].to_msgpack #=> "\x93\x01\x02\x03" - * MessagePack.unpack(msg) #=> [1,2,3] - * - * Use Unpacker class for streaming deserialization. - * - */ -void Init_msgpack(void) -{ - mMessagePack = rb_define_module("MessagePack"); - - rb_define_const(mMessagePack, "VERSION", rb_str_new2(MESSAGEPACK_VERSION)); - -#ifdef COMPAT_HAVE_ENCODING - s_enc_ascii8bit = rb_ascii8bit_encindex(); - s_enc_utf8 = rb_utf8_encindex(); - s_enc_usascii = rb_usascii_encindex(); - s_enc_utf8_value = rb_enc_from_encoding(rb_utf8_encoding()); -#endif - - Init_msgpack_unpack(mMessagePack); - Init_msgpack_pack(mMessagePack); -} diff --git a/ruby/test/test_cases.rb b/ruby/test/test_cases.rb deleted file mode 100644 index bfb752e2..00000000 --- a/ruby/test/test_cases.rb +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env ruby -here = File.dirname(__FILE__) -require "#{here}/test_helper" - -begin -require 'json' -rescue LoadError -require 'rubygems' -require 'json' -end - -CASES_PATH = "#{here}/cases.mpac" -CASES_COMPACT_PATH = "#{here}/cases_compact.mpac" -CASES_JSON_PATH = "#{here}/cases.json" - -class MessagePackTestCases < Test::Unit::TestCase - def feed_file(path) - pac = MessagePack::Unpacker.new - pac.feed File.read(path) - pac - end - - def test_compare_compact - pac = feed_file(CASES_PATH) - cpac = feed_file(CASES_COMPACT_PATH) - - objs = []; pac.each {| obj| objs << obj } - cobjs = []; cpac.each {|cobj| cobjs << cobj } - - objs.zip(cobjs).each {|obj, cobj| - assert_equal(obj, cobj) - } - end - - def test_compare_json - pac = feed_file(CASES_PATH) - - objs = []; pac.each {|obj| objs << obj } - jobjs = JSON.load File.read(CASES_JSON_PATH) - - objs.zip(jobjs) {|obj, jobj| - assert_equal(obj, jobj) - } - end -end - diff --git a/ruby/test/test_encoding.rb b/ruby/test/test_encoding.rb deleted file mode 100644 index 2cf0767c..00000000 --- a/ruby/test/test_encoding.rb +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__)+'/test_helper' - -if RUBY_VERSION < "1.9" - exit -end - -class MessagePackTestEncoding < Test::Unit::TestCase - def self.it(name, &block) - define_method("test_#{name}", &block) - end - - it "US-ASCII" do - check_unpack "abc".force_encoding("US-ASCII") - end - - it "UTF-8 ascii" do - check_unpack "abc".force_encoding("UTF-8") - end - - it "UTF-8 mbstr" do - check_unpack "\xE3\x81\x82".force_encoding("UTF-8") - end - - it "UTF-8 invalid" do - check_unpack "\xD0".force_encoding("UTF-8") - end - - it "ASCII-8BIT" do - check_unpack "\xD0".force_encoding("ASCII-8BIT") - end - - it "EUC-JP" do - x = "\xA4\xA2".force_encoding("EUC-JP") - check_unpack(x) - end - - it "EUC-JP invalid" do - begin - "\xD0".force_encoding("EUC-JP").to_msgpack - assert(false) - rescue Encoding::InvalidByteSequenceError - assert(true) - end - end - - private - def check_unpack(str) - if str.encoding.to_s == "ASCII-8BIT" - should_str = str.dup.force_encoding("UTF-8") - else - should_str = str.encode("UTF-8") - end - - raw = str.to_msgpack - r = MessagePack.unpack(str.to_msgpack) - assert_equal(r.encoding.to_s, "UTF-8") - assert_equal(r, should_str.force_encoding("UTF-8")) - - if str.valid_encoding? - sym = str.to_sym - r = MessagePack.unpack(sym.to_msgpack) - assert_equal(r.encoding.to_s, "UTF-8") - assert_equal(r, should_str.force_encoding("UTF-8")) - end - end -end - diff --git a/ruby/test/test_helper.rb b/ruby/test/test_helper.rb deleted file mode 100644 index 4def861a..00000000 --- a/ruby/test/test_helper.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'test/unit' -begin -require File.dirname(__FILE__) + '/../msgpack' -rescue LoadError -require File.dirname(__FILE__) + '/../lib/msgpack' -end - -if ENV["GC_STRESS"] - GC.stress = true -end diff --git a/ruby/test/test_pack_unpack.rb b/ruby/test/test_pack_unpack.rb deleted file mode 100644 index 8bdb3628..00000000 --- a/ruby/test/test_pack_unpack.rb +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__)+'/test_helper' - -class MessagePackTestPackUnpack < Test::Unit::TestCase - def self.it(name, &block) - define_method("test_#{name}", &block) - end - - it "nil" do - check 1, nil - end - - it "true" do - check 1, true - end - - it "false" do - check 1, false - end - - it "zero" do - check 1, 0 - end - - it "positive fixnum" do - check 1, 1 - check 1, (1<<6) - check 1, (1<<7)-1 - end - - it "positive int 8" do - check 1, -1 - check 2, (1<<7) - check 2, (1<<8)-1 - end - - it "positive int 16" do - check 3, (1<<8) - check 3, (1<<16)-1 - end - - it "positive int 32" do - check 5, (1<<16) - check 5, (1<<32)-1 - end - - it "positive int 64" do - check 9, (1<<32) - check 9, (1<<64)-1 - end - - it "negative fixnum" do - check 1, -1 - check 1, -((1<<5)-1) - check 1, -(1<<5) - end - - it "negative int 8" do - check 2, -((1<<5)+1) - check 2, -(1<<7) - end - - it "negative int 16" do - check 3, -((1<<7)+1) - check 3, -(1<<15) - end - - it "negative int 32" do - check 5, -((1<<15)+1) - check 5, -(1<<31) - end - - it "negative int 64" do - check 9, -((1<<31)+1) - check 9, -(1<<63) - end - - it "double" do - check 9, 1.0 - check 9, 0.1 - check 9, -0.1 - check 9, -1.0 - end - - it "fixraw" do - check_raw 1, 0 - check_raw 1, (1<<5)-1 - end - - it "raw 16" do - check_raw 3, (1<<5) - check_raw 3, (1<<16)-1 - end - - it "raw 32" do - check_raw 5, (1<<16) - #check_raw 5, (1<<32)-1 # memory error - end - - it "fixarray" do - check_array 1, 0 - check_array 1, (1<<4)-1 - end - - it "array 16" do - check_array 3, (1<<4) - check_array 3, (1<<16)-1 - end - - it "array 32" do - check_array 5, (1<<16) - #check_array 5, (1<<32)-1 # memory error - end - - it "nil" do - match nil, "\xc0" - end - - it "false" do - match false, "\xc2" - end - - it "true" do - match true, "\xc3" - end - - it "0" do - match 0, "\x00" - end - - it "127" do - match 127, "\x7f" - end - - it "128" do - match 128, "\xcc\x80" - end - - it "256" do - match 256, "\xcd\x01\x00" - end - - it "-1" do - match -1, "\xff" - end - - it "-33" do - match -33, "\xd0\xdf" - end - - it "-129" do - match -129, "\xd1\xff\x7f" - end - - it "{1=>1}" do - obj = {1=>1} - match obj, "\x81\x01\x01" - end - - it "1.0" do - match 1.0, "\xcb\x3f\xf0\x00\x00\x00\x00\x00\x00" - end - - it "[]" do - match [], "\x90" - end - - it "[0, 1, ..., 14]" do - obj = (0..14).to_a - match obj, "\x9f\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e" - end - - it "[0, 1, ..., 15]" do - obj = (0..15).to_a - match obj, "\xdc\x00\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - end - - it "{}" do - obj = {} - match obj, "\x80" - end - -## FIXME -# it "{0=>0, 1=>1, ..., 14=>14}" do -# a = (0..14).to_a; -# match Hash[*a.zip(a).flatten], "\x8f\x05\x05\x0b\x0b\x00\x00\x06\x06\x0c\x0c\x01\x01\x07\x07\x0d\x0d\x02\x02\x08\x08\x0e\x0e\x03\x03\x09\x09\x04\x04\x0a\x0a" -# end -# -# it "{0=>0, 1=>1, ..., 15=>15}" do -# a = (0..15).to_a; -# match Hash[*a.zip(a).flatten], "\xde\x00\x10\x05\x05\x0b\x0b\x00\x00\x06\x06\x0c\x0c\x01\x01\x07\x07\x0d\x0d\x02\x02\x08\x08\x0e\x0e\x03\x03\x09\x09\x0f\x0f\x04\x04\x0a\x0a" -# end - -## FIXME -# it "fixmap" do -# check_map 1, 0 -# check_map 1, (1<<4)-1 -# end -# -# it "map 16" do -# check_map 3, (1<<4) -# check_map 3, (1<<16)-1 -# end -# -# it "map 32" do -# check_map 5, (1<<16) -# #check_map 5, (1<<32)-1 # memory error -# end - - it "buffer" do - str = "a"*32*1024*4 - raw = str.to_msgpack - pac = MessagePack::Unpacker.new - - len = 0 - parsed = false - - n = 655 - time = raw.size / n - time += 1 unless raw.size % n == 0 - off = 0 - - time.times do - assert(!parsed) - - fe = raw[off, n] - assert(fe.length > 0) - off += fe.length - - #pac.feed fe - #pac.each {|obj| - pac.feed_each(fe) {|obj| - assert(!parsed) - assert_equal(obj, str) - parsed = true - } - end - - assert(parsed) - end - - it "gc mark" do - obj = [1024, {["a","b"]=>["c","d"]}, ["e","f"], "d", 70000, 4.12, 1.5, 1.5, 1.5] - num = 4 - raw = obj.to_msgpack * num - pac = MessagePack::Unpacker.new - parsed = 0 - raw.split(//).each do |b| - #pac.feed(b) - pac.feed_each(b) {|o| - GC.start - assert_equal(obj, o) - parsed += 1 - } - GC.start - end - assert_equal(parsed, num) - end - - it "streaming backward compatibility" do - obj = [1024, {["a","b"]=>["c","d"]}, ["e","f"], "d", 70000, 4.12, 1.5, 1.5, 1.5] - num = 4 - raw = obj.to_msgpack * num - pac = MessagePack::Unpacker.new - buffer = "" - nread = 0 - parsed = 0 - raw.split(//).each do |b| - buffer << b - nread = pac.execute(buffer, nread) - if pac.finished? - o = pac.data - assert_equal(obj, o) - parsed += 1 - pac.reset - buffer.slice!(0, nread) - nread = 0 - next unless buffer.empty? - end - end - assert_equal(parsed, num) - end - - it "MessagePack::VERSION constant" do - p MessagePack::VERSION - end - - private - def check(len, obj) - v = obj.to_msgpack - assert_equal(v.length, len) - assert_equal(MessagePack.unpack(v), obj) - end - - def check_raw(overhead, num) - check num+overhead, " "*num - end - - def check_array(overhead, num) - check num+overhead, Array.new(num) - end - - def match(obj, buf) - assert_equal(obj.to_msgpack, buf) - assert_equal(MessagePack::unpack(buf), obj) - end -end - diff --git a/ruby/unpack.c b/ruby/unpack.c deleted file mode 100644 index a3bb861d..00000000 --- a/ruby/unpack.c +++ /dev/null @@ -1,1001 +0,0 @@ -/* - * MessagePack for Ruby unpacking routine - * - * Copyright (C) 2008-2010 FURUHASHI Sadayuki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "ruby.h" -#include "compat.h" - -#include "msgpack/unpack_define.h" - -static ID s_sysread; -static ID s_readpartial; - -struct unpack_buffer { - size_t used; - size_t free; - char* ptr; -}; - -typedef struct { - int finished; - VALUE source; - size_t offset; - struct unpack_buffer buffer; - VALUE stream; - VALUE streambuf; - ID stream_append_method; - size_t buffer_free_size; -} unpack_user; - - -#define msgpack_unpack_struct(name) \ - struct template ## name - -#define msgpack_unpack_func(ret, name) \ - ret template ## name - -#define msgpack_unpack_callback(name) \ - template_callback ## name - -#define msgpack_unpack_object VALUE - -#define msgpack_unpack_user unpack_user - - -struct template_context; -typedef struct template_context msgpack_unpack_t; - -static void template_init(msgpack_unpack_t* u); - -static VALUE template_data(msgpack_unpack_t* u); - -static int template_execute(msgpack_unpack_t* u, - const char* data, size_t len, size_t* off); - - -static inline VALUE template_callback_root(unpack_user* u) -{ return Qnil; } - -static inline int template_callback_uint8(unpack_user* u, uint8_t d, VALUE* o) -{ *o = INT2FIX(d); return 0; } - -static inline int template_callback_uint16(unpack_user* u, uint16_t d, VALUE* o) -{ *o = INT2FIX(d); return 0; } - -static inline int template_callback_uint32(unpack_user* u, uint32_t d, VALUE* o) -{ *o = UINT2NUM(d); return 0; } - -static inline int template_callback_uint64(unpack_user* u, uint64_t d, VALUE* o) -{ *o = rb_ull2inum(d); return 0; } - -static inline int template_callback_int8(unpack_user* u, int8_t d, VALUE* o) -{ *o = INT2FIX((long)d); return 0; } - -static inline int template_callback_int16(unpack_user* u, int16_t d, VALUE* o) -{ *o = INT2FIX((long)d); return 0; } - -static inline int template_callback_int32(unpack_user* u, int32_t d, VALUE* o) -{ *o = INT2NUM((long)d); return 0; } - -static inline int template_callback_int64(unpack_user* u, int64_t d, VALUE* o) -{ *o = rb_ll2inum(d); return 0; } - -static inline int template_callback_float(unpack_user* u, float d, VALUE* o) -{ *o = rb_float_new(d); return 0; } - -static inline int template_callback_double(unpack_user* u, double d, VALUE* o) -{ *o = rb_float_new(d); return 0; } - -static inline int template_callback_nil(unpack_user* u, VALUE* o) -{ *o = Qnil; return 0; } - -static inline int template_callback_true(unpack_user* u, VALUE* o) -{ *o = Qtrue; return 0; } - -static inline int template_callback_false(unpack_user* u, VALUE* o) -{ *o = Qfalse; return 0;} - -static inline int template_callback_array(unpack_user* u, unsigned int n, VALUE* o) -{ *o = rb_ary_new2(n); return 0; } - -static inline int template_callback_array_item(unpack_user* u, VALUE* c, VALUE o) -{ rb_ary_push(*c, o); return 0; } - -static inline int template_callback_map(unpack_user* u, unsigned int n, VALUE* o) -{ *o = rb_hash_new(); return 0; } - -static inline int template_callback_map_item(unpack_user* u, VALUE* c, VALUE k, VALUE v) -{ rb_hash_aset(*c, k, v); return 0; } - -#ifdef RSTRING_EMBED_LEN_MAX -#define COW_MIN_SIZE RSTRING_EMBED_LEN_MAX -#else -#define COW_MIN_SIZE ((sizeof(VALUE)*3)/sizeof(char)-1) -#endif - -static inline int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, VALUE* o) -{ - if(u->source == Qnil || l <= COW_MIN_SIZE) { - *o = rb_str_new(p, l); - } else { - *o = rb_str_substr(u->source, p - b, l); - } -#ifdef COMPAT_HAVE_ENCODING - ENCODING_SET(*o, s_enc_utf8); -#endif - return 0; -} - - -#include "msgpack/unpack_template.h" - - -#define UNPACKER(from, name) \ - msgpack_unpack_t *name = NULL; \ - Data_Get_Struct(from, msgpack_unpack_t, name); \ - if(name == NULL) { \ - rb_raise(rb_eArgError, "NULL found for " # name " when shouldn't be."); \ - } - -#define CHECK_STRING_TYPE(value) \ - value = rb_check_string_type(value); \ - if( NIL_P(value) ) { \ - rb_raise(rb_eTypeError, "instance of String needed"); \ - } - - -static VALUE template_execute_rescue(VALUE nouse) -{ - rb_gc_enable(); - COMPAT_RERAISE; -} - -static VALUE template_execute_do(VALUE argv) -{ - VALUE* args = (VALUE*)argv; - - msgpack_unpack_t* mp = (msgpack_unpack_t*)args[0]; - char* dptr = (char*)args[1]; - size_t dlen = (size_t)args[2]; - size_t* from = (size_t*)args[3]; - - int ret = template_execute(mp, dptr, dlen, from); - - return (VALUE)ret; -} - -static int template_execute_wrap(msgpack_unpack_t* mp, - VALUE str, size_t dlen, size_t* from) -{ - VALUE args[4] = { - (VALUE)mp, - (VALUE)RSTRING_PTR(str), - (VALUE)dlen, - (VALUE)from, - }; - - // FIXME execute実行中はmp->topが更新されないのでGC markが機能しない - rb_gc_disable(); - - mp->user.source = str; - - int ret = (int)rb_rescue(template_execute_do, (VALUE)args, - template_execute_rescue, Qnil); - - rb_gc_enable(); - - return ret; -} - -static int template_execute_wrap_each(msgpack_unpack_t* mp, - const char* ptr, size_t dlen, size_t* from) -{ - VALUE args[4] = { - (VALUE)mp, - (VALUE)ptr, - (VALUE)dlen, - (VALUE)from, - }; - - // FIXME execute実行中はmp->topが更新されないのでGC markが機能しない - rb_gc_disable(); - - mp->user.source = Qnil; - - int ret = (int)rb_rescue(template_execute_do, (VALUE)args, - template_execute_rescue, Qnil); - - rb_gc_enable(); - - return ret; -} - - -static VALUE cUnpacker; - - -/** - * Document-module: MessagePack::UnpackerError - * - */ -static VALUE eUnpackError; - - -#ifndef MSGPACK_UNPACKER_BUFFER_INIT_SIZE -#define MSGPACK_UNPACKER_BUFFER_INIT_SIZE (32*1024) -#endif - -#ifndef MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE -#define MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE (8*1024) -#endif - -/* -#ifndef MSGPACK_BUFFER_FREE_SIZE -#define MSGPACK_BUFFER_FREE_SIZE (1024*1024) -#endif -*/ -#define MSGPACK_BUFFER_FREE_SIZE 0 - -static void MessagePack_Unpacker_free(void* data) -{ - if(data) { - msgpack_unpack_t* mp = (msgpack_unpack_t*)data; - free(mp->user.buffer.ptr); - free(mp); - } -} - -static void MessagePack_Unpacker_mark(msgpack_unpack_t *mp) -{ - unsigned int i; - rb_gc_mark(mp->user.stream); - rb_gc_mark(mp->user.streambuf); - rb_gc_mark_maybe(template_data(mp)); - for(i=0; i < mp->top; ++i) { - rb_gc_mark(mp->stack[i].obj); - rb_gc_mark_maybe(mp->stack[i].map_key); - } -} - -static VALUE MessagePack_Unpacker_alloc(VALUE klass) -{ - VALUE obj; - msgpack_unpack_t* mp = ALLOC_N(msgpack_unpack_t, 1); - - // rb_gc_mark (not _maybe) is used for following member objects. - mp->user.stream = Qnil; - mp->user.streambuf = Qnil; - - mp->user.finished = 0; - mp->user.offset = 0; - mp->user.buffer.used = 0; - mp->user.buffer.free = 0; - mp->user.buffer.ptr = NULL; - - obj = Data_Wrap_Struct(klass, MessagePack_Unpacker_mark, - MessagePack_Unpacker_free, mp); - return obj; -} - -static ID append_method_of(VALUE stream) -{ - if(rb_respond_to(stream, s_sysread)) { - return s_sysread; - } else { - return s_readpartial; - } -} - -/** - * Document-method: MessagePack::Unpacker#initialize - * - * call-seq: - * MessagePack::Unpacker.new(stream = nil) - * - * Creates instance of MessagePack::Unpacker. - * - * You can specify a _stream_ for input stream. - * It is required to implement *sysread* or *readpartial* method. - * - * With the input stream, buffers will be feeded into the deserializer automatically. - * - * Without the input stream, use *feed* method manually. Or you can manage the buffer manually - * with *execute*, *finished?*, *data* and *reset* methods. - */ -static VALUE MessagePack_Unpacker_initialize(int argc, VALUE *argv, VALUE self) -{ - VALUE stream; - switch(argc) { - case 0: - stream = Qnil; - break; - case 1: - stream = argv[0]; - break; - default: - rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); - } - - UNPACKER(self, mp); - template_init(mp); - mp->user.stream = stream; - mp->user.streambuf = rb_str_buf_new(MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE); - mp->user.stream_append_method = append_method_of(stream); - mp->user.buffer_free_size = MSGPACK_BUFFER_FREE_SIZE; - - return self; -} - - -/** - * Document-method: MessagePack::Unpacker#stream - * - * call-seq: - * unpacker.stream - * - * Gets the input stream. - */ -static VALUE MessagePack_Unpacker_stream_get(VALUE self) -{ - UNPACKER(self, mp); - return mp->user.stream; -} - -/** - * Document-method: MessagePack::Unpacker#stream= - * - * call-seq: - * unpacker.stream = stream - * - * Resets the input stream. You can set nil not to use input stream. - */ -static VALUE MessagePack_Unpacker_stream_set(VALUE self, VALUE val) -{ - UNPACKER(self, mp); - mp->user.stream = val; - mp->user.stream_append_method = append_method_of(val); - return val; -} - - -static void reserve_buffer(msgpack_unpack_t* mp, size_t require) -{ - struct unpack_buffer* buffer = &mp->user.buffer; - - if(buffer->used == 0) { - if(require <= buffer->free) { - /* enough free space */ - return; - } - /* no used buffer: realloc only */ - size_t nsize = buffer->free == 0 ? - MSGPACK_UNPACKER_BUFFER_INIT_SIZE : buffer->free*2; - while(nsize < require) { - nsize *= 2; - } - char* tmp = REALLOC_N(buffer->ptr, char, nsize); - buffer->free = nsize; - buffer->ptr = tmp; - return; - } - - if(buffer->used <= mp->user.offset) { - /* clear buffer and rewind offset */ - buffer->free += buffer->used; - buffer->used = 0; - mp->user.offset = 0; - } - - if(require <= buffer->free) { - /* enough free space */ - return; - } - - size_t nsize = (buffer->used + buffer->free) * 2; - - if(mp->user.offset <= buffer->used / 2) { - /* parsed less than half: realloc only */ - while(nsize < buffer->used + require) { - nsize *= 2; - } - char* tmp = REALLOC_N(buffer->ptr, char, nsize); - buffer->free = nsize - buffer->used; - buffer->ptr = tmp; - - } else { - /* parsed more than half: realloc and move */ - size_t not_parsed = buffer->used - mp->user.offset; - while(nsize < not_parsed + require) { - nsize *= 2; - } - char* tmp = REALLOC_N(buffer->ptr, char, nsize); - memcpy(tmp, tmp + mp->user.offset, not_parsed); - buffer->free = nsize - not_parsed; - buffer->used = not_parsed; - buffer->ptr = tmp; - mp->user.offset = 0; - } -} - -static inline void try_free_buffer(msgpack_unpack_t* mp, size_t require) -{ - if(mp->user.buffer_free_size == 0) { - return; - } - - struct unpack_buffer* buffer = &mp->user.buffer; - size_t csize = buffer->used + buffer->free; - - if(csize <= mp->user.buffer_free_size) { - return; - } - - if(mp->user.offset <= buffer->used / 2) { - /* parsed less than half: do nothing */ - - } else if(mp->user.offset < buffer->used) { - /* parsed more than half but not all: realloc and move */ - size_t nsize = MSGPACK_UNPACKER_BUFFER_INIT_SIZE; - size_t not_parsed = buffer->used - mp->user.offset; - while(nsize < not_parsed + require) { - nsize *= 2; - } - - if(nsize >= csize) { - return; - } - - char* tmp; - if(mp->user.offset == 0) { - tmp = ALLOC_N(char, nsize); - memcpy(tmp, buffer->ptr + mp->user.offset, not_parsed); - free(buffer->ptr); - } else { - tmp = REALLOC_N(buffer->ptr, char, nsize); - } - buffer->free = nsize - not_parsed; - buffer->used = not_parsed; - buffer->ptr = tmp; - mp->user.offset = 0; - - } else { - /* all parsed: free all */ - free(buffer->ptr); - buffer->free = 0; - buffer->used = 0; - buffer->ptr = NULL; - mp->user.offset = 0; - } -} - -static void feed_buffer(msgpack_unpack_t* mp, const char* ptr, size_t len) -{ - struct unpack_buffer* buffer = &mp->user.buffer; - - reserve_buffer(mp, len); - - memcpy(buffer->ptr + buffer->used, ptr, len); - buffer->used += len; - buffer->free -= len; -} - -/** - * Document-method: MessagePack::Unpacker#feed - * - * call-seq: - * unpacker.feed(data) - * - * Fills the internal buffer with the specified buffer. - */ -static VALUE MessagePack_Unpacker_feed(VALUE self, VALUE data) -{ - UNPACKER(self, mp); - StringValue(data); - feed_buffer(mp, RSTRING_PTR(data), RSTRING_LEN(data)); - return Qnil; -} - -/** - * Document-method: MessagePack::Unpacker#fill - * - * call-seq: - * unpacker.fill -> length of read data - * - * Fills the internal buffer using the input stream. - * - * If the input stream is not specified, it returns nil. - * You can set it on *initialize* or *stream=* methods. - * - * This methods raises exceptions that _stream.sysread_ or - * _stream.readpartial_ method raises. - */ -static VALUE MessagePack_Unpacker_fill(VALUE self) -{ - UNPACKER(self, mp); - - if(mp->user.stream == Qnil) { - return Qnil; - } - - rb_funcall(mp->user.stream, mp->user.stream_append_method, 2, - LONG2FIX(MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE), - mp->user.streambuf); - - size_t len = RSTRING_LEN(mp->user.streambuf); - feed_buffer(mp, RSTRING_PTR(mp->user.streambuf), len); - - return LONG2FIX(len); -} - - -/** - * Document-method: MessagePack::Unpacker#each - * - * call-seq: - * unpacker.each {|object| } - * - * Deserializes objects repeatedly. This calls *fill* method automatically. - * - * UnpackError is throw when parse error is occured. - * This method raises exceptions that *fill* method raises. - */ -static VALUE MessagePack_Unpacker_each(VALUE self) -{ - UNPACKER(self, mp); - int ret; - -#ifdef RETURN_ENUMERATOR - RETURN_ENUMERATOR(self, 0, 0); -#endif - - while(1) { - if(mp->user.buffer.used <= mp->user.offset) { - do_fill: - { - VALUE len = MessagePack_Unpacker_fill(self); - if(len == Qnil || FIX2LONG(len) == 0) { - break; - } - } - } - - ret = template_execute_wrap_each(mp, - mp->user.buffer.ptr, mp->user.buffer.used, - &mp->user.offset); - - if(ret < 0) { - rb_raise(eUnpackError, "parse error."); - - } else if(ret > 0) { - VALUE data = template_data(mp); - template_init(mp); - rb_yield(data); - - } else { - goto do_fill; - } - } - - try_free_buffer(mp, 0); - - return Qnil; -} - -static VALUE feed_each_impl(VALUE args) -{ - VALUE self = ((VALUE*)args)[0]; - VALUE data = ((VALUE*)args)[1]; - size_t* pconsumed = (size_t*)((VALUE*)args)[2]; - - UNPACKER(self, mp); - int ret; - const char* ptr = RSTRING_PTR(data); - size_t len = RSTRING_LEN(data); - - if(mp->user.buffer.used > 0) { - while(1) { - ret = template_execute_wrap_each(mp, - mp->user.buffer.ptr, mp->user.buffer.used, - &mp->user.offset); - - if(ret < 0) { - rb_raise(eUnpackError, "parse error."); - - } else if(ret > 0) { - VALUE data = template_data(mp); - template_init(mp); - rb_yield(data); - - } else { - break; - } - } - } - - if(len <= 0) { - return Qnil; - } - - if(mp->user.buffer.used <= mp->user.offset) { - // wrap & execute & feed - while(1) { - ret = template_execute_wrap_each(mp, - ptr, len, pconsumed); - - if(ret < 0) { - rb_raise(eUnpackError, "parse error."); - - } else if(ret > 0) { - VALUE data = template_data(mp); - template_init(mp); - rb_yield(data); - - } else { - break; - } - } - - } else { - // feed & execute - feed_buffer(mp, ptr, len); - *pconsumed = len; - - while(1) { - ret = template_execute_wrap_each(mp, - mp->user.buffer.ptr, mp->user.buffer.used, - &mp->user.offset); - - if(ret < 0) { - rb_raise(eUnpackError, "parse error."); - - } else if(ret > 0) { - VALUE data = template_data(mp); - template_init(mp); - rb_yield(data); - - } else { - break; - } - } - } - - return Qnil; -} - -static VALUE feed_each_ensure(VALUE args) { - VALUE self = ((VALUE*)args)[0]; - VALUE data = ((VALUE*)args)[1]; - size_t* pconsumed = (size_t*)((VALUE*)args)[2]; - - const char* dptr = RSTRING_PTR(data) + *pconsumed; - size_t dlen = RSTRING_LEN(data) - *pconsumed; - - if(dlen > 0) { - UNPACKER(self, mp); - try_free_buffer(mp, dlen); - feed_buffer(mp, dptr, dlen); - } - - return Qnil; -} - -/** - * Document-method: MessagePack::Unpacker#feed_each - * - * call-seq: - * unpacker.feed_each(data) {|object| } - * - * Same as feed(data) + each {|object| }, but tries to avoid copying of the buffer. - */ -static VALUE MessagePack_Unpacker_feed_each(VALUE self, VALUE data) -{ - size_t consumed = 0; - StringValue(data); - - VALUE args[3]; - args[0] = self; - args[1] = data; - args[2] = (VALUE)&consumed; - - return rb_ensure(feed_each_impl, (VALUE)args, - feed_each_ensure, (VALUE)args); -} - - -static inline VALUE MessagePack_unpack_impl(VALUE self, VALUE data, unsigned long dlen) -{ - msgpack_unpack_t mp; - template_init(&mp); - - mp.user.finished = 0; - - size_t from = 0; - int ret = template_execute_wrap(&mp, data, dlen, &from); - - if(ret < 0) { - rb_raise(eUnpackError, "parse error."); - - } else if(ret == 0) { - rb_raise(eUnpackError, "insufficient bytes."); - - } else { - if(from < dlen) { - rb_raise(eUnpackError, "extra bytes."); - } - return template_data(&mp); - } -} - -/** - * Document-method: MessagePack::Unpacker.unpack_limit - * - * call-seq: - * MessagePack::Unpacker.unpack_limit(data, limit) -> object - * - * Deserializes one object over the specified buffer upto _limit_ bytes. - * - * UnpackError is throw when parse error is occured, the buffer is insufficient - * to deserialize one object or there are extra bytes. - */ -static VALUE MessagePack_unpack_limit(VALUE self, VALUE data, VALUE limit) -{ - CHECK_STRING_TYPE(data); - return MessagePack_unpack_impl(self, data, NUM2ULONG(limit)); -} - -/** - * Document-method: MessagePack::Unpacker.unpack - * - * call-seq: - * MessagePack::Unpacker.unpack(data) -> object - * - * Deserializes one object over the specified buffer. - * - * UnpackError is throw when parse error is occured, the buffer is insufficient - * to deserialize one object or there are extra bytes. - */ -static VALUE MessagePack_unpack(VALUE self, VALUE data) -{ - CHECK_STRING_TYPE(data); - return MessagePack_unpack_impl(self, data, RSTRING_LEN(data)); -} - - -static VALUE MessagePack_Unpacker_execute_impl(VALUE self, VALUE data, - size_t from, size_t limit) -{ - UNPACKER(self, mp); - - if(from >= limit) { - rb_raise(eUnpackError, "offset is bigger than data buffer size."); - } - - int ret = template_execute_wrap(mp, data, limit, &from); - - if(ret < 0) { - rb_raise(eUnpackError, "parse error."); - } else if(ret > 0) { - mp->user.finished = 1; - return ULONG2NUM(from); - } else { - mp->user.finished = 0; - return ULONG2NUM(from); - } -} - -/** - * Document-method: MessagePack::Unpacker#execute_limit - * - * call-seq: - * unpacker.execute_limit(data, offset, limit) -> next offset - * - * Deserializes one object over the specified buffer from _offset_ bytes upto _limit_ bytes. - * - * This method doesn't use the internal buffer. - * - * Call *reset* method before calling this method again. - * - * UnpackError is throw when parse error is occured. - */ -static VALUE MessagePack_Unpacker_execute_limit(VALUE self, VALUE data, - VALUE off, VALUE limit) -{ - CHECK_STRING_TYPE(data); - return MessagePack_Unpacker_execute_impl(self, data, - (size_t)NUM2ULONG(off), (size_t)NUM2ULONG(limit)); -} - -/** - * Document-method: MessagePack::Unpacker#execute - * - * call-seq: - * unpacker.execute(data, offset) -> next offset - * - * Deserializes one object over the specified buffer from _offset_ bytes. - * - * This method doesn't use the internal buffer. - * - * Call *reset* method before calling this method again. - * - * This returns offset that was parsed to. - * Use *finished?* method to check an object is deserialized and call *data* - * method if it returns true. - * - * UnpackError is throw when parse error is occured. - */ -static VALUE MessagePack_Unpacker_execute(VALUE self, VALUE data, VALUE off) -{ - CHECK_STRING_TYPE(data); - return MessagePack_Unpacker_execute_impl(self, data, - (size_t)NUM2ULONG(off), (size_t)RSTRING_LEN(data)); -} - -/** - * Document-method: MessagePack::Unpacker#finished? - * - * call-seq: - * unpacker.finished? - * - * Returns true if an object is ready to get with data method. - * - * Use this method with execute method. - */ -static VALUE MessagePack_Unpacker_finished_p(VALUE self) -{ - UNPACKER(self, mp); - if(mp->user.finished) { - return Qtrue; - } - return Qfalse; -} - -/** - * Document-method: MessagePack::Unpacker#data - * - * call-seq: - * unpacker.data - * - * Gets the object deserialized by execute method. - * - * Use this method with execute method. - */ -static VALUE MessagePack_Unpacker_data(VALUE self) -{ - UNPACKER(self, mp); - return template_data(mp); -} - -/** - * Document-method: MessagePack::Unpacker#reset - * - * call-seq: - * unpacker.reset - * - * Resets the internal state of the unpacker. - */ -static VALUE MessagePack_Unpacker_reset(VALUE self) -{ - UNPACKER(self, mp); - template_init(mp); - mp->user.finished = 0; - try_free_buffer(mp, 0); - return self; -} - - -void Init_msgpack_unpack(VALUE mMessagePack) -{ - s_sysread = rb_intern("sysread"); - s_readpartial = rb_intern("readpartial"); - - eUnpackError = rb_define_class_under(mMessagePack, "UnpackError", rb_eStandardError); - cUnpacker = rb_define_class_under(mMessagePack, "Unpacker", rb_cObject); - rb_define_alloc_func(cUnpacker, MessagePack_Unpacker_alloc); - - rb_define_method(cUnpacker, "initialize", MessagePack_Unpacker_initialize, -1); - - /* Buffered API */ - rb_define_method(cUnpacker, "feed", MessagePack_Unpacker_feed, 1); - rb_define_method(cUnpacker, "fill", MessagePack_Unpacker_fill, 0); - rb_define_method(cUnpacker, "each", MessagePack_Unpacker_each, 0); - rb_define_method(cUnpacker, "stream", MessagePack_Unpacker_stream_get, 0); - rb_define_method(cUnpacker, "stream=", MessagePack_Unpacker_stream_set, 1); - rb_define_method(cUnpacker, "feed_each", MessagePack_Unpacker_feed_each, 1); - - /* Unbuffered API */ - rb_define_method(cUnpacker, "execute", MessagePack_Unpacker_execute, 2); - rb_define_method(cUnpacker, "execute_limit", MessagePack_Unpacker_execute_limit, 3); - rb_define_method(cUnpacker, "finished?", MessagePack_Unpacker_finished_p, 0); - rb_define_method(cUnpacker, "data", MessagePack_Unpacker_data, 0); - rb_define_method(cUnpacker, "reset", MessagePack_Unpacker_reset, 0); - - /** - * MessagePack module is defined in rbinit.c file. - * mMessagePack = rb_define_module("MessagePack"); - */ - rb_define_module_function(mMessagePack, "unpack", MessagePack_unpack, 1); - rb_define_module_function(mMessagePack, "unpack_limit", MessagePack_unpack_limit, 2); -} - -/** - * Document-module: MessagePack::Unpacker - * - * Deserializer class that includes Buffered API and Unbuffered API. - * - * - * Buffered API uses the internal buffer of the Unpacker. - * Following code uses Buffered API with an input stream: - * - * # create an unpacker with input stream. - * pac = MessagePack::Unpacker.new(STDIN) - * - * # deserialize object one after another. - * pac.each {|obj| - * # ... - * } - * - * - * Following code doesn't use the input stream and feeds buffer - * manually. This is useful to use special stream or with - * event-driven I/O library. - * - * # create an unpacker without input stream. - * pac = MessagePack::Unpacker.new() - * - * # feed buffer to the internal buffer. - * pac.feed(input_bytes) - * - * # deserialize object one after another. - * pac.each {|obj| - * # ... - * } - * - * - * You can manage the buffer manually with the combination of - * *execute*, *finished?*, *data* and *reset* method. - * - * # create an unpacker. - * pac = MessagePack::Unpacker.new() - * - * # manage buffer and offset manually. - * offset = 0 - * buffer = '' - * - * # read some data into the buffer. - * buffer << [1,2,3].to_msgpack - * buffer << [4,5,6].to_msgpack - * - * while true - * offset = pac.execute(buffer, offset) - * - * if pac.finished? - * obj = pac.data - * - * buffer.slice!(0, offset) - * offset = 0 - * pac.reset - * - * # do something with the object - * # ... - * - * # repeat execution if there are more data. - * next unless buffer.empty? - * end - * - * break - * end - */ - diff --git a/ruby/unpack.h b/ruby/unpack.h deleted file mode 100644 index 91d3eb7c..00000000 --- a/ruby/unpack.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * MessagePack for Ruby unpacking routine - * - * Copyright (C) 2008-2010 FURUHASHI Sadayuki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef UNPACK_H__ -#define UNPACK_H__ - -#include "ruby.h" - -void Init_msgpack_unpack(VALUE mMessagePack); - -#endif /* unpack.h */ - diff --git a/ruby/version.rb b/ruby/version.rb deleted file mode 100644 index f31e1212..00000000 --- a/ruby/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module MessagePack - VERSION = "0.4.8" -end