Merge branch 'master' of git://github.com/msgpack/msgpack

Reseting msgpack.erl to upstream version.
This commit is contained in:
Vincent de Phily 2010-07-09 12:35:22 +02:00
commit 64b9f0762c
24 changed files with 416 additions and 229 deletions

View File

@ -1,4 +1,14 @@
2010-07-06 version 0.5.1:
* Add msgpack_vrefbuffer_new and msgpack_vrefbuffer_free
* Add msgpack_sbuffer_new and msgpack_sbuffer_free
* Add msgpack_unpacker_next and msgpack_unpack_next
* msgpack::unpack returns void
* Add MSGPACK_VERSION{,_MAJOR,_MINOR} macros to check header version
* Add msgpack_version{,_major,_minor} functions to check library version
* ./configure supports --disable-cxx option not to build C++ API
2010-04-29 version 0.5.0:
* msgpack_object_type is changed. MSGPACK_OBJECT_NIL is now 0x00.

View File

@ -12,7 +12,6 @@ EXTRA_DIST = \
$(DOC_FILES)
doxygen:
./preprocess
./preprocess clean
cd src && $(MAKE) doxygen
./preprocess

View File

@ -1,6 +1,6 @@
AC_INIT(src/object.cpp)
AC_CONFIG_AUX_DIR(ac)
AM_INIT_AUTOMAKE(msgpack, 0.5.0)
AM_INIT_AUTOMAKE(msgpack, 0.5.1)
AC_CONFIG_HEADER(config.h)
AC_SUBST(CFLAGS)
@ -9,23 +9,31 @@ CFLAGS="-O4 -Wall $CFLAGS"
AC_SUBST(CXXFLAGS)
CXXFLAGS="-O4 -Wall $CXXFLAGS"
AC_PROG_CC
AC_PROG_CXX
AC_MSG_CHECKING([if C++ API is enabled])
AC_ARG_ENABLE(cxx,
AS_HELP_STRING([--disable-cxx],
[don't build C++ API]) )
AC_MSG_RESULT([$enable_cxx])
if test "$enable_cxx" != "no"; then
AC_PROG_CXX
AM_PROG_CC_C_O
fi
AM_CONDITIONAL(ENABLE_CXX, test "$enable_cxx" != "no")
AC_PROG_LIBTOOL
AM_PROG_AS
AM_PROG_CC_C_O
AC_LANG_PUSH([C++])
AC_CHECK_HEADERS(tr1/unordered_map)
AC_CHECK_HEADERS(tr1/unordered_set)
AC_LANG_POP([C++])
AC_MSG_CHECKING([if debug option is enabled])
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--disable-debug],
[disable assert macros and omit -g option.]) )
[disable assert macros and omit -g option]) )
AC_MSG_RESULT([$enable_debug])
if test "$enable_debug" != "no"; then
CXXFLAGS="$CXXFLAGS -g"
CFLAGS="$CFLAGS -g"
@ -33,7 +41,6 @@ else
CXXFLAGS="$CXXFLAGS -DNDEBUG"
CFLAGS="$CFLAGS -DNDEBUG"
fi
AC_MSG_RESULT($enable_debug)
AC_CACHE_CHECK([for __sync_* atomic operations], msgpack_cv_atomic_ops, [
@ -54,5 +61,15 @@ add CFLAGS="--march=i686" and CXXFLAGS="-march=i686" options to ./configure as f
])
fi
AC_OUTPUT([Makefile src/Makefile test/Makefile])
major=`echo $VERSION | sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
minor=`echo $VERSION | sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
AC_SUBST(VERSION_MAJOR, $major)
AC_SUBST(VERSION_MINOR, $minor)
AC_OUTPUT([Makefile
src/Makefile
src/msgpack/version.h
test/Makefile])

View File

@ -2,42 +2,43 @@ IF NOT EXIST include MKDIR include
IF NOT EXIST include\msgpack MKDIR include\msgpack
IF NOT EXIST include\msgpack\type MKDIR include\msgpack\type
IF NOT EXIST include\msgpack\type\tr1 MKDIR include\msgpack\type\tr1
copy msgpack\pack_define.h include\msgpack\
copy msgpack\pack_template.h include\msgpack\
copy msgpack\unpack_define.h include\msgpack\
copy msgpack\unpack_template.h include\msgpack\
copy msgpack\sysdep.h include\msgpack\
copy msgpack.h include\
copy msgpack\sbuffer.h include\msgpack\
copy msgpack\vrefbuffer.h include\msgpack\
copy msgpack\zbuffer.h include\msgpack\
copy msgpack\pack.h include\msgpack\
copy msgpack\unpack.h include\msgpack\
copy msgpack\object.h include\msgpack\
copy msgpack\zone.h include\msgpack\
copy msgpack.hpp include\
copy msgpack\sbuffer.hpp include\msgpack\
copy msgpack\vrefbuffer.hpp include\msgpack\
copy msgpack\zbuffer.hpp include\msgpack\
copy msgpack\pack.hpp include\msgpack\
copy msgpack\unpack.hpp include\msgpack\
copy msgpack\object.hpp include\msgpack\
copy msgpack\zone.hpp include\msgpack\
copy msgpack\type.hpp include\msgpack\type\
copy msgpack\type\bool.hpp include\msgpack\type\
copy msgpack\type\float.hpp include\msgpack\type\
copy msgpack\type\int.hpp include\msgpack\type\
copy msgpack\type\list.hpp include\msgpack\type\
copy msgpack\type\deque.hpp include\msgpack\type\
copy msgpack\type\map.hpp include\msgpack\type\
copy msgpack\type\nil.hpp include\msgpack\type\
copy msgpack\type\pair.hpp include\msgpack\type\
copy msgpack\type\raw.hpp include\msgpack\type\
copy msgpack\type\set.hpp include\msgpack\type\
copy msgpack\type\string.hpp include\msgpack\type\
copy msgpack\type\vector.hpp include\msgpack\type\
copy msgpack\type\tuple.hpp include\msgpack\type\
copy msgpack\type\define.hpp include\msgpack\type\
copy msgpack\type\tr1\unordered_map.hpp include\msgpack\type\
copy msgpack\type\tr1\unordered_set.hpp include\msgpack\type\
copy src\msgpack\pack_define.h include\msgpack\
copy src\msgpack\pack_template.h include\msgpack\
copy src\msgpack\unpack_define.h include\msgpack\
copy src\msgpack\unpack_template.h include\msgpack\
copy src\msgpack\sysdep.h include\msgpack\
copy src\msgpack.h include\
copy src\msgpack\sbuffer.h include\msgpack\
copy src\msgpack\version.h include\msgpack\
copy src\msgpack\vrefbuffer.h include\msgpack\
copy src\msgpack\zbuffer.h include\msgpack\
copy src\msgpack\pack.h include\msgpack\
copy src\msgpack\unpack.h include\msgpack\
copy src\msgpack\object.h include\msgpack\
copy src\msgpack\zone.h include\msgpack\
copy src\msgpack.hpp include\
copy src\msgpack\sbuffer.hpp include\msgpack\
copy src\msgpack\vrefbuffer.hpp include\msgpack\
copy src\msgpack\zbuffer.hpp include\msgpack\
copy src\msgpack\pack.hpp include\msgpack\
copy src\msgpack\unpack.hpp include\msgpack\
copy src\msgpack\object.hpp include\msgpack\
copy src\msgpack\zone.hpp include\msgpack\
copy src\msgpack\type.hpp include\msgpack\type\
copy src\msgpack\type\bool.hpp include\msgpack\type\
copy src\msgpack\type\float.hpp include\msgpack\type\
copy src\msgpack\type\int.hpp include\msgpack\type\
copy src\msgpack\type\list.hpp include\msgpack\type\
copy src\msgpack\type\deque.hpp include\msgpack\type\
copy src\msgpack\type\map.hpp include\msgpack\type\
copy src\msgpack\type\nil.hpp include\msgpack\type\
copy src\msgpack\type\pair.hpp include\msgpack\type\
copy src\msgpack\type\raw.hpp include\msgpack\type\
copy src\msgpack\type\set.hpp include\msgpack\type\
copy src\msgpack\type\string.hpp include\msgpack\type\
copy src\msgpack\type\vector.hpp include\msgpack\type\
copy src\msgpack\type\tuple.hpp include\msgpack\type\
copy src\msgpack\type\define.hpp include\msgpack\type\
copy src\msgpack\type\tr1\unordered_map.hpp include\msgpack\type\
copy src\msgpack\type\tr1\unordered_set.hpp include\msgpack\type\

View File

@ -157,7 +157,7 @@
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\objectc.c"
RelativePath=".\src\objectc.c"
>
<FileConfiguration
Name="Debug|Win32"
@ -177,7 +177,7 @@
</FileConfiguration>
</File>
<File
RelativePath=".\unpack.c"
RelativePath=".\src\unpack.c"
>
<FileConfiguration
Name="Debug|Win32"
@ -197,7 +197,7 @@
</FileConfiguration>
</File>
<File
RelativePath=".\vrefbuffer.c"
RelativePath=".\src\version.c"
>
<FileConfiguration
Name="Debug|Win32"
@ -217,7 +217,7 @@
</FileConfiguration>
</File>
<File
RelativePath=".\zone.c"
RelativePath=".\src\vrefbuffer.c"
>
<FileConfiguration
Name="Debug|Win32"
@ -237,7 +237,27 @@
</FileConfiguration>
</File>
<File
RelativePath=".\object.cpp"
RelativePath=".\src\zone.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\object.cpp"
>
</File>
</Filter>
@ -247,23 +267,23 @@
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\msgpack\pack_define.h"
RelativePath=".\src\msgpack\pack_define.h"
>
</File>
<File
RelativePath=".\msgpack\pack_template.h"
RelativePath=".\src\msgpack\pack_template.h"
>
</File>
<File
RelativePath=".\msgpack\sysdep.h"
RelativePath=".\src\msgpack\sysdep.h"
>
</File>
<File
RelativePath=".\msgpack\unpack_define.h"
RelativePath=".\src\msgpack\unpack_define.h"
>
</File>
<File
RelativePath=".\msgpack\unpack_template.h"
RelativePath=".\src\msgpack\unpack_template.h"
>
</File>
</Filter>

View File

@ -4,9 +4,14 @@ lib_LTLIBRARIES = libmsgpack.la
libmsgpack_la_SOURCES = \
unpack.c \
objectc.c \
version.c \
vrefbuffer.c \
zone.c \
zone.c
if ENABLE_CXX
libmsgpack_la_SOURCES += \
object.cpp
endif
# -version-info CURRENT:REVISION:AGE
libmsgpack_la_LDFLAGS = -version-info 3:0:0
@ -18,15 +23,12 @@ lib_LTLIBRARIES += libmsgpackc.la
libmsgpackc_la_SOURCES = \
unpack.c \
objectc.c \
version.c \
vrefbuffer.c \
zone.c
libmsgpackc_la_LDFLAGS = -version-info 2:0:0
# work around for duplicated file name
kumo_manager_CFLAGS = $(AM_CFLAGS)
kumo_manager_CXXFLAGS = $(AM_CXXFLAGS)
nobase_include_HEADERS = \
msgpack/pack_define.h \
@ -36,12 +38,16 @@ nobase_include_HEADERS = \
msgpack/sysdep.h \
msgpack.h \
msgpack/sbuffer.h \
msgpack/version.h \
msgpack/vrefbuffer.h \
msgpack/zbuffer.h \
msgpack/pack.h \
msgpack/unpack.h \
msgpack/object.h \
msgpack/zone.h \
msgpack/zone.h
if ENABLE_CXX
nobase_include_HEADERS += \
msgpack.hpp \
msgpack/sbuffer.hpp \
msgpack/vrefbuffer.hpp \
@ -67,8 +73,10 @@ nobase_include_HEADERS = \
msgpack/type/define.hpp \
msgpack/type/tr1/unordered_map.hpp \
msgpack/type/tr1/unordered_set.hpp
endif
EXTRA_DIST = \
msgpack/version.h.in \
msgpack/zone.hpp.erb \
msgpack/type/define.hpp.erb \
msgpack/type/tuple.hpp.erb

View File

@ -26,3 +26,5 @@
#include "msgpack/unpack.h"
#include "msgpack/sbuffer.h"
#include "msgpack/vrefbuffer.h"
#include "msgpack/version.h"

View File

@ -187,5 +187,20 @@ inline void operator<< (
} // namespace msgpack
//inline std::ostream& operator<< (std::ostream& o, const msgpack::type::tuple<>& v) {
// return o << "[]";
//}
//<%0.upto(GENERATION_LIMIT) {|i|%>
//template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
//inline std::ostream& operator<< (std::ostream& o,
// const msgpack::type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>& v) {
// return o << "["
// <%0.upto(i) {|j|%>
// <<<%if j != 0 then%> ", " <<<%end%> v.template get<<%=j%>>()<%}%>
// << "]";
//}
//<%}%>
#endif /* msgpack/type/tuple.hpp */

View File

@ -0,0 +1,40 @@
/*
* MessagePack for C version information
*
* Copyright (C) 2008-2009 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 MSGPACK_VERSION_H__
#define MSGPACK_VERSION_H__
#ifdef __cplusplus
extern "C" {
#endif
const char* msgpack_version(void);
int msgpack_version_major(void);
int msgpack_version_minor(void);
#define MSGPACK_VERSION "@VERSION@"
#define MSGPACK_VERSION_MAJOR @VERSION_MAJOR@
#define MSGPACK_VERSION_MINOR @VERSION_MINOR@
#ifdef __cplusplus
}
#endif
#endif /* msgpack/version.h */

17
cpp/src/version.c Normal file
View File

@ -0,0 +1,17 @@
#include "msgpack.h"
const char* msgpack_version(void)
{
return MSGPACK_VERSION;
}
int msgpack_version_major(void)
{
return MSGPACK_VERSION_MAJOR;
}
int msgpack_version_minor(void)
{
return MSGPACK_VERSION_MINOR;
}

View File

@ -13,6 +13,7 @@ check_PROGRAMS = \
convert \
buffer \
cases \
version \
msgpackc_test \
msgpack_test
@ -37,6 +38,8 @@ buffer_LDADD = -lz
cases_SOURCES = cases.cc
version_SOURCES = version.cc
msgpackc_test_SOURCES = msgpackc_test.cpp
msgpack_test_SOURCES = msgpack_test.cpp

13
cpp/test/version.cc Normal file
View File

@ -0,0 +1,13 @@
#include <msgpack.hpp>
#include <gtest/gtest.h>
TEST(version, print)
{
printf("MSGPACK_VERSION : %s\n", MSGPACK_VERSION);
printf("MSGPACK_VERSION_MAJOR : %d\n", MSGPACK_VERSION_MAJOR);
printf("MSGPACK_VERSION_MINOR : %d\n", MSGPACK_VERSION_MINOR);
printf("msgpack_version() : %s\n", msgpack_version());
printf("msgpack_version_major() : %d\n", msgpack_version_major());
printf("msgpack_version_minor() : %d\n", msgpack_version_minor());
}

View File

@ -2,18 +2,8 @@ MessagePack for Erlang
======================
Binary-based efficient object serialization library.
## Status
see wiki ( http://redmine.msgpack.org/projects/msgpack/wiki/QuickStartErlang ) for details
still in development.
# Status
TODOs:
- decide string specification.
## Installation
## Example
## License
-
0.1.0 released.

View File

@ -19,54 +19,48 @@
-author('kuenishi+msgpack@gmail.com').
%% tuples, atoms are not supported. lists, integers, double, and so on.
%% see http://msgpack.sourceforge.jp/spec for
%% supported formats. APIs are almost compatible
%% for C API (http://msgpack.sourceforge.jp/c:doc)
%% see http://msgpack.sourceforge.jp/spec for supported formats.
%% APIs are almost compatible with C API (http://msgpack.sourceforge.jp/c:doc)
%% except buffering functions (both copying and zero-copying).
-export([pack/1, unpack/1, unpack_all/1]).
-export([pack_map/1]).
% compile:
% erl> c(msgpack).
% erl> S = <some term>.
% erl> {S, <<>>} = msgpack:unpack( msgpack:pack(S) ).
-type reason() :: enomem | {badarg, term()}.
-type msgpack_term() :: [msgpack_term()] | {[{msgpack_term(),msgpack_term()}]} | integer() | float() | binary().
-type reason() :: enomem | badarg | no_code_matches | undefined.
-type msgpack_term() :: [msgpack_term()]
| {[{msgpack_term(),msgpack_term()}]}
| integer() | float() | binary().
% ===== external APIs ===== %
-spec pack(Term::msgpack_term()) -> binary() | {error, reason()}.
pack(Term)->
try
pack_(Term)
catch
error:Error when is_tuple(Error), element(1, Error) =:= error ->
Error;
throw:Exception ->
erlang:display(Exception),
{error, Exception}
end.
% @doc Pack one erlang term into an msgpack message.
-spec pack(Term::msgpack_term()) -> binary() | reason().
pack(O) when is_integer(O) andalso O < 0 ->
pack_int_(O);
pack(O) when is_integer(O) ->
pack_uint_(O);
pack(O) when is_float(O) ->
pack_double(O);
pack(nil) ->
pack_nil();
pack(true) ->
pack_true();
pack(false) ->
pack_false();
pack(Bin) when is_binary(Bin) ->
pack_raw(Bin);
pack(List) when is_list(List) ->
pack_array(List);
pack({Map}) when is_list(Map) ->
pack_map(Map);
pack(Map) when is_tuple(Map), element(1,Map)=:=dict ->
pack_map(dict:from_list(Map));
pack(Other) ->
{error, {badarg, Other}}.
% @doc Unpack one (possibly deeply nested) msgpack message into an erlang term.
% If failed in decoding and not end, get more data
% and feed more Bin into this function.
-spec unpack( binary() ) -> {Decoded::msgpack_term(), Rest::binary()} | {more, undefined} | {error, reason()}.
unpack(Bin) when is_binary(Bin) ->
unpack_(Bin);
unpack(Other) ->
{error, {badarg, Other}}.
% unpacking.
% if failed in decoding and not end, get more data
% and feed more Bin into this function.
% TODO: error case for imcomplete format when short for any type formats.
-spec unpack( Bin::binary() )-> {msgpack_term(), binary()} | {error, reason()}.
unpack(Bin)->
try
unpack_(Bin)
catch
error:Error when is_tuple(Error), element(1, Error) =:= error ->
Error;
throw:Exception ->
{error, Exception}
end.
-spec unpack_all( binary() ) -> [msgpack_term()].
unpack_all(Data)->
@ -77,9 +71,44 @@ unpack_all(Data)->
[Term|unpack_all(Binary)]
end.
-spec pack_map(M::[{msgpack_term(),msgpack_term()}])-> binary() | {error, badarg}.
pack_map(M)->
case length(M) of
Len when Len < 16 ->
<< 2#1000:4, Len:4/integer-unit:1, (pack_map_(M, <<>>))/binary >>;
Len when Len < 16#10000 -> % 65536
<< 16#DE:8, Len:16/big-unsigned-integer-unit:1, (pack_map_(M, <<>>))/binary >>;
Len ->
<< 16#DF:8, Len:32/big-unsigned-integer-unit:1, (pack_map_(M, <<>>))/binary >>
end.
% ===== internal APIs ===== %
% pack them all
-spec pack_(msgpack_term()) -> binary() | no_return().
pack_(I) when is_integer(I) andalso I < 0 ->
pack_int_(I);
pack_(I) when is_integer(I) ->
pack_uint_(I);
pack_(F) when is_float(F) ->
pack_double(F);
pack_(nil) ->
<< 16#C0:8 >>;
pack_(true) ->
<< 16#C3:8 >>;
pack_(false) ->
<< 16#C2:8 >>;
pack_(Bin) when is_binary(Bin) ->
pack_raw(Bin);
pack_(List) when is_list(List) ->
pack_array(List);
pack_({Map}) when is_list(Map) ->
pack_map(Map);
pack_(Map) when is_tuple(Map), element(1,Map)=:=dict ->
pack_map(dict:to_list(Map));
pack_(_Other) ->
throw({error, undefined}).
% positive fixnum
pack_uint_(N) when N < 128 ->
<< 2#0:1, N:7 >>;
@ -97,28 +126,23 @@ pack_uint_(N) ->
<< 16#CF:8, N:64/big-unsigned-integer-unit:1 >>.
% negative fixnum
pack_int_(N) when N >= -32->
pack_int_(N) when is_integer(N) , N >= -32->
<< 2#111:3, N:5 >>;
% int 8
pack_int_(N) when N >= -256 ->
<< 16#D0:8, N:8 >>;
pack_int_(N) when N > -128 ->
<< 16#D0:8, N:8/big-signed-integer-unit:1 >>;
% int 16
pack_int_(N) when N >= -65536 ->
pack_int_(N) when N > -32768 ->
<< 16#D1:8, N:16/big-signed-integer-unit:1 >>;
% int 32
pack_int_(N) when N >= -16#FFFFFFFF ->
pack_int_(N) when N > -16#FFFFFFFF ->
<< 16#D2:8, N:32/big-signed-integer-unit:1 >>;
% int 64
pack_int_(N) ->
<< 16#D3:8, N:64/big-signed-integer-unit:1 >>.
% nil/true/false
pack_nil() -> << 16#C0:8 >>.
pack_true()-> << 16#C3:8 >>.
pack_false()-> << 16#C2:8 >>.
% float : erlang's float is always IEEE 754 64bit format.
%pack_float(F) when is_float(F)->
% pack_float(F) when is_float(F)->
% << 16#CA:8, F:32/big-float-unit:1 >>.
% pack_double(F).
% double
@ -146,107 +170,107 @@ pack_array(L) ->
Len ->
<< 16#DD:8, Len:32/big-unsigned-integer-unit:1, (pack_array_(L, <<>>))/binary >>
end.
pack_array_([], Acc) -> Acc;
pack_array_([Head|Tail], Acc) ->
pack_array_(Tail, <<Acc/binary, (pack(Head))/binary>>).
pack_array_(Tail, <<Acc/binary, (pack_(Head))/binary>>).
% FIXME! this should be tail-recursive and without lists:reverse/1
unpack_array_(Remain, 0, RetList) -> {lists:reverse(RetList), Remain};
unpack_array_(Bin, RestLen, RetList) ->
case unpack(Bin) of
{more, undefined} -> {more, undefined};
{Term, Rest}-> unpack_array_(Rest, RestLen-1, [Term|RetList])
end.
% FIXME: write test for pack_map/1
pack_map(M)->
case length(M) of
Len when Len < 16 ->
<< 2#1000:4, Len:4/integer-unit:1, (pack_map_(M, <<>>))/binary >>;
Len when Len < 16#10000 -> % 65536
<< 16#DE:8, Len:16/big-unsigned-integer-unit:1, (pack_map_(M, <<>>))/binary >>;
Len ->
<< 16#DF:8, Len:32/big-unsigned-integer-unit:1, (pack_map_(M, <<>>))/binary >>
end.
% Users SHOULD NOT send too long list: this uses lists:reverse/1
unpack_array_(Remain, 0, Acc) when is_binary(Remain)-> {lists:reverse(Acc), Remain};
unpack_array_(<<>>, RestLen, _) when RestLen > 0 -> throw(short);
unpack_array_(Bin, RestLen, Acc) when is_binary(Bin)->
{Term, Rest}=unpack_(Bin),
unpack_array_(Rest, RestLen-1, [Term|Acc]).
pack_map_([], Acc) -> Acc;
pack_map_([{Key,Value}|Tail], Acc) ->
pack_map_(Tail, << Acc/binary, (pack(Key))/binary, (pack(Value))/binary>>).
pack_map_(Tail, << Acc/binary, (pack_(Key))/binary, (pack_(Value))/binary>>).
% FIXME: write test for unpack_map/1
-spec unpack_map_(binary(), non_neg_integer(), [{msgpack_term(), msgpack_term()}]) -> {more, undefined} | {any(), binary()} | {error, reason()}.
% Users SHOULD NOT send too long list: this uses lists:reverse/1
-spec unpack_map_(binary(), non_neg_integer(), [{msgpack_term(), msgpack_term()}])->
{[{msgpack_term(), msgpack_term()}], binary()} | no_return().
unpack_map_(Bin, 0, Acc) -> {{lists:reverse(Acc)}, Bin};
unpack_map_(<<>>, _, _ ) -> throw(short);
unpack_map_(Bin, Len, Acc) ->
case unpack(Bin) of
{more, undefined} -> {more, undefined};
{Key, Rest} ->
case unpack(Rest) of
{more, undefined} -> {more, undefined};
{Value, Rest2} ->
unpack_map_(Rest2,Len-1,[{Key,Value}|Acc])
end
end.
-spec unpack_(Payload::binary()) -> {more, undefined} | {msgpack_term(), binary()} | {error, reason()}.
% Atoms
unpack_(<<16#C0, Rest/binary>>) -> {nil, Rest};
unpack_(<<16#C2, Rest/binary>>) -> {false, Rest};
unpack_(<<16#C3, Rest/binary>>) -> {true, Rest};
{Key, Rest} = unpack_(Bin),
{Value, Rest2} = unpack_(Rest),
unpack_map_(Rest2,Len-1,[{Key,Value}|Acc]).
% unpack then all
-spec unpack_(Bin::binary()) -> {msgpack_term(), binary()} | {error, reason()} | no_return().
unpack_(Bin) when not is_binary(Bin)-> throw(badarg);
unpack_(Bin) when bit_size(Bin) >= 8 ->
case Bin of
% ATOMS
<<16#C0, Rest/binary>> -> {nil, Rest};
<<16#C2, Rest/binary>> -> {false, Rest};
<<16#C3, Rest/binary>> -> {true, Rest};
% Floats
unpack_(<<16#CA, Val:32/float-unit:1, Rest/binary>>) -> {Val, Rest};
unpack_(<<16#CB, Val:64/float-unit:1, Rest/binary>>) -> {Val, Rest};
<<16#CA, V:32/float-unit:1, Rest/binary>> -> {V, Rest};
<<16#CB, V:64/float-unit:1, Rest/binary>> -> {V, Rest};
% Unsigned integers
unpack_(<<16#CC, Val:8/unsigned-integer, Rest/binary>>) -> {Val, Rest};
unpack_(<<16#CD, Val:16/big-unsigned-integer-unit:1, Rest/binary>>) -> {Val, Rest};
unpack_(<<16#CE, Val:32/big-unsigned-integer-unit:1, Rest/binary>>) -> {Val, Rest};
unpack_(<<16#CF, Val:64/big-unsigned-integer-unit:1, Rest/binary>>) -> {Val, Rest};
<<16#CC, V:8/unsigned-integer, Rest/binary>> -> {V, Rest};
<<16#CD, V:16/big-unsigned-integer-unit:1, Rest/binary>> -> {V, Rest};
<<16#CE, V:32/big-unsigned-integer-unit:1, Rest/binary>> -> {V, Rest};
<<16#CF, V:64/big-unsigned-integer-unit:1, Rest/binary>> -> {V, Rest};
% Signed integers
unpack_(<<16#D0, Val:8/signed-integer, Rest/binary>>) -> {Val, Rest};
unpack_(<<16#D1, Val:16/big-signed-integer-unit:1, Rest/binary>>) -> {Val, Rest};
unpack_(<<16#D2, Val:32/big-signed-integer-unit:1, Rest/binary>>) -> {Val, Rest};
unpack_(<<16#D3, Val:64/big-signed-integer-unit:1, Rest/binary>>) -> {Val, Rest};
<<16#D0, V:8/signed-integer, Rest/binary>> -> {V, Rest};
<<16#D1, V:16/big-signed-integer-unit:1, Rest/binary>> -> {V, Rest};
<<16#D2, V:32/big-signed-integer-unit:1, Rest/binary>> -> {V, Rest};
<<16#D3, V:64/big-signed-integer-unit:1, Rest/binary>> -> {V, Rest};
% Raw bytes
unpack_(<<16#DA, Len:16/unsigned-integer-unit:1, Val:Len/binary, Rest/binary>>) -> {Val, Rest};
unpack_(<<16#DB, Len:32/unsigned-integer-unit:1, Val:Len/binary, Rest/binary>>) -> {Val, Rest};
<<16#DA, L:16/unsigned-integer-unit:1, V:L/binary, Rest/binary>> -> {V, Rest};
<<16#DB, L:32/unsigned-integer-unit:1, V:L/binary, Rest/binary>> -> {V, Rest};
% Arrays
unpack_(<<16#DC, Len:16/big-unsigned-integer-unit:1, Rest/binary>>) -> unpack_array_(Rest, Len, []);
unpack_(<<16#DD, Len:32/big-unsigned-integer-unit:1, Rest/binary>>) -> unpack_array_(Rest, Len, []);
<<16#DC, L:16/big-unsigned-integer-unit:1, Rest/binary>> -> unpack_array_(Rest, L, []);
<<16#DD, L:32/big-unsigned-integer-unit:1, Rest/binary>> -> unpack_array_(Rest, L, []);
% Maps
unpack_(<<16#DE, Len:16/big-unsigned-integer-unit:1, Rest/binary>>) -> unpack_map_(Rest, Len, []);
unpack_(<<16#DF, Len:32/big-unsigned-integer-unit:1, Rest/binary>>) -> unpack_map_(Rest, Len, []);
<<16#DE, L:16/big-unsigned-integer-unit:1, Rest/binary>> -> unpack_map_(Rest, L, []);
<<16#DF, L:32/big-unsigned-integer-unit:1, Rest/binary>> -> unpack_map_(Rest, L, []);
% Tag-encoded lengths (kept last, for speed)
unpack_(<<0:1, Val:7, Rest/binary>>) -> {Val, Rest}; % pos fixnum
unpack_(<<2#111:3, Val:5, Rest/binary>>) -> {Val - 2#100000, Rest}; % neg fixnum
unpack_(<<2#101:3, Len:5, Val:Len/binary, Rest/binary>>) -> {Val, Rest}; % fixraw
unpack_(<<2#1001:4, Len:4, Rest/binary>>) -> unpack_array_(Rest, Len, []); % fixarray
unpack_(<<2#1000:4, Len:4, Rest/binary>>) -> unpack_map_(Rest, Len, []); % fixmap
<<0:1, V:7, Rest/binary>> -> {V, Rest}; % positive int
<<2#111:3, V:5, Rest/binary>> -> {V - 2#100000, Rest}; % negative int
<<2#101:3, L:5, V:L/binary, Rest/binary>> -> {V, Rest}; % raw bytes
<<2#1001:4, L:4, Rest/binary>> -> unpack_array_(Rest, L, []); % array
<<2#1000:4, L:4, Rest/binary>> -> unpack_map_(Rest, L, []); % map
% Incomplete / invalid data
unpack_(<<F:8, Rest/binary>>) when F==16#C1; F==16#C4; F==16#C5; F==16#C6; F==16#C7; F==16#C8; F==16#C9; F==16#D5; F==16#D6; F==16#D7; F==16#D8; F==16#D9->
{error, {badarg, <<F, Rest/binary>>}};
unpack_(_Bin) ->
{more, undefined}.
<<F:16, _/binary>> when F==16#CA; F==16#CB; F==16#CC;
F==16#CD; F==16#CE; F==16#CF;
F==16#D0; F==16#D1; F==16#D2;
F==16#D3; F==16#DA; F==16#DB;
F==16#DC; F==16#DD; F==16#DE;
F==16#DF ->
throw(short);
<<F:16, _/binary>> when F==16#C1;
F==16#C7; F==16#C8; F==16#C9;
F==16#D5; F==16#D6; F==16#D7;
F==16#D8; F==16#D9 ->
throw(badarg);
_ ->
throw(short) % or unknown/badarg?
end;
unpack_(<<>>)-> throw(short);
unpack_(<<2#101:3, _/binary>>) -> throw(short).
% ===== test codes ===== %
-include_lib("eunit/include/eunit.hrl").
-ifdef(EUNIT).
compare_all([], [])-> ok;
compare_all([], R)-> {toomuchrhs, R};
compare_all(L, [])-> {toomuchlhs, L};
compare_all([], R)-> {toomuchrhs, R};
compare_all(L, [])-> {toomuchlhs, L};
compare_all([LH|LTL], [RH|RTL]) ->
LH=RH,
?assertEqual(LH, RH),
compare_all(LTL, RTL).
test_([]) -> 0;
test_([Term|Rest])->
Pack = msgpack:pack(Term),
?assertEqual({Term, <<>>}, msgpack:unpack( Pack )),
1+test_(Rest).
test_data()->
[true, false, nil,
0, 1, 2, 123, 512, 1230, 678908, 16#FFFFFFFFFF,
@ -256,6 +280,7 @@ test_data()->
<<"hogehoge">>, <<"243546rf7g68h798j", 0, 23, 255>>,
<<"hoasfdafdas][">>,
[0,42, <<"sum">>, [1,2]], [1,42, nil, [3]],
-234, -40000, -16#10000000, -16#100000000,
42
].
@ -265,9 +290,9 @@ basic_test()->
Passed = length(Tests).
port_test()->
Port = open_port({spawn, "ruby ../test/crosslang.rb"}, [binary]),
Tests = test_data(),
{[Tests],<<>>} = msgpack:unpack(msgpack:pack([Tests])),
Port = open_port({spawn, "ruby ../test/crosslang.rb"}, [binary]),
true = port_command(Port, msgpack:pack(Tests) ),
receive
{Port, {data, Data}}-> {Tests, <<>>}=msgpack:unpack(Data)
@ -278,7 +303,7 @@ test_p(Len,Term,OrigBin,Len) ->
{Term, <<>>}=msgpack:unpack(OrigBin);
test_p(I,_,OrigBin,Len) when I < Len->
<<Bin:I/binary, _/binary>> = OrigBin,
?assertEqual({more, undefined}, msgpack:unpack(Bin)).
?assertEqual({error,short}, msgpack:unpack(Bin)).
partial_test()-> % error handling test.
Term = lists:seq(0, 45),
@ -288,10 +313,7 @@ partial_test()-> % error handling test.
long_test()->
Longer = lists:seq(0, 655),
% Longest = lists:seq(0,12345),
{Longer, <<>>} = msgpack:unpack(msgpack:pack(Longer)),
% {Longest, <<>>} = msgpack:unpack(msgpack:pack(Longest)).
ok.
{Longer, <<>>} = msgpack:unpack(msgpack:pack(Longer)).
map_test()->
Ints = lists:seq(0, 65),
@ -301,6 +323,7 @@ map_test()->
ok.
unknown_test()->
Port = open_port({spawn, "ruby testcase_generator.rb"}, [binary]),
Tests = [0, 1, 2, 123, 512, 1230, 678908,
-1, -23, -512, -1230, -567898,
<<"hogehoge">>, <<"243546rf7g68h798j">>,
@ -308,23 +331,22 @@ unknown_test()->
-234.4355, 1.0e-34, 1.0e64,
[23, 234, 0.23],
[0,42,<<"sum">>, [1,2]], [1,42, nil, [3]],
dict:from_list([{1,2},{<<"hoge">>,nil}]),
{[{1,2},{<<"hoge">>,nil}]}, % map
-234, -50000,
42
],
Port = open_port({spawn, "ruby testcase_generator.rb"}, [binary]),
receive
{Port, {data, Data}}->
compare_all(Tests, msgpack:unpack_all(Data))
after 1024-> ?assert(false) end,
{Port, {data, Data}}-> compare_all(Tests, msgpack:unpack_all(Data))
after 1024-> ?assert(false) end,
port_close(Port).
test_([]) -> 0;
test_([S|Rest])->
Pack = msgpack:pack(S),
?assertEqual({S, <<>>}, msgpack:unpack(Pack)),
1+test_(Rest).
other_test()->
?assertEqual({more,undefined}, msgpack:unpack(<<>>)).
?assertEqual({error,short},msgpack:unpack(<<>>)).
benchmark_test()->
Data=[test_data() || _ <- lists:seq(0, 10000)],
S=?debugTime(" serialize", msgpack:pack(Data)),
{Data,<<>>}=?debugTime("deserialize", msgpack:unpack(S)),
?debugFmt("for ~p KB test data.", [byte_size(S) div 1024]).
-endif.

View File

@ -45,6 +45,7 @@ objs = [0, 1, 2, 123, 512, 1230, 678908,
[23, 234, 0.23],
[0,42,"sum", [1,2]], [1,42, nil, [3]],
{ 1 => 2, "hoge" => nil },
-234, -50000,
42
]
begin

View File

@ -0,0 +1,6 @@
2010-06-29 version 0.4.3:
* Adds MessagePack::VERSION constant
* Fixes SEGV problem caused by GC bug at MessagePack_Unpacker_mark

View File

@ -1,4 +1,5 @@
require 'mkmf'
$CFLAGS << " -I.. -Wall -O4"
require './version.rb'
$CFLAGS << %[ -I.. -Wall -O4 -DMESSAGEPACK_VERSION=\\"#{MessagePack::VERSION}\\"]
create_makefile('msgpack')

View File

@ -8,6 +8,7 @@ cp pack.h ext/
cp rbinit.c ext/
cp unpack.c ext/
cp unpack.h ext/
cp version.rb ext/
cp ../msgpack/pack_define.h msgpack/
cp ../msgpack/pack_template.h msgpack/
cp ../msgpack/unpack_define.h msgpack/
@ -19,6 +20,8 @@ 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

View File

@ -1,7 +1,8 @@
require './version.rb'
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "msgpack"
s.version = "0.4.2"
s.version = MessagePack::VERSION
s.summary = "MessagePack, a binary-based efficient data interchange format."
s.author = "FURUHASHI Sadayuki"
s.email = "frsyuki@users.sourceforge.jp"

View File

@ -43,7 +43,9 @@ static VALUE mMessagePack;
void Init_msgpack(void)
{
mMessagePack = rb_define_module("MessagePack");
rb_define_const(mMessagePack, "VERSION", rb_str_new2(MESSAGEPACK_VERSION));
Init_msgpack_unpack(mMessagePack);
Init_msgpack_pack(mMessagePack);
}

View File

@ -5,3 +5,4 @@ rescue LoadError
require File.dirname(__FILE__) + '/../lib/msgpack'
end
#GC.stress = true

View File

@ -276,6 +276,10 @@ class MessagePackTestPackUnpack < Test::Unit::TestCase
assert_equal(parsed, num)
end
it "MessagePack::VERSION constant" do
p MessagePack::VERSION
end
private
def check(len, obj)
v = obj.to_msgpack

View File

@ -287,6 +287,7 @@ 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);
@ -297,6 +298,17 @@ 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.size = 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;
@ -343,14 +355,10 @@ static VALUE MessagePack_Unpacker_initialize(int argc, VALUE *argv, VALUE self)
UNPACKER(self, mp);
template_init(mp);
mp->user.finished = 0;
mp->user.offset = 0;
mp->user.buffer.size = 0;
mp->user.buffer.free = 0;
mp->user.buffer.ptr = NULL;
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);
return self;
}
@ -638,7 +646,7 @@ static VALUE MessagePack_Unpacker_execute_impl(VALUE self, VALUE data,
* Document-method: MessagePack::Unpacker#execute_limit
*
* call-seq:
* unpacker.unpack_limit(data, offset, limit) -> next offset
* unpacker.execute_limit(data, offset, limit) -> next offset
*
* Deserializes one object over the specified buffer from _offset_ bytes upto _limit_ bytes.
*
@ -660,7 +668,7 @@ static VALUE MessagePack_Unpacker_execute_limit(VALUE self, VALUE data,
* Document-method: MessagePack::Unpacker#execute
*
* call-seq:
* unpacker.unpack(data, offset) -> next offset
* unpacker.execute(data, offset) -> next offset
*
* Deserializes one object over the specified buffer from _offset_ bytes.
*

3
ruby/version.rb Normal file
View File

@ -0,0 +1,3 @@
module MessagePack
VERSION = "0.4.3"
end