Compare commits

..

435 Commits

Author SHA1 Message Date
frsyuki
f5453d38ec cpp: version 0.5.2 2010-07-14 17:06:16 +09:00
frsyuki
331bf0af21 cpp: type::raw_ref::str(), operator==, operator!=, operator< and operator> are now const 2010-07-14 17:04:41 +09:00
frsyuki
167e2475d8 cpp: generate version.h using AC_OUTPUT macro in ./configure 2010-07-06 23:30:15 +09:00
frsyuki
fe77251242 cpp: fixes missing dependency to generate version.h 2010-07-06 19:16:49 +09:00
frsyuki
0c331d2887 cpp: updates vcproj 2010-07-06 18:18:28 +09:00
frsyuki
39facd5dc6 cpp: version 0.5.1 2010-07-06 17:59:07 +09:00
frsyuki
a2bd5ae638 cpp: ./configure supports --disable-cxx option not to build/install C++ API 2010-07-06 17:45:15 +09:00
frsyuki
c57f616141 cpp: adds MSGPACK_VERSION{,_MAJOR,_MINOR} macros and msgpack{,_major,_minor} functions 2010-07-06 17:10:25 +09:00
frsyuki
3af10a1d00 cpp: adds MSGPACK_VERSION{,_MAJOR,_MINOR} macros and msgpack{,_major,_minor} functions 2010-07-06 17:00:58 +09:00
frsyuki
b3987e2402 Merge branch 'master' of github.com:msgpack/msgpack 2010-07-06 12:26:30 +09:00
frsyuki
71dd44f430 cpp: adds operator<<(std::ostream&, const tuple<Type...>&) (experimental) 2010-07-06 12:26:21 +09:00
UENISHI Kota
584462f9b9 erlang: improved spec. 2010-07-01 01:16:25 +09:00
UENISHI Kota
ff5d5d7cbc erlang: updated the comments 2010-07-01 01:14:38 +09:00
UENISHI Kota
370e92b1a6 erlang: just a golf. 2010-07-01 01:14:20 +09:00
UENISHI Kota
2469768a85 erlang: reducing unnecessary binary matching in unpack_/2
* more efficient unpack_/1 by Vincent de Phille's code. thanks.
2010-07-01 01:07:56 +09:00
UENISHI Kota
acb8fa613e erlang: adding shorthand fix for {more, undefined} problem 2010-07-01 01:02:19 +09:00
UENISHI Kota
83b4b7d83d erlang: more suitable variable name and removing unnecessary guards. 2010-07-01 00:58:48 +09:00
frsyuki
20de730541 ruby: 0.4.3 2010-06-29 15:39:47 +09:00
frsyuki
134c27c900 Merge branch 'master' of github.com:msgpack/msgpack 2010-06-29 15:13:21 +09:00
frsyuki
123ae024c6 ruby: MessagePack::VERSION constant 2010-06-29 15:12:52 +09:00
frsyuki
34a29cd0a5 ruby: fixes SEGV problem caused by GC bug at MessagePack_Unpacker_mark. 2010-06-29 14:56:23 +09:00
frsyuki
9fffa9800a ruby: fixes RDoc of Unpacker#execute and Unpacker#execute_impl 2010-06-29 14:54:09 +09:00
UENISHI Kota
358457f49d erlang: bad wrong export.. 2010-06-29 00:25:58 +09:00
UENISHI Kota
90e305d789 erlang: explicit API for serializing proplists,
so as not to make wrong call of pack({proplists()}).
2010-06-29 00:23:49 +09:00
UENISHI Kota
b471e52e28 erlang: explicit API for serializing proplists,
so as not to make wrong call of pack({proplists()}).
2010-06-29 00:21:47 +09:00
UENISHI Kota
9b5fc37399 Merge branch 'master' of http://github.com/vincentdephily/msgpack 2010-06-29 00:10:10 +09:00
Vincent de Phily
537322e3b5 Big speedup (around 40%) of maps and arrays encoding by using proper tail recursion. 2010-06-28 14:17:44 +02:00
Vincent de Phily
279121f87f erlang: Use a simple proplist instead of a dict.
A dict is overkill (code, cpu, memory) in most cases, and proplist<->dict conversion can easily be done by the libray user if desired.
        This is in line with other erlang libraries I've seen for various encoding schemes.
        The map encoder had a bug until I looked at it (see previous commit), so I guess it wasn't used much yet and a change is ok at this stage.
        The chosen representation for maps is a tuple containing the proplist as the only element.
2010-06-28 11:56:12 +02:00
UENISHI Kota
a1b2b41cdc erlang: bugfix(serialization of -234 goes <<208,22>> while it should go int16 <<0xD1, ...>>) 2010-06-26 08:40:36 +09:00
Vincent de Phily
0cca90c21d Fix encoding of fixmap type.
The tag value was wrong, and a missing /binary flag caused an error.
2010-06-25 17:32:11 +02:00
UENISHI Kota
ad052cb510 updated readme 2010-06-25 01:26:57 +09:00
UENISHI Kota
57f0598373 erlang: code refined and tests added 2010-06-25 00:44:14 +09:00
UENISHI Kota
92d192277e erlang: unpack_map's silly bug fixed. use dict:store/3.... 2010-06-25 00:22:53 +09:00
UENISHI Kota
2cdfbd8970 erlang: testing pack_map/unpack_map with a silly bug 2010-06-24 07:26:34 +09:00
UENISHI Kota
bc0c5f0cdc erlang: (un)pack_map improved, incremental unpacking 2010-06-23 09:02:53 +09:00
UENISHI Kota
230ee3a03b erlang: too short binary to decode causes error {more, Int}. 2010-06-23 01:26:10 +09:00
UENISHI Kota
ab0bf37d30 Merge branch 'master' of ssh://github.com/msgpack/msgpack 2010-06-22 11:44:25 +09:00
UENISHI Kota
b1e66256ce erlang: external APIs' type/specs. 2010-06-22 11:28:36 +09:00
UENISHI Kota
fd80693420 erlang: tests improved and code refined. 2010-06-22 11:15:18 +09:00
Naoki INADA
f222f5ed9b Python: 0.1.4 2010-06-15 18:06:58 +09:00
INADA Naoki
59603b902a Python: add "load(s)/dump(s)" alias for compatibility to simplejson/marshal/pickle. 2010-06-15 17:51:24 +09:00
frsyuki
82a5dd6cf9 java: update 2010-06-10 14:02:58 -07:00
frsyuki
a97f9081a3 Merge branch 'master' of github.com:msgpack/msgpack 2010-06-03 22:04:36 +09:00
frsyuki
b3e0ad1303 ruby: 0.4.2 2010-06-03 22:00:15 +09:00
frsyuki
251090406a ruby: adds a test case for buffering 2010-06-03 21:52:01 +09:00
frsyuki
9c3ed173b1 ruby: fixes buffering routine 2010-06-03 21:51:40 +09:00
UENISHI Kota
7cd41aeb72 erlang: tracing crosslang.rb moving to ../test 2010-06-03 00:17:17 +09:00
UENISHI Kota
8ecaf7ad4c Merge branch 'master' of ssh://github.com/msgpack/msgpack 2010-06-03 00:14:19 +09:00
frsyuki
d4049fe593 ruby: add test/test_cases.rb 2010-06-01 16:35:21 +09:00
frsyuki
989b14b519 update test/README.md 2010-06-01 15:58:44 +09:00
frsyuki
fb3e11408c add test/cases.json 2010-06-01 15:56:29 +09:00
frsyuki
3d3af3284e cpp: adds Doxyfile 2010-06-01 08:43:30 +09:00
frsyuki
eabcf15790 cpp: update tests 2010-06-01 07:16:25 +09:00
frsyuki
684bca203a cpp: adds msgpack_unpacker_next and msgpack_unpack_next 2010-06-01 07:15:58 +09:00
frsyuki
d42ecccf6f cpp: msgpack::unpack returns void 2010-06-01 07:13:47 +09:00
frsyuki
5a92c861e3 cpp: adds msgpack_vrefbuffer_new and msgpack_vrefbuffer_free 2010-06-01 07:11:01 +09:00
frsyuki
103b14ea3c cpp: adds msgpack_zbuffer_new and msgpack_zbuffer_free 2010-06-01 07:10:39 +09:00
frsyuki
e49f091b4e cpp: adds msgpack_sbuffer_new and msgpack_sbuffer_free 2010-06-01 07:10:17 +09:00
frsyuki
6056f93910 cpp: add cases.mpac test 2010-06-01 05:15:36 +09:00
frsyuki
18fa2d1af4 Merge branch 'master' of github.com:msgpack/msgpack 2010-06-01 04:47:37 +09:00
frsyuki
062ed8a4c4 add test/cases.mpac and test/cases_compact.mpac 2010-06-01 04:47:28 +09:00
UENISHI Kota
49f3872d04 erlang: temporary documentation and .gitignore 2010-06-01 00:31:12 +09:00
UENISHI Kota
d9b467098a erlang: added more cross-language tests. better type specification. 2010-05-31 23:56:06 +09:00
UENISHI Kota
7d1e51437e erlang: added usage of cross-language test. 2010-05-31 23:13:32 +09:00
frsyuki
f5a7d444e2 Merge branch 'master' of github.com:msgpack/msgpack 2010-05-31 17:32:51 +09:00
frsyuki
a0071c2f9f add crosslang.rb 2010-05-31 17:27:51 +09:00
frsyuki
98a5e43883 add crosslang.cc 2010-05-31 17:16:40 +09:00
UENISHI Kota
f40ebe5b43 Merge branch 'master' of ssh://github.com/msgpack/msgpack 2010-05-31 00:26:49 +09:00
UENISHI Kota
d7d78d9a2b added more tests,
and OMake continuous building.
2010-05-31 00:25:53 +09:00
Hideyuki Tanaka
5a12d36a0a incr version 2010-05-30 19:45:00 +09:00
Hideyuki Tanaka
e61dc76ae1 fix peek object 2010-05-30 19:11:04 +09:00
Hideyuki Tanaka
0da22193bd fix typo 2010-05-30 17:20:49 +09:00
Hideyuki Tanaka
d43921823e fix initialize pointer 2010-05-30 17:19:43 +09:00
UENISHI Kota
6b5b76b0c9 initial import from http://bitbucket.org/kuenishi/messagepack-for-erlang 2010-05-30 15:01:10 +09:00
frsyuki
602971408b cpp: move source files into src/ directory 2010-05-30 03:02:40 +09:00
frsyuki
2f5d83f07d cpp: type::tuple& operator>>: fix conversion type 2010-05-30 01:45:07 +09:00
frsyuki
81b0c316cd java: Unpacker: rewind internal buffer on filled <= offset 2010-05-30 01:39:48 +09:00
frsyuki
6df86384ca java: update javadoc 2010-05-29 07:54:49 +09:00
frsyuki
3fbcde4bd7 ruby: don't use rb_enc_set/get on ruby 1.8 2010-05-26 18:11:09 +09:00
frsyuki
293293c23c ruby: set mp->user.source = Qnil before tempalte_execute_do on Unpacker#each 2010-05-26 18:01:27 +09:00
frsyuki
47185d757e ruby: version 0.4.0 2010-05-26 07:55:02 +09:00
frsyuki
94c3998507 ruby: update gemspec 2010-05-26 07:43:05 +09:00
frsyuki
5fa589691c ruby: use malloc/realloc for stream buffer 2010-05-26 07:01:28 +09:00
frsyuki
26bc835c7e ruby: buffer rewinding 2010-05-26 04:30:49 +09:00
frsyuki
fc7da17fa2 cpp: add sbuffer::clear() and vrefbuffer::clear() 2010-05-25 02:57:37 +09:00
frsyuki
dbebe9771b ruby: update rdoc 2010-05-25 02:55:58 +09:00
frsyuki
d0af8aa9f1 ruby: rdoc 2010-05-23 21:10:49 +09:00
Kazuki Ohta
f8173e93f5 java: version 0.3 (added CHANGES.txt and LICENSE.txt) 2010-05-23 01:48:20 +09:00
frsyuki
fa6ea6848f java: fixed problem that empty array and empty map don't check Schema 2010-05-23 01:38:01 +09:00
frsyuki
5982970e21 java: fixed problem that empty array and empty map don't check Schema 2010-05-23 01:34:45 +09:00
Kazuki Ohta
c43e5e0c95 java: added testcases for empty array and empty map 2010-05-23 01:31:15 +09:00
frsyuki
b4fc79c38e java: fixes compile error 2010-05-22 17:05:17 +09:00
frsyuki
b9cb270b8f java: add Unpacker.unpack(MessageUnpackable) and Unpacker.tryUnpackNil() 2010-05-22 03:34:43 +09:00
frsyuki
1fe35d7efe java: fix Packer.packByte 2010-05-22 03:34:17 +09:00
frsyuki
ec8c19b1f0 java: javadoc 2010-05-20 17:32:15 +09:00
frsyuki
c2525bcc05 java: add Unpacker.wrap method 2010-05-20 06:19:26 +09:00
frsyuki
985c31b378 java: add Unpacker.wrap method 2010-05-20 06:18:32 +09:00
frsyuki
135a9f5586 java: fix direct conversion API 2010-05-20 05:44:44 +09:00
frsyuki
979ff80982 java: redesign 2010-05-20 03:49:26 +09:00
frsyuki
6cde9f3a9d Merge branch 'master' of github.com:msgpack/msgpack 2010-05-19 16:31:16 +09:00
frsyuki
5cad81bf4c cpp: fix return type mismatch in zone.c 2010-05-18 14:48:36 +09:00
frsyuki
18967162cf cpp: fix return type mismatch in unpack.c 2010-05-18 14:48:23 +09:00
tokuhirom
6ea75f3a9f Perl: do not use done_testing 2010-05-17 05:52:32 +09:00
tokuhirom
f51123d009 oops 2010-05-17 05:49:39 +09:00
tokuhirom
be6376ee2d Perl: build_requires and requires are duped. 2010-05-08 12:02:31 +09:00
tokuhirom
120a85a3e5 Perl: releng for 0.12 2010-05-05 17:28:38 +09:00
tokuhirom
262fe96c29 Perl: PERL_NO_GET_CONTEXT makes horrible dTHXs. remove it. 2010-05-05 17:25:45 +09:00
tokuhirom
1864df5ed0 Perl: cleanup Makefile.PL 2010-05-05 17:25:25 +09:00
tokuhirom
09bae0a9e8 Perl: Test::Requires is not needed for this test. 2010-05-05 17:25:08 +09:00
tokuhirom
ebe41a24f1 perl: releng for data-messagepack 0.11 2010-05-05 16:59:31 +09:00
tokuhirom
f0f574a15b Perl: releng for 0.10 2010-05-05 16:55:06 +09:00
tokuhirom
9420436c09 Perl: added test case 2010-05-05 16:22:40 +09:00
tokuhirom
2b8f853b96 Perl: fixed some issues. thanks to gfx++
http://gist.github.com/387743
2010-05-05 16:17:57 +09:00
tokuhirom
2c2bf60d0c Perl: added README file. 2010-05-05 15:50:07 +09:00
Hideyuki Tanaka
62b82448d5 Merge branch 'master' of git@github.com:msgpack/msgpack 2010-05-05 04:33:11 +09:00
Hideyuki Tanaka
2f12e6c3d0 remove compiler warnings 2010-05-05 04:28:04 +09:00
Kazuki Ohta
8ce23f8e3e java: fixed pom.xml to work "mvn deploy" command 2010-05-04 18:33:29 +09:00
Hideyuki Tanaka
dbe760d6e2 make () to OBJECT instance (Nil) 2010-05-04 16:24:45 +09:00
Hideyuki Tanaka
674c26d9c7 fix feed function from Handle 2010-05-04 16:22:04 +09:00
tokuhirom
7b68b04efd Perl: change for release Data-MessagePack-0.09_01 2010-05-03 01:36:48 +09:00
tokuhirom
e0b65bf196 Merge branch 'master' of git@github.com:msgpack/msgpack 2010-05-03 01:20:00 +09:00
tokuhirom
77f5cb1f1f Perl: updated docs. 2010-05-03 01:09:21 +09:00
tokuhirom
2a222737f8 Merge branch 'master' of git@github.com:msgpack/msgpack 2010-05-03 01:04:50 +09:00
tokuhirom
77d48f9cee Perl: fixed memory leak issue 2010-05-03 00:46:15 +09:00
tokuhirom
c77eac325e Perl: added failing test case for memory leaks 2010-05-03 00:22:16 +09:00
tokuhirom
517ced2a54 Perl: added more test case for streaming unpacker 2010-05-03 00:08:02 +09:00
tokuhirom
70d2c47367 perl: added more test case for streaming deserializer. 2010-05-02 22:09:18 +09:00
frsyuki
e57084f6df cpp: update ChangeLog 2010-04-29 23:45:48 +09:00
frsyuki
8783cf8ec3 cpp: fixes unpacker::next 2010-04-29 22:32:43 +09:00
frsyuki
2af7a7c6ac Merge branch 'master' of github.com:msgpack/msgpack 2010-04-29 22:15:17 +09:00
frsyuki
91a1f8d9e1 cpp: new streaming deserialier API. 2010-04-29 22:15:03 +09:00
Kazuki Ohta
fc5e8ddca1 java: add Unpacker.feed() function for java.nio.ByteBuffer 2010-04-29 21:27:41 +09:00
frsyuki
6352472c5f python: sourceforge.jp -> sourceforge.net 2010-04-29 09:06:46 +09:00
Naoki INADA
833ee6484c Release msgpack-python 0.1.3 2010-04-29 07:52:32 +09:00
Naoki INADA
dda3d24bca Add download url. 2010-04-29 07:08:41 +09:00
Naoki INADA
f77d76a320 Add COPYING file to python package. 2010-04-29 07:01:16 +09:00
frsyuki
c51fabf6ed msgpack/pack_template.h: don't evaluate undefined macro 2010-04-29 02:39:53 +09:00
frsyuki
b10cb658ca pack_template.h: template_unsigned_long:
wrong size checking on !defined(SIZEOF_SHORT) && !defined(SHRT_MAX)"
2010-04-29 00:39:45 +09:00
frsyuki
68f60568ac cpp: build libmsgpackc.so for backward compatibility. 2010-04-26 21:52:19 +09:00
frsyuki
9fbca83ac0 cpp: add test/{zone,pack_unpack,streaming,object,convert,buffer}.cc 2010-04-25 18:08:14 +09:00
frsyuki
d19bfaa2cb cpp: fixes msgpack_vc8.vcproj 2010-04-25 09:09:06 +09:00
frsyuki
53d5ddb345 cpp: fixes operator<<(packer<Stream>&, const object&) 2010-04-25 08:26:42 +09:00
frsyuki
0a5c2e7ab9 c,cpp: MSGPACK_OBJECT_NIL = 0x00 2010-04-25 08:16:12 +09:00
frsyuki
35802ba949 cpp: msgpack_object_equal 2010-04-25 08:00:04 +09:00
frsyuki
72160aac9a cpp: combines libmsgpackc and libmsgpack into libmsgpack 2010-04-25 07:56:19 +09:00
frsyuki
9df6916029 cpp: object::object(const T& v, zone* z) 2 2010-04-25 06:39:12 +09:00
frsyuki
9bfa2354ff cpp: fixes serialization of object::type == DOUBLE 2010-04-25 02:37:04 +09:00
frsyuki
7d945d3c8e cpp: explicit object(const T& v) 2010-04-25 02:30:53 +09:00
frsyuki
05e28752f1 cpp: MSGPACK_DEFINE defines T::msgpack_object(object*, zone*) 2010-04-25 01:57:05 +09:00
frsyuki
01b6673528 cpp: bool operator==(object& x, const T& y) 2010-04-25 01:24:24 +09:00
frsyuki
4e85ebbf98 cpp: object::object(const T& v, zone* z) 2010-04-25 01:12:25 +09:00
frsyuki
120e8bffd7 cpp: object::object(const T& v) and object::operator=(const T& v) 2010-04-25 00:03:09 +09:00
frsyuki
8335823748 ruby-0.3.9 2010-04-23 20:24:36 +09:00
frsyuki
c9fcf4020f ruby: streaming deserializer test 2010-04-23 20:18:48 +09:00
frsyuki
b10a736744 ruby: fixese backward compatibility of streaming deserializer 2010-04-23 18:13:36 +09:00
frsyuki
60fbaf7612 ruby: 0.3.8 2010-04-22 14:56:25 +09:00
frsyuki
d24193630e reverts variable-length stack: avoids memory leak 2010-04-22 14:46:54 +09:00
frsyuki
354af69f62 ruby: fixes SEGV on MessagePack_Unpacker_each 2010-04-22 14:38:10 +09:00
Taro L. Saito
bccac610a4 changed the src/test folder 2010-04-20 00:05:26 +09:00
Taro L. Saito
5aa6209664 add README 2010-04-19 23:52:40 +09:00
Taro L. Saito
d693d92702 removed unnecessary settings 2010-04-19 23:34:18 +09:00
Taro L. Saito
f2622e54e3 moved src and test codes to src/{main,test}/java 2010-04-19 23:05:00 +09:00
Taro L. Saito
20fe9b6dde added pom.xml 2010-04-19 22:39:53 +09:00
Kazuki Ohta
11f7aa4212 cpp: fixed small typo in configure.in 2010-04-18 15:11:50 +09:00
Hideyuki Tanaka
f53c351fd2 haskell binding 2010-04-18 02:17:49 +09:00
Kazuki Ohta
fb96617377 java: add javadoc,javadoc-jar,pom,dist,mvn-install,mvn-deploy ANT tasks.
Now maven2 repository for msgpack is created at the following URL.
  - http://msgpack.sourceforge.net/maven2/
2010-04-18 01:18:40 +09:00
frsyuki
05b8c00ee7 cpp: fixes windows compatibility 2010-04-18 00:39:45 +09:00
frsyuki
58854fdae9 cpp: add cpp/README.md 2010-04-18 00:39:23 +09:00
frsyuki
fd31ff772f Merge branch 'master' of github.com:msgpack/msgpack 2010-04-18 00:08:17 +09:00
frsyuki
ab8e0c9e31 c,cpp: reforms source tree 2010-04-18 00:08:03 +09:00
Kazuki Ohta
abeed3be84 java: add tests for array and map 2010-04-17 23:25:42 +09:00
Kazuki Ohta
a65438c6fe java: skip building jar file for the faster testing 2010-04-17 22:53:56 +09:00
frsyuki
c3f43fb0cf template_execute: fixes embed stack 2010-04-17 22:43:11 +09:00
Kazuki Ohta
2807504a81 java: add tests for float, double, nil, boolean, string 2010-04-17 22:10:41 +09:00
Kazuki Ohta
08b716c96d java: add TestPackUnpack for int 2010-04-17 21:16:32 +09:00
Kazuki Ohta
b4b1f0a2c9 introduce JUnit framework for testing. 2010-04-17 20:17:43 +09:00
frsyuki
228f742b2f ruby: set encoding to 'ASCII-8BIT' before deserializing on ruby-1.9 2010-04-17 20:02:47 +09:00
frsyuki
a55affe4d5 ruby: add Symbol#to_msgpack 2010-04-17 16:16:56 +09:00
frsyuki
a6ec726ed7 malloc/realloc the stack when its length becomes > MSGPACK_EMBED_STACK_SIZE 2010-04-14 21:11:31 +09:00
frsyuki
87835a4e60 ruby: remove init_stack, adopt rb_gc_mark_maybe 2010-04-14 21:08:06 +09:00
Masahiro Nakagawa
1f18af4395 c: fixes comment in pack_template.h 2010-04-08 23:01:19 +09:00
frsyuki
e79747a600 cpp: msgpack/pack.hpp: fixes header 2010-04-07 20:02:00 +09:00
Masahiro Nakagawa
bd36ac2c0c cpp: fixes argument type of pack_int* methods 2010-04-07 19:54:14 +09:00
frsyuki
c6186f2c01 ruby: version 0.3.7 2010-04-06 17:59:34 +09:00
frsyuki
d639f57470 ruby: fixes Segmentation fault on MessagePack.unpack(nil) 2010-04-06 17:46:38 +09:00
Hideyuki TAKEI
99a2d28592 import MessagePack for PHP 2010-04-05 00:10:28 +09:00
frsyuki
254ee80c16 c: fixes msgpack_zbuffer_write: error checking 2010-04-04 22:11:16 +09:00
frsyuki
e43f57fe1a c: fixes msgpack_zbuffer_flush: error checking 2010-04-04 22:06:27 +09:00
Masahiro Nakagawa
f88c029a4c c: fixes msgpack_zbuffer_flush 2010-04-04 21:55:00 +09:00
frsyuki
93c3cbeaef ruby fixes gemspec: require_paths = ["lib"] 2010-04-04 21:45:56 +09:00
frsyuki
88c77b793f Merge branch 'master' of github.com:msgpack/msgpack 2010-04-04 21:40:19 +09:00
frsyuki
11286524a5 ruby: fixes 'File not found: lib' message on gem installation 2010-04-02 03:22:29 +09:00
frsyuki
7c863c341e ruby: use gem-compile gem instead of some scripts to create binary gems 2010-04-02 02:19:41 +09:00
moaikids
3416cf984e fix: org.msgpack.impl.UnpackerImpl.java CS_MAP_16 deserialize bug(line.388) 2010-04-01 23:15:36 +09:00
moaikids
1784746e7e fix: CS_MAP_16 deserialize bug(line.388) 2010-04-01 23:13:56 +09:00
Keiji Muraishi
6c6df1adaf should raise TypeError on find unsupported value 2010-03-31 17:29:07 +09:00
Keiji Muraishi
f91e1c17c0 fix typo in Makefile 2010-03-31 17:09:00 +09:00
frsyuki
58201b95f2 ruby: version 0.3.4 2010-03-31 13:46:28 +09:00
frsyuki
fcce8f6d51 ruby: use 'readpartial' instead of 'sysread' if !io.respond_to?(:sysread) 2010-03-31 12:00:26 +09:00
frsyuki
f7bdda8828 cpp: fixes pack_short(int) -> pack_short(short) 2010-03-29 21:18:01 +09:00
frsyuki
df5a60fd5b ruby: append_buffer calls "<<" method if the buffer object.class != String 2010-03-26 15:16:13 +09:00
frsyuki
5782ab7ccc c,cpp: add msgpack_zbuffer and msgpack::zbuffer 2010-03-26 14:33:49 +09:00
frsyuki
72e3f98213 cpp: alias pack(Stream* s, const T& v) -> pack(Stream& const T& v) 2010-03-26 14:30:50 +09:00
frsyuki
1b1433a664 ruby: copy the deserialized string if length <= RSTRING_EMBED_LEN_MAX 2010-03-26 14:29:49 +09:00
frsyuki
568704ed22 fixes Visual C++ compatibility 2010-03-19 13:34:53 +09:00
frsyuki
05a7e4eb64 ruby: add msgpack.mingw.{gemspec,sh} 2010-03-02 17:09:59 +09:00
frsyuki
7a0acf2838 Merge branch 'master' of frsyuki@git.sourceforge.jp:/gitroot/msgpack/msgpack 2010-03-01 18:00:16 +09:00
frsyuki
27787505e0 strict-aliasing rule 2 2010-02-27 02:37:01 +09:00
frsyuki
2c8048115d Merge branch 'master' of frsyuki@git.sourceforge.jp:/gitroot/msgpack/msgpack 2010-02-18 14:31:41 +09:00
frsyuki
7df1780853 ruby: makegem.sh 2010-02-06 21:31:16 +09:00
frsyuki
d5609f3207 ruby: makegem.sh 2010-02-06 21:28:27 +09:00
frsyuki
cd10fbc1fe removed symbolic links 2010-02-06 20:09:41 +09:00
firewood
ca0b085d15 add a blanc after Japanese comment 2010-02-05 22:50:05 +09:00
firewood
9a034234d8 add vc2005 project file. 2010-02-05 22:49:28 +09:00
firewood
66ef6c9e4c undef after including winsock2.h. 2010-02-05 22:49:00 +09:00
frsyuki
7df60b259b MSVC2005 compatibility (@hotpepsi++) 2010-02-02 10:52:42 +09:00
frsyuki
34b3bbc883 ruby: add Unpacker#each 2010-01-29 17:23:48 +09:00
Naoki INADA
e02d20dd74 replace setup by setup_dev. 2010-01-25 20:52:48 +09:00
Naoki INADA
1a11608f1f cythoning *.pyx when sdist. 2010-01-25 20:51:55 +09:00
Naoki INADA
9e2c9d7812 Tiny fix in README 2010-01-25 12:21:46 +09:00
Kazuki Ohta
404a393315 c, cpp: fix test problem
- using LDADD instead of LDFLAGS
- fix include path in test.cpp
2010-01-21 21:55:06 +09:00
frsyuki
c69092e110 configure.in: fix message 2010-01-21 17:25:32 +09:00
frsyuki
ebc0eeac79 c,cpp: 0.4.1 2010-01-20 15:17:33 +09:00
frsyuki
2b72f35c32 configure.in: show error message if __sync_* atomic operations are not supported 2010-01-20 14:49:51 +09:00
frsyuki
d8212ad620 strict-aliasing rule 2010-01-20 14:46:54 +09:00
Kazuki Ohta
1066bb38a8 add tests for multi[map, set] and tr1::unordered_[multi][map, set] 2010-01-16 02:03:11 +09:00
frsyuki
2bf3f1856f c,cpp: configure.in: version 0.4.0 2010-01-15 14:45:52 +09:00
frsyuki
f145129f6e c,cpp: optimize msgpack_vrefbuffer 2010-01-15 05:29:41 +09:00
frsyuki
8d365458d5 c,cpp: optimize msgpack_zone: variable-length array of chunk -> list of chunk 2010-01-15 05:27:44 +09:00
frsyuki
55cfbf378e cpp: add msgpack/type/tr1/unordered_{map,set}.hpp 2010-01-14 21:20:32 +09:00
frsyuki
d76093b148 import MessagePack for Java 2010-01-08 17:34:14 +09:00
tokuhirom
7873e41e00 Perl: change for release Data-MessagePack-0.09 2010-01-04 12:10:46 +09:00
tokuhirom
9817e9b18d Perl: support NVTYPE=="long double" or IVTYPE="long long" environment. 2010-01-04 11:59:52 +09:00
tokuhirom
519716bbe4 Merge branch 'master' of git://git.sourceforge.jp/gitroot/msgpack/msgpack 2010-01-04 11:23:40 +09:00
frsyuki
c2dd22ec10 c,cpp: add msgpack_vrefbuffer_migrate, msgpack::vrefbuffer::migrate 2009-12-19 22:09:29 +09:00
Naoki INADA
232aced926 Update gitignore. 2009-12-17 18:03:33 +09:00
Naoki INADA
63b9a876b0 Fix tests. 2009-12-17 17:58:41 +09:00
inada-n
5cf85a82d3 Add .gitignore for Python. 2009-12-17 15:20:20 +09:00
inada-n
b9f78821d4 Make tuple default. 2009-12-17 15:19:18 +09:00
Naoki INADA
f4c5b15cc6 Add use_tuple option that returns tuple for array object to Unpacker. 2009-12-17 11:13:47 +09:00
Naoki INADA
4d33bd456c Update new headers. 2009-12-17 10:43:22 +09:00
Naoki INADA
3a5f7f53ff Start 0.2.0 2009-12-17 10:43:01 +09:00
inada-n
1ed4236bcf Make new Python release. 2009-12-16 22:18:17 +09:00
inada-n
5ff2c6be74 Fix bug come from previous commit 2009-12-16 22:14:13 +09:00
inada-n
dd18402737 Fix stream unpacker broken. 2009-12-16 22:05:31 +09:00
frsyuki
686e8ca0f0 c,cpp: fix unpacker 2009-12-16 04:08:36 +09:00
frsyuki
5aa47d6677 cpp: zone::push_finalizer supports std::auto_ptr<T> 2009-12-16 03:52:14 +09:00
frsyuki
0d44348c7d ruby: version 0.3.2 2009-12-11 04:13:24 +09:00
frsyuki
35929b46ae add msgpack/sysdep.h 2009-12-10 07:22:39 +09:00
frsyuki
ba3ba0367c msgpack template: macros for compilers that doesn't not support Case Ranges 2009-12-10 06:40:29 +09:00
frsyuki
7ce866ad7c msgpack template: architecture specific endian conversion 2009-12-10 06:19:53 +09:00
frsyuki
0ae1965f6b ruby: fixes MessagePack_Unpacker_mark marks uninitialized map_key 2009-12-10 04:32:33 +09:00
frsyuki
eb9e892491 import MessagePack for Java implementation plan 3 2009-11-26 11:22:08 +09:00
frsyuki
e39e1d4f60 import MessagePack for Java implementation plan 2 2009-11-12 01:10:36 +09:00
Naoki INADA
93a95725fc Fix Makefile 2009-11-05 14:26:12 +09:00
Naoki INADA
4758d9f04b Fix to use MANIEFST.in. 2009-11-05 14:24:47 +09:00
frsyuki
d39c016e1d java: fix streaming de/serializer 2009-10-25 02:41:55 +09:00
frsyuki
5393a0df16 import MessagePack for Java implementation plan 1 2009-10-25 01:27:09 +09:00
Tokuhiro Matsuno
68176e10f5 added some pattern to MANIFEST.SKIP 2009-10-22 14:34:53 +09:00
Tokuhiro Matsuno
c6a2569af8 - generate README automatically
- added LICENSE term
2009-10-22 14:32:39 +09:00
frsyuki
3424dc916c cpp: add missing type::tuple::tuple(object o) 2009-10-09 17:49:30 +09:00
frsyuki
c8ad32a39e cpp: preprocess.sh: more verbose 2009-10-05 23:31:08 +09:00
Kazuki Ohta
d0b76814b0 cpp: add tests for stream unpacker api 2009-09-12 03:12:53 +09:00
frsyuki
bf3cb63d46 cpp: version 0.3.8 2009-09-10 13:53:12 +09:00
frsyuki
8da7b692f6 cpp: define, type::tuple: GENERATION_LIMIT = 31 2009-09-10 13:50:19 +09:00
Kazuki Ohta
320c79db49 c++: add vrefbuffer test 2009-09-04 16:20:29 +09:00
frsyuki
ebf64d9892 cpp: test.cpp: fixes EXPECT_EQ rule 2009-08-26 12:28:08 +09:00
frsyuki
c12d5b8461 c: test.cpp: add msgpack_sbuffer_destroy and msgpack_zone_destroy 2009-08-26 12:27:28 +09:00
Kazuki Ohta
7186edc45e C: more strict tests for float, double
C++: more strict tests for float, double & enum, union member
2009-08-26 11:52:12 +09:00
Kazuki Ohta
c94772104d C: add test for map
C++: add tests for primitive types, stl types, user-defined type
2009-08-26 11:28:54 +09:00
Kazuki Ohta
9374571056 C: add more tests (float, double, nil, true, false, array, raw) 2009-08-26 09:24:07 +09:00
Kazuki Ohta
c232e91f83 c: fix bugs in c/test.cpp and add more tests 2009-08-25 19:26:54 +09:00
Kazuki Ohta
5b8777026a c: add sometests for serialization 2009-08-25 19:04:21 +09:00
Kazuki Ohta
51e435d46c fix build 2009-08-25 18:40:06 +09:00
frsyuki
d3f9ab7dec add c/test.cpp cpp/test.cpp 2009-08-25 18:35:26 +09:00
frsyuki
1ba330c473 fix cpp/preprocess.sh 2009-08-25 18:25:58 +09:00
frsyuki
dba7f480ed cpp: add missing preprocess.sh file 2009-08-19 17:50:15 +09:00
frsyuki
3a39accb0b cpp: preprocess eruby templates on ./bootstrap; released package doesn't require erb 2009-08-19 17:47:22 +09:00
frsyuki
387eca6fbf cpp-0.3.7 2009-08-19 17:36:05 +09:00
frsyuki
b2381d0513 cpp: fix overflow check for minimum number of signed integer type 2009-08-19 15:10:10 +09:00
frsyuki
92952f6566 c++: fix object >> std::string 2009-08-10 22:16:44 +09:00
frsyuki
a62a5d6c69 c++: fix type.hpp 2009-08-10 18:33:35 +09:00
frsyuki
0627324da6 c++: rebuild type/*.hpp 2009-08-10 18:26:01 +09:00
frsyuki
394331cd4e c++: add std::pair and std::set serializer 2009-08-10 17:34:21 +09:00
frsyuki
0491768fb2 c++: fix Makefile.am 2009-08-10 15:58:43 +09:00
frsyuki
a5705183d6 0.3.5 2009-08-07 13:32:32 +09:00
frsyuki
95a6316cc7 cpp: fix msgpack::type::make_define() 2009-08-07 13:32:07 +09:00
frsyuki
be32e3b1fb cpp: add missing msgpack::type::make_tuple() 2009-08-07 13:31:42 +09:00
frsyuki
b4cb5e23c0 fix Makefile.am 2009-08-07 11:28:23 +09:00
frsyuki
1375732c80 add 2009-08-07 11:15:33 +09:00
frsyuki
7fbe845434 cpp: msgpack::define is obsolete 2009-08-06 13:59:48 +09:00
frsyuki
3afa9f265e cpp: add msgpack::type::define 2009-08-06 13:51:49 +09:00
frsyuki
ec8932d6a1 fix missing tuple<>::value_type 2009-08-06 13:28:41 +09:00
frsyuki
f7a9805f7b operator>> (object, std::vector<T>): return reference; don't copy 2009-08-06 13:26:34 +09:00
frsyuki
aaef612a05 Makefile.am: don't package perl and ruby files 2009-08-06 13:20:43 +09:00
Tokuhiro Matsuno
da9b75f553 Checking in changes prior to tagging of version 0.08. Changelog diff is:
diff --git a/perl/Changes b/perl/Changes
index 4e7f1d7..c6e370c 100644
--- a/perl/Changes
+++ b/perl/Changes
@@ -1,3 +1,7 @@
+0.08
+
+    - fixed PVNV issue...
+
 0.07

     - do not use switch (SvTYPE(val)).
2009-07-30 16:52:13 +09:00
Tokuhiro Matsuno
d3906bd1ab Perl: use M::I::XSUtil 2009-07-30 16:38:03 +09:00
Tokuhiro Matsuno
4db90d23ac - fixed SVt_PVNV issue. 2009-07-30 16:22:00 +09:00
Tokuhiro Matsuno
bb455c1f71 perl: display module version 2009-07-30 13:29:24 +09:00
Tokuhiro Matsuno
3275eee281 Perl: display original data 2009-07-30 13:24:38 +09:00
Tokuhiro Matsuno
0fe79a7752 Perl: added benchmark script for memroy-usage 2009-07-30 13:19:49 +09:00
Tokuhiro Matsuno
794adf9469 Checking in changes prior to tagging of version 0.07. Changelog diff is:
diff --git a/perl/Changes b/perl/Changes
index 1a51ddf..4e7f1d7 100644
--- a/perl/Changes
+++ b/perl/Changes
@@ -1,3 +1,7 @@
+0.07
+
+    - do not use switch (SvTYPE(val)).
+
 0.06

     - use SvNOK.
2009-07-22 16:42:12 +09:00
Tokuhiro Matsuno
718227bc2c Perl: do not use switch (SvTYPE) 2009-07-22 16:40:15 +09:00
Tokuhiro Matsuno
390c5ad8a0 added test case. 2009-07-22 13:41:31 +09:00
Tokuhiro Matsuno
2da4b17d0b Merge branch 'master' of tokuhirom@git.sourceforge.jp:/gitroot/msgpack/msgpack 2009-07-22 13:28:27 +09:00
inada-n
d19c488929 version: python-0.1.1 2009-07-13 15:52:25 +09:00
inada-n
0db5e0439d Fix: Unpacker.unpack() may raise StopIteration before unpacking large object when deserializing from file. 2009-07-13 15:49:38 +09:00
inada-n
6083bad5ff Fix wrong MANIFEST. 2009-07-13 14:46:53 +09:00
inada-n
63a507a123 merge python binding from bzr. 2009-07-13 14:40:02 +09:00
Naoki INADA
294e3fe7ab Add setup script for distribution. 2009-07-13 14:27:57 +09:00
Naoki INADA
e5c49dae13 Release 0.1.0 2009-07-12 20:02:21 +09:00
Naoki INADA
900785e1aa Clean up 2009-07-12 09:29:11 +09:00
Naoki INADA
979efbb950 Support MinGW. 2009-07-09 13:41:04 +09:00
Tokuhiro Matsuno
7da1a9b3cf Checking in changes prior to tagging of version 0.06. Changelog diff is:
diff --git a/perl/Changes b/perl/Changes
index 15603ea..1a51ddf 100644
--- a/perl/Changes
+++ b/perl/Changes
@@ -1,3 +1,7 @@
+0.06
+
+    - use SvNOK.
+
 0.05

     - change type detection for old perl
2009-07-03 18:19:29 +09:00
Tokuhiro Matsuno
661f273481 Perl: use SvNOK. 2009-07-03 18:18:40 +09:00
Tokuhiro Matsuno
cb5c878b77 Checking in changes prior to tagging of version 0.05. Changelog diff is:
diff --git a/perl/Changes b/perl/Changes
index 33fb36c..15603ea 100644
--- a/perl/Changes
+++ b/perl/Changes
@@ -1,3 +1,7 @@
+0.05
+
+    - change type detection for old perl
+
 0.04

     - check SvROK first(reported by yappo++)
2009-07-03 18:15:45 +09:00
Tokuhiro Matsuno
34ed3bc9e3 Perl: check IV by SvIOK 2009-07-03 18:09:38 +09:00
Tokuhiro Matsuno
ad7cf12128 perl: added test case for "the flag is working?" 2009-07-03 17:27:44 +09:00
Tokuhiro Matsuno
6fb6283463 Checking in changes prior to tagging of version 0.04. Changelog diff is:
diff --git a/perl/Changes b/perl/Changes
index 0c170a3..33fb36c 100644
--- a/perl/Changes
+++ b/perl/Changes
@@ -1,3 +1,11 @@
+0.04
+
+    - check SvROK first(reported by yappo++)
+    - PreferInteger: faster string to integer conversion; support negative value
+      (frsyuki++)
+    - make PreferInteger variable magical and remove get_sv from _msgpack_pack_sv
+      (frsyuki++)
+
 0.03

     - performance tuning for too long string
2009-07-03 15:23:50 +09:00
Tokuhiro Matsuno
b45dc8db61 check SvROK first 2009-07-03 15:14:31 +09:00
Tokuhiro Matsuno
3397d261d8 Merge branch 'master' of tokuhirom@git.sourceforge.jp:/gitroot/msgpack/msgpack
Conflicts:
	perl/lib/Data/MessagePack.pm
2009-07-03 11:39:34 +09:00
frsyuki
eaa8be8ddd perl: PreferInteger: faster string to integer conversion; support negative value 2009-07-03 02:08:22 +09:00
frsyuki
0f9dcb8610 perl: make PreferInteger variable magical and remove get_sv from _msgpack_pack_sv 2009-07-03 01:49:37 +09:00
Tokuhiro Matsuno
3446c475d7 Checking in changes prior to tagging of version 0.03. Changelog diff is:
diff --git a/perl/Changes b/perl/Changes
index fb31a69..0c170a3 100644
--- a/perl/Changes
+++ b/perl/Changes
@@ -1,3 +1,8 @@
+0.03
+
+    - performance tuning for too long string
+    - fixed memory leaks in stream unpacker
+
 0.02

     - added $Data::MessagePack::PreferInteger
2009-07-02 17:43:58 +09:00
Tokuhiro Matsuno
ffef0a0b6f oops. fixed memory leaks in stream unpacker. 2009-07-02 17:42:28 +09:00
Tokuhiro Matsuno
580fbe77e9 do not check the string longer than 10. 2009-07-02 16:40:41 +09:00
Tokuhiro Matsuno
e92e99c4d1 Perl: I don't need CCFLAGS 2009-07-02 14:43:22 +09:00
Tokuhiro Matsuno
c3f793aa09 Checking in changes prior to tagging of version 0.02. Changelog diff is:
diff --git a/perl/Changes b/perl/Changes
index 18041d4..fb31a69 100644
--- a/perl/Changes
+++ b/perl/Changes
@@ -1,3 +1,8 @@
+0.02
+
+    - added $Data::MessagePack::PreferInteger
+      (requested by yappo++)
+
 0.01

     - initial release to CPAN
2009-07-02 14:37:54 +09:00
Tokuhiro Matsuno
3d9908c8e5 Merge branch 'master' of git://git.sourceforge.jp/gitroot/msgpack/msgpack
Conflicts:
	perl/pack.c
2009-07-02 14:31:52 +09:00
Tokuhiro Matsuno
7b198d5966 s/Preferred/Prefer/g suggested by kazuho++ 2009-07-02 14:29:49 +09:00
Tokuhiro Matsuno
601209c83c support $Data::MessagePack::PreferredInteger for Data::Model 2009-07-02 14:25:48 +09:00
Naoki INADA
78db826a75 Fix memory leak. Remove stream packing feature. Add errorcheck in packing. 2009-07-01 20:55:24 +09:00
Tokuhiro Matsuno
c2a63b2c54 Checking in changes prior to tagging of version 0.01. Changelog diff is: 2009-07-01 18:40:14 +09:00
Tokuhiro Matsuno
7c27624161 added .shipit file 2009-07-01 18:34:27 +09:00
Tokuhiro Matsuno
d86b90e663 added Changes file 2009-07-01 18:34:11 +09:00
Tokuhiro Matsuno
d72bef9f9a added MANIFEST.SKIP files 2009-07-01 18:33:56 +09:00
Tokuhiro Matsuno
37972dfe3e copy files into this dir. 2009-07-01 18:20:14 +09:00
Tokuhiro Matsuno
c6496ddf13 added .gitignore file 2009-07-01 18:08:39 +09:00
Tokuhiro Matsuno
a95e8c790c this module requires perl 5.8 2009-07-01 17:45:18 +09:00
Naoki INADA
03942a1b90 Major speedup on packing. 2009-07-01 00:57:46 +09:00
Naoki INADA
d4317fdc85 Some optimization on packing. 2009-06-30 23:03:33 +09:00
Naoki INADA
b5010c71a9 Fix tests. 2009-06-29 11:21:28 +09:00
Naoki INADA
9015bd4ecf Fix error on packing unsigned long long. 2009-06-29 10:09:04 +09:00
Naoki INADA
fe2421275d Add some test cases. 2009-06-29 09:31:43 +09:00
Naoki INADA
257270c1eb Refactor packing code. 2009-06-29 08:23:49 +09:00
Naoki INADA
0b33a634a6 Update test_format. 2009-06-29 08:23:27 +09:00
Naoki INADA
3e396ef146 Don't use C++. 2009-06-28 21:24:16 +09:00
Naoki INADA
1b07b61c04 Ues more suitable type when packing. 2009-06-28 21:24:02 +09:00
Naoki INADA
fa2efcdb5b Rename test files. 2009-06-27 12:04:11 +09:00
Naoki INADA
a345131aaa Add: README 2009-06-27 12:03:00 +09:00
Naoki INADA
ffc16736ba merge to git master 2009-06-27 10:35:07 +09:00
Naoki INADA
3c3df3133c Implement streaming deserializer. 2009-06-26 14:10:20 +09:00
Naoki INADA
16a208243b merge 2009-06-26 14:09:15 +09:00
frsyuki
dd407410d2 version 0.3.3 2009-06-24 16:01:13 +09:00
frsyuki
8f52ed26c7 version 0.3.3 2009-06-24 16:01:13 +09:00
Naoki INADA
479263989b Stop unnecessary caching. 2009-06-24 14:58:02 +09:00
Tokuhiro Matsuno
87e1adcb40 works correctly under Perl5.8.x. Perl5.8.x makes "a" as PVIV in {"a", 0}. 2009-06-24 14:46:28 +09:00
Tokuhiro Matsuno
8e166de1d1 works correctly under Perl5.8.x. Perl5.8.x makes "a" as PVIV in {"a", 0}. 2009-06-24 14:46:28 +09:00
Tokuhiro Matsuno
3aef3edbad works correctly under Perl5.8.x.
Perl5.8.x makes "a" as PVIV in {"a", 0}.
2009-06-24 14:36:37 +09:00
Tokuhiro Matsuno
b2fdaac99e update ppport.h 2009-06-24 14:11:06 +09:00
Tokuhiro Matsuno
9a342ab7f8 update ppport.h 2009-06-24 14:11:06 +09:00
frsyuki
8596d36d02 perl package 2009-06-24 13:53:12 +09:00
Naoki INADA
423e5132a1 merge 2009-06-24 08:49:48 +09:00
Naoki INADA
1581acfd14 Make setup.py executable. 2009-06-24 14:33:36 +09:00
Naoki INADA
5d4189306a Check return value of c-api. 2009-06-24 04:25:05 +09:00
Naoki INADA
f61b282886 Reduce memory footprint. 2009-06-24 01:54:47 +09:00
Naoki INADA
3fd28d0792 Remove duplicated values. 2009-06-24 01:38:48 +09:00
Naoki INADA
dd53b141ef Remove unneccessary value. 2009-06-24 01:13:39 +09:00
Naoki INADA
99d0a41ec6 Fix setup script bug. 2009-06-24 01:13:22 +09:00
Naoki INADA
b8e5b918a3 Update manifest. 2009-06-22 22:50:05 +09:00
Naoki INADA
71af62c1df merge to master. 2009-06-22 20:08:17 +09:00
Naoki INADA
7d5f04917e Update manifest. 2009-06-22 19:55:46 +09:00
Naoki INADA
46d7c65621 Fix compile error. 2009-06-22 19:49:02 +09:00
Naoki INADA
87f5df1503 Use std::stack. 2009-06-22 15:59:02 +09:00
Naoki INADA
9a77ab57f6 merge document fix. 2009-06-22 14:55:46 +09:00
Naoki INADA
20a7ff0be8 Make msgpack package instead of module. and using Cython in setup script. 2009-06-22 14:38:36 +09:00
Naoki INADA
075081a521 Fix manifest. 2009-06-22 14:28:04 +09:00
Naoki INADA
f4387e9746 merge changing include path 2009-06-22 13:26:41 +09:00
Naoki INADA
0d14239c21 Optimize to parsing data that has a number of same short raw field. 2009-06-22 09:51:24 +09:00
Naoki INADA
2475187c7d Fix refcount leak and optimize list initialization. 2009-06-17 13:45:08 +09:00
Naoki INADA
4d6e9ffaa2 Fix can't pack float values. 2009-06-16 01:58:07 +09:00
Naoki INADA
6184e17a42 Increase stack size. 2009-06-16 01:56:04 +09:00
Naoki INADA
e814986b4e Fix document miss. 2009-06-10 13:33:42 +09:00
Naoki INADA
3a9f74e79c Make msgpack package instead of module. 2009-06-10 10:58:09 +09:00
Naoki INADA
a1fb1507d4 Refactor include path. 2009-06-10 10:45:07 +09:00
Naoki INADA
85ca594118 free buffer when packer deleted. 2009-06-09 13:12:29 +09:00
Naoki INADA
9c9393bff9 Fix setup script doesn't work. 2009-06-08 13:21:38 +09:00
Naoki INADA
560bd901f8 Fix double INCREF-ing when unpacking. 2009-06-08 12:46:02 +09:00
Naoki INADA
114ef92d42 Merge branch 'master' of git://git.sourceforge.jp/gitroot/msgpack/msgpack 2009-06-08 04:43:25 +09:00
Naoki INADA
1840ef70ae merge to trunk 2009-06-08 04:38:20 +09:00
Naoki INADA
935db853f0 add test. 2009-06-08 04:33:58 +09:00
Naoki INADA
17d2ca2d63 Fix unpacking True, False and True. 2009-06-08 04:33:47 +09:00
Naoki INADA
c930f5367b add cythoned source and setup script. 2009-06-08 01:43:50 +09:00
Naoki INADA
d8a3bc920c refactoring 2009-06-08 01:30:43 +09:00
Naoki INADA
711e4817a5 support packing long and tuple. add missing files. 2009-06-08 00:23:38 +09:00
frsyuki
7cd359c1fd add msgpack_vrefbuffer, msgpack::vrefbuffer 2009-06-07 14:59:50 +09:00
frsyuki
2598d98922 Merge branch 'master' of frsyuki@git.sourceforge.jp:/gitroot/msgpack/msgpack 2009-06-07 13:33:22 +09:00
frsyuki
8617213149 cpp: fix map<K, V> converter 2009-06-03 22:01:27 +09:00
Naoki INADA
3628ea22d4 add pyx 2009-05-22 14:31:20 +09:00
frsyuki
6a0729ea91 cpp: const 2009-05-13 17:53:27 +09:00
Tokuhiro Matsuno
b0062a7f6f perl: oops. this doens't needed. 2009-04-15 23:14:56 +09:00
Tokuhiro Matsuno
b140b27b9a perl: added argument check 2009-04-15 23:11:26 +09:00
Tokuhiro Matsuno
e0bd2a2911 perl: added benchmark script for deserialization 2009-04-15 23:06:47 +09:00
Tokuhiro Matsuno
ea41db4cc7 perl: renamed benchmark script 2009-04-15 23:02:27 +09:00
Tokuhiro Matsuno
5a201be844 perl: use more efficent strategy for memory allocation.this code taken from JSON::XS. thanks to mlehmann++ 2009-04-15 22:43:59 +09:00
Tokuhiro Matsuno
28e113fd00 oops. remove debugging code. 2009-04-15 22:43:16 +09:00
Tokuhiro Matsuno
5710b87b06 perl: enhancement portability 2009-04-15 13:09:05 +09:00
Tokuhiro Matsuno
8c62d93bca added perl support 2009-04-15 12:55:41 +09:00
frsyuki
b8cc8b72bd version 0.3.1 2009-03-04 01:54:07 +09:00
frsyuki
cc7379d532 more test caces 2009-03-04 01:36:56 +09:00
frsyuki
163fc6f589 fix serialization bug on BigEndian environment 3 2009-03-04 01:15:22 +09:00
frsyuki
c7f193e441 fix serialization bug on BigEndian environment 2009-03-04 01:04:43 +09:00
frsyuki
09978e500a update ruby/msgpack.gemspec 2009-03-01 18:32:50 +09:00
frsyuki
2fad10ca3f zone::base 2009-03-01 16:40:02 +09:00
frsyuki
e707b7a600 zone::push_finalizer reverts memory allocation on exception 2009-03-01 15:49:24 +09:00
frsyuki
e7403013e5 msgpack_zone: sizeof(int) bytes alignment 2009-03-01 14:59:13 +09:00
frsyuki
c3f9696268 fix packaging problem 2009-03-01 13:46:20 +09:00
frsyuki
cb24a0c24f fix msgpack_unpacker_expand_buffer 2009-03-01 03:39:34 +09:00
frsyuki
0efb8160b9 msgpack_zone_clear, msgpack::zone::clear 2009-03-01 02:55:45 +09:00
frsyuki
bf13ba72b5 fix unpacker 2009-03-01 02:27:04 +09:00
frsyuki
6fc38d1669 msgpack::pack is not obsolete 2009-03-01 01:31:12 +09:00
frsyuki
879c70f93a fix msgpack_sbuffer_release 2009-03-01 01:13:31 +09:00
frsyuki
6fda01111e msgpack::sbuffer::data() const 2009-03-01 01:06:16 +09:00
frsyuki
4f4fa39cd5 c: msgpack_sbuffer; cpp: msgpack::sbuffer 2009-03-01 00:59:15 +09:00
frsyuki (none)
c60b6be548 add NOTICE file 2009-02-26 18:37:13 +09:00
frsyuki (none)
9b4b49a6a8 example: limit message size 2009-02-26 01:33:34 +09:00
frsyuki (none)
c0baf9b873 add msgpack_unpacker_message_size 2009-02-26 01:27:00 +09:00
frsyuki (none)
65ef9cab66 remove msgpack_unpacker_buffered_size, add msgpack_unpacker_parsed_size 2009-02-26 01:15:14 +09:00
frsyuki (none)
6ffee9e54a c: msgpack_unpacker_buffered_size; c++: unpacker::buffered_size 2009-02-25 23:31:53 +09:00
frsyuki (none)
43360e3786 fix msgpack::unpack_return 2009-02-25 18:55:56 +09:00
frsyuki (none)
4d708aa4da c: msgpack_pack_object 2009-02-24 16:37:47 +09:00
frsyuki (none)
5d51129e65 add example/simple.c 2009-02-24 16:37:01 +09:00
frsyuki (none)
a0b82e39e1 AC_CONFIG_AUX_DIR(ac) 2009-02-22 15:47:06 +09:00
frsyuki (none)
9642368835 type conversion operator msgpack_object <-> msgpack::object 2009-02-22 15:36:02 +09:00
frsyuki (none)
cbf7afc1cc c and c++: rewritten and integrated 2009-02-22 15:14:21 +09:00
254 changed files with 23156 additions and 9544 deletions

View File

@@ -1,48 +0,0 @@
if ENABLE_CXX
export ERB
SUBDIRS = c cpp
else
SUBDIRS = c
endif
nobase_include_HEADERS = \
msgpack/pack_define.h \
msgpack/pack_template.h \
msgpack/unpack_define.h \
msgpack/unpack_template.h
EXTRA_DIST = \
ruby/bench.rb \
ruby/extconf.rb \
ruby/gem/README \
ruby/gem/Rakefile \
ruby/gem/test/test_helper.rb \
ruby/gengem.sh \
ruby/msgpack.gemspec \
ruby/pack.c \
ruby/pack.h \
ruby/rbinit.c \
ruby/test_case.rb \
ruby/test_format.rb \
ruby/test_pack.rb \
ruby/unpack.c \
ruby/unpack.h \
perl/Makefile.PL \
perl/MessagePack.c \
perl/benchmark/deserialize.pl \
perl/benchmark/serialize.pl \
perl/lib/Data/MessagePack.pm \
perl/lib/Data/MessagePack \
perl/lib/Data/MessagePack/Unpacker.pod \
perl/pack.c \
perl/ppport.h \
perl/t/00_compile.t \
perl/t/01_pack.t \
perl/t/02_unpack.t \
perl/t/03_stream_unpack.t \
perl/t/04_invert.t \
perl/t/Util.pm \
perl/t/data.pl \
perl/unpack.c \
perl/xt/99_pod.t

72
README
View File

@@ -1,72 +0,0 @@
MessagePack
-----------
Binary-based efficient data interchange format.
*Requirements
MessagePack is only tested on Linux and Mac OS X, but it may run on other
UNIX-like platforms.
Following programs are required to build:
- gcc >= 4.1 with C++ support
- ruby >= 1.8 (ruby is used as a preprocessor)
*Installation
Simply run ./configure && make && make install to install C and C++ binding.
$ ./configure
$ make
$ sudo make install
To install Ruby binding, run ./gengem.sh script on ruby/ directory and install
generated gem package.
$ cd ruby
$ ./gengem.sh
$ gem install gem/pkg/msgpack-*.gem
*Usage
C++:
include msgpack.hpp header and link libmsgpack library.
see example/simple.cc for example.
g++ simple.cc -lmsgpack
g++ stream.cc -lmsgpack -lpthread
C:
include msgpack.h header and link libmsgpackc library.
see example/simple.c for example.
gcc simple.c -lmsgpackc
Ruby:
require msgpack library.
see example/simple.rb for example.
ruby -rubygems simple.rb
API Document is available at http://msgpack.sourceforge.jp/.
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.

37
README.md Normal file
View File

@@ -0,0 +1,37 @@
MessagePack
===========
Extremely efficient object serialization library. It's like JSON, but very fast and small.
## What's 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.
Typical small integer (like flags or error code) is saved only in 1 byte, and typical short string only needs 1 byte except the length of the string itself. \[1,2,3\] (3 elements array) is serialized in 4 bytes using MessagePack as follows:
require 'msgpack'
msg = [1,2,3].to_msgpack #=> "\x93\x01\x02\x03"
MessagePack.unpack(msg) #=> [1,2,3]
## Performance
![Serialization + Deserialization Speed Test](http://msgpack.sourceforge.net/index/speedtest.png)
In this test, it measured the elapsed time of serializing and deserializing 200,000 target objects. The target object consists of the three integers and 512 bytes string.
The source code of this test is available from [frsyuki' serializer-speed-test repository.](http://github.com/frsyuki/serializer-speed-test)
## Getting Started
Usage and other documents about implementations in each language are found at [the web site.](http://msgpack.sourceforge.net/)
## Learn More
- [Project Web Site](http://msgpack.sourceforge.net/)
- [MessagePack format specification](http://msgpack.sourceforge.net/spec)
- [Repository at github](http://github.com/msgpack/msgpack)
- [Wiki](http://msgpack.sourceforge.net/start)
- [MessagePack-RPC](http://github.com/msgpack/msgpack-rpc)

View File

@@ -1,20 +0,0 @@
lib_LTLIBRARIES = libmsgpackc.la
libmsgpackc_la_SOURCES = \
unpack.c \
object.c \
vrefbuffer.c \
zone.c
nobase_include_HEADERS = \
msgpack.h \
msgpack/sbuffer.h \
msgpack/vrefbuffer.h \
msgpack/pack.h \
msgpack/unpack.h \
msgpack/object.h \
msgpack/zone.h
# -version-info CURRENT:REVISION:AGE
libmsgpackc_la_LDFLAGS = -version-info 1:0:0

323
c/bench.c
View File

@@ -1,323 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <msgpack/pack.h>
#include <msgpack/unpack.h>
#include <yajl/yajl_parse.h>
#include <yajl/yajl_gen.h>
static struct timeval g_timer;
void reset_timer()
{
gettimeofday(&g_timer, NULL);
}
void show_timer(size_t bufsz)
{
struct timeval endtime;
gettimeofday(&endtime, NULL);
double sec = (endtime.tv_sec - g_timer.tv_sec)
+ (double)(endtime.tv_usec - g_timer.tv_usec) / 1000 / 1000;
printf("%f sec\n", sec);
printf("%f MB\n", ((double)bufsz)/1024/1024);
printf("%f Mbps\n", ((double)bufsz)*8/sec/1000/1000);
}
static int reformat_null(void * ctx) { return 1; }
static int reformat_boolean(void * ctx, int boolean) { return 1; }
static int reformat_number(void * ctx, const char * s, unsigned int l) { return 1; }
static int reformat_string(void * ctx, const unsigned char * stringVal, unsigned int stringLen) { return 1; }
static int reformat_map_key(void * ctx, const unsigned char * stringVal, unsigned int stringLen) { return 1; }
static int reformat_start_map(void * ctx) { return 1; }
static int reformat_end_map(void * ctx) { return 1; }
static int reformat_start_array(void * ctx) { return 1; }
static int reformat_end_array(void * ctx) { return 1; }
static void* unpack_uint8(void* data, uint8_t d) { return NULL; }
static void* unpack_uint16(void* data, uint16_t d) { return NULL; }
static void* unpack_uint32(void* data, uint32_t d) { return NULL; }
static void* unpack_uint64(void* data, uint64_t d) { return NULL; }
static void* unpack_int8(void* data, int8_t d) { return NULL; }
static void* unpack_int16(void* data, int16_t d) { return NULL; }
static void* unpack_int32(void* data, int32_t d) { return NULL; }
static void* unpack_int64(void* data, int64_t d) { return NULL; }
static void* unpack_float(void* data, float d) { return NULL; }
static void* unpack_double(void* data, double d) { return NULL; }
static void* unpack_nil(void* data) { return NULL; }
static void* unpack_true(void* data) { return NULL; }
static void* unpack_false(void* data) { return NULL; }
static void* unpack_array(void* data, unsigned int n) { return NULL; }
static void unpack_array_item(void* data, void* c, void* o) { }
static void* unpack_map(void* data, unsigned int n) { return NULL; }
static void unpack_map_item(void* data, void* c, void* k, void* v) { }
static void* unpack_raw(void* data, const char* b, const char* p, unsigned int l) { /*printf("unpack raw %p %lu\n",p,l);*/ return NULL; }
typedef struct {
size_t allocated;
size_t length;
char* buffer;
} pack_buffer;
static const size_t PACK_INITIAL_BUFFER_SIZE = 32*1024;
static void pack_buffer_init(pack_buffer* data)
{
data->buffer = malloc(PACK_INITIAL_BUFFER_SIZE);
data->length = 0;
data->allocated = PACK_INITIAL_BUFFER_SIZE;
}
static void pack_buffer_reset(pack_buffer* data)
{
data->buffer = realloc(data->buffer, PACK_INITIAL_BUFFER_SIZE);
data->allocated = PACK_INITIAL_BUFFER_SIZE;
data->length = 0;
}
static void pack_buffer_free(pack_buffer* data)
{
free(data->buffer);
}
static void pack_append_buffer(void* user, const char* b, unsigned int l)
{
pack_buffer* data = (pack_buffer*)user;
if(data->allocated - data->length < l) {
data->buffer = realloc(data->buffer, data->allocated*2);
data->allocated *= 2;
}
memcpy(data->buffer + data->length, b, l);
data->length += l;
}
static const unsigned int TASK_INT_NUM = 1<<24;
static const unsigned int TASK_STR_LEN = 1<<15;
//static const unsigned int TASK_INT_NUM = 1<<20;
//static const unsigned int TASK_STR_LEN = 1<<12;
static const char* TASK_STR_PTR;
void bench_json(void)
{
puts("== JSON ==");
yajl_gen_config gcfg = {0, NULL};
yajl_gen g = yajl_gen_alloc(&gcfg);
yajl_parser_config hcfg = { 0, 0 };
yajl_callbacks callbacks = {
reformat_null,
reformat_boolean,
NULL,
NULL,
reformat_number,
reformat_string,
reformat_start_map,
reformat_map_key,
reformat_end_map,
reformat_start_array,
reformat_end_array
};
yajl_handle h = yajl_alloc(&callbacks, &hcfg, NULL);
const unsigned char * buf;
unsigned int len;
puts("generate integer");
reset_timer();
{
unsigned int i;
yajl_gen_array_open(g);
for(i=0; i < TASK_INT_NUM; ++i) {
yajl_gen_integer(g, i);
}
yajl_gen_array_close(g);
}
show_timer(len);
yajl_gen_get_buf(g, &buf, &len);
puts("----");
puts("parse integer");
reset_timer();
{
yajl_status stat = yajl_parse(h, buf, len);
if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) {
unsigned char * str = yajl_get_error(h, 1, buf, len);
fprintf(stderr, (const char *) str);
}
}
show_timer(len);
//yajl_gen_clear(g);
yajl_gen_free(g);
g = yajl_gen_alloc(&gcfg);
yajl_free(h);
h = yajl_alloc(&callbacks, &hcfg, NULL);
puts("----");
puts("generate string");
reset_timer();
{
unsigned int i;
yajl_gen_array_open(g);
for(i=0; i < TASK_STR_LEN; ++i) {
yajl_gen_string(g, (const unsigned char*)TASK_STR_PTR, i);
}
yajl_gen_array_close(g);
}
show_timer(len);
yajl_gen_get_buf(g, &buf, &len);
puts("----");
puts("parse string");
reset_timer();
{
yajl_status stat = yajl_parse(h, buf, len);
if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) {
unsigned char * str = yajl_get_error(h, 1, buf, len);
fprintf(stderr, (const char *) str);
}
}
show_timer(len);
yajl_gen_free(g);
yajl_free(h);
}
void bench_msgpack(void)
{
puts("== MessagePack ==");
pack_buffer mpkbuf;
pack_buffer_init(&mpkbuf);
msgpack_pack_t* mpk = msgpack_pack_new(
&mpkbuf, pack_append_buffer);
msgpack_unpack_callback cb = {
unpack_uint8,
unpack_uint16,
unpack_uint32,
unpack_uint64,
unpack_int8,
unpack_int16,
unpack_int32,
unpack_int64,
unpack_float,
unpack_double,
unpack_nil,
unpack_true,
unpack_false,
unpack_array,
unpack_array_item,
unpack_map,
unpack_map_item,
unpack_raw,
};
msgpack_unpack_t* mupk = msgpack_unpack_new(NULL, &cb);
size_t len;
const char* buf;
puts("pack integer");
reset_timer();
{
unsigned int i;
msgpack_pack_array(mpk, TASK_INT_NUM);
for(i=0; i < TASK_INT_NUM; ++i) {
msgpack_pack_unsigned_int(mpk, i);
}
}
show_timer(mpkbuf.length);
len = mpkbuf.length;
buf = mpkbuf.buffer;
puts("----");
puts("unpack integer");
reset_timer();
{
size_t off = 0;
int ret = msgpack_unpack_execute(mupk, buf, len, &off);
if(ret < 0) {
fprintf(stderr, "Parse error.\n");
} else if(ret == 0) {
fprintf(stderr, "Not finished.\n");
}
}
show_timer(mpkbuf.length);
pack_buffer_reset(&mpkbuf);
msgpack_unpack_reset(mupk);
puts("----");
puts("pack string");
reset_timer();
{
unsigned int i;
msgpack_pack_array(mpk, TASK_STR_LEN);
for(i=0; i < TASK_STR_LEN; ++i) {
msgpack_pack_raw(mpk, i);
msgpack_pack_raw_body(mpk, TASK_STR_PTR, i);
}
}
show_timer(mpkbuf.length);
len = mpkbuf.length;
buf = mpkbuf.buffer;
puts("----");
puts("unpack string");
reset_timer();
{
size_t off = 0;
int ret = msgpack_unpack_execute(mupk, buf, len, &off);
if(ret < 0) {
fprintf(stderr, "Parse error.\n");
} else if(ret == 0) {
fprintf(stderr, "Not finished.\n");
}
}
show_timer(mpkbuf.length);
msgpack_unpack_free(mupk);
msgpack_pack_free(mpk);
pack_buffer_free(&mpkbuf);
}
int main(int argc, char* argv[])
{
char* str = malloc(TASK_STR_LEN);
memset(str, 'a', TASK_STR_LEN);
TASK_STR_PTR = str;
bench_msgpack();
bench_json();
return 0;
}

View File

@@ -1,9 +0,0 @@
CFLAGS += -Wall -g -I. -I.. -O4
LDFLAGS += -lyajl
all: bench
bench: bench.o pack.o unpack.o pack.h unpack.h
$(CC) bench.o pack.o unpack.o $(CFLAGS) $(LDFLAGS) -o $@

View File

@@ -1 +0,0 @@
.

View File

@@ -1,125 +0,0 @@
/*
* MessagePack for C unpacking routine
*
* 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_unpacker_H__
#define msgpack_unpacker_H__
#include "msgpack/zone.h"
#include "msgpack/object.h"
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct msgpack_unpacker {
char* buffer;
size_t used;
size_t free;
size_t off;
size_t parsed;
msgpack_zone* z;
size_t initial_buffer_size;
void* ctx;
} msgpack_unpacker;
bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size);
void msgpack_unpacker_destroy(msgpack_unpacker* mpac);
msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size);
void msgpack_unpacker_free(msgpack_unpacker* mpac);
static inline bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size);
static inline char* msgpack_unpacker_buffer(msgpack_unpacker* mpac);
static inline size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac);
static inline void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size);
int msgpack_unpacker_execute(msgpack_unpacker* mpac);
msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac);
msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac);
void msgpack_unpacker_reset_zone(msgpack_unpacker* mpac);
void msgpack_unpacker_reset(msgpack_unpacker* mpac);
static inline size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac);
typedef enum {
MSGPACK_UNPACK_SUCCESS = 2,
MSGPACK_UNPACK_EXTRA_BYTES = 1,
MSGPACK_UNPACK_CONTINUE = 0,
MSGPACK_UNPACK_PARSE_ERROR = -1,
} msgpack_unpack_return;
msgpack_unpack_return
msgpack_unpack(const char* data, size_t len, size_t* off,
msgpack_zone* z, msgpack_object* result);
static inline size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac);
bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac);
bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size);
bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size)
{
if(mpac->free >= size) { return true; }
return msgpack_unpacker_expand_buffer(mpac, size);
}
char* msgpack_unpacker_buffer(msgpack_unpacker* mpac)
{
return mpac->buffer + mpac->used;
}
size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac)
{
return mpac->free;
}
void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size)
{
mpac->used += size;
mpac->free -= size;
}
size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac)
{
return mpac->parsed - mpac->off + mpac->used;
}
size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac)
{
return mpac->parsed;
}
#ifdef __cplusplus
}
#endif
#endif /* msgpack/unpack.h */

View File

@@ -1,135 +0,0 @@
/*
* MessagePack for C zero-copy buffer implementation
*
* 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.
*/
#include "msgpack/vrefbuffer.h"
#include <stdlib.h>
#include <string.h>
bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
size_t ref_size, size_t chunk_size)
{
if(chunk_size < sizeof(msgpack_vrefbuffer_chunk)+72) {
chunk_size = 72;
} else {
chunk_size -= sizeof(msgpack_vrefbuffer_chunk);
}
vbuf->chunk_size = chunk_size;
vbuf->ref_size = ref_size;
// glibcは72バイト以下のmallocが高速
size_t nfirst = (sizeof(struct iovec) < 72/2) ?
72 / sizeof(struct iovec) : 8;
struct iovec* array = (struct iovec*)malloc(
sizeof(struct iovec) * nfirst);
if(array == NULL) {
return false;
}
vbuf->tail = array;
vbuf->end = array + nfirst;
vbuf->array = array;
vbuf->chunk = (msgpack_vrefbuffer_chunk*)malloc(
chunk_size + sizeof(msgpack_vrefbuffer_chunk));
if(vbuf->chunk == NULL) {
free(array);
return false;
}
vbuf->chunk->next = NULL;
vbuf->chunk->free = chunk_size;
return true;
}
void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf)
{
msgpack_vrefbuffer_chunk* c = vbuf->chunk;
while(true) {
msgpack_vrefbuffer_chunk* n = c->next;
free(c);
if(n) {
c = n;
} else {
break;
}
}
free(vbuf->array);
}
int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
const char* buf, unsigned int len)
{
if(vbuf->tail == vbuf->end) {
const size_t nused = vbuf->end - vbuf->array;
const size_t nnext = nused * 2;
struct iovec* nvec = (struct iovec*)realloc(
vbuf->array, sizeof(struct iovec)*nnext);
if(nvec == NULL) {
return -1;
}
vbuf->array = nvec;
vbuf->end = nvec + nnext;
vbuf->tail = nvec + nused;
}
vbuf->tail->iov_base = (char*)buf;
vbuf->tail->iov_len = len;
++vbuf->tail;
return 0;
}
int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
const char* buf, unsigned int len)
{
msgpack_vrefbuffer_chunk* chunk = vbuf->chunk;
size_t cur_size = vbuf->chunk_size;
if(chunk->free < len) {
cur_size = (cur_size > len) ? cur_size : len;
chunk = (msgpack_vrefbuffer_chunk*)malloc(
cur_size + sizeof(msgpack_vrefbuffer_chunk));
if(chunk == NULL) {
return -1;
}
chunk->free = cur_size;
chunk->next = vbuf->chunk;
vbuf->chunk = chunk;
}
char* m = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk)
+ (cur_size - chunk->free);
memcpy(m, buf, len);
chunk->free -= len;
if(vbuf->tail != vbuf->array && m ==
(const char*)((vbuf->tail-1)->iov_base) + (vbuf->tail-1)->iov_len) {
(vbuf->tail-1)->iov_len += len;
return 0;
} else {
return msgpack_vrefbuffer_append_ref(vbuf, m, len);
}
}

View File

@@ -1,44 +0,0 @@
AC_INIT(msgpack/unpack_template.h)
AC_CONFIG_AUX_DIR(ac)
AM_INIT_AUTOMAKE(msgpack, 0.3.2)
AC_CONFIG_HEADER(config.h)
AC_SUBST(CFLAGS)
if test "" = "$CFLAGS"; then
CFLAGS="-g -O4"
fi
AC_PROG_CC
CFLAGS="-O4 -Wall $CFLAGS -I.."
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_SUBST(CXXFLAGS)
if test "" = "$CXXFLAGS"; then
CXXFLAGS="-g -O4"
fi
AC_CHECK_PROG(ERB, erb, erb)
if test "x$ERB" = x; then
AC_MSG_ERROR([cannot find erb. Ruby is needed to build.])
fi
fi
# FIXME
AC_PROG_CXX
CXXFLAGS="-O4 -Wall $CXXFLAGS -I.. -I../c"
AM_CONDITIONAL(ENABLE_CXX, test "$enable_cxx" != "no")
AC_PROG_LIBTOOL
AC_OUTPUT([Makefile c/Makefile cpp/Makefile])

View File

@@ -1,4 +1,4 @@
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.

25
cpp/ChangeLog Normal file
View File

@@ -0,0 +1,25 @@
2010-07-14 version 0.5.2:
* type::raw::str(), operator==, operator!=, operator< and operator> are now const
* generates version.h using AC_OUTPUT macro in ./configure
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.
* New safe streaming deserializer API.
* Add object::object(const T&) and object::operator=(const T&)
* Add operator==(object, const T&)
* MSGPACK_DEFINE macro defines msgpack_object(object* obj, zone* z)
* C++ programs doesn't need to link "msgpackc" library.

1552
cpp/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,47 +1,18 @@
lib_LTLIBRARIES = libmsgpack.la
SUBDIRS = src test
libmsgpack_la_SOURCES = \
object.cpp
nobase_include_HEADERS = \
msgpack.hpp \
msgpack/sbuffer.hpp \
msgpack/vrefbuffer.hpp \
msgpack/pack.hpp \
msgpack/unpack.hpp \
msgpack/object.hpp \
msgpack/zone.hpp \
msgpack/type.hpp \
msgpack/type/array.hpp \
msgpack/type/boolean.hpp \
msgpack/type/float.hpp \
msgpack/type/integer.hpp \
msgpack/type/map.hpp \
msgpack/type/nil.hpp \
msgpack/type/raw.hpp \
msgpack/type/tuple.hpp
# FIXME
object.lo: msgpack/type/tuple.hpp msgpack/zone.hpp
msgpack/type/tuple.hpp: msgpack/type/tuple.hpp.erb
$(ERB) $< > $@.tmp
mv $@.tmp $@
msgpack/zone.hpp: msgpack/zone.hpp.erb
$(ERB) $< > $@.tmp
mv $@.tmp $@
MOSTLYCLEANFILES = \
msgpack/type/tuple.hpp \
msgpack/zone.hpp
DOC_FILES = \
README.md \
LICENSE \
NOTICE \
msgpack_vc8.vcproj \
msgpack_vc8.sln \
msgpack_vc8.postbuild.bat
EXTRA_DIST = \
msgpack/type/tuple.hpp.erb \
msgpack/zone.hpp.erb
$(DOC_FILES)
libmsgpack_la_LIBADD = -L../c -lmsgpackc
# -version-info CURRENT:REVISION:AGE
libmsgpack_la_LDFLAGS = -version-info 1:0:0
doxygen:
./preprocess clean
cd src && $(MAKE) doxygen
./preprocess

View File

78
cpp/README.md Normal file
View File

@@ -0,0 +1,78 @@
MessagePack for C/C++
=====================
Binary-based efficient object serialization library.
## Installation
Download latest package from [releases of MessagePack](http://sourceforge.net/projects/msgpack/files/) and extract it.
On UNIX-like platform, run ./configure && make && sudo make install:
$ ./configure
$ make
$ sudo make install
On Windows, open msgpack_vc8.vcproj file and build it using batch build. DLLs are built on lib folder, and the headers are built on include folder.
To use the library in your program, include msgpack.hpp header and link msgpack and msgpackc library.
## Example
#include <msgpack.hpp>
#include <vector>
int main(void) {
// This is target object.
std::vector<std::string> target;
target.push_back("Hello,");
target.push_back("World!");
// Serialize it.
msgpack::sbuffer buffer; // simple buffer
msgpack::pack(&buffer, target);
// Deserialize the serialized data.
msgpack::zone mempool; // this manages the life of deserialized object
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(buffer.data, buffer.size, NULL, &mempool, &obj);
if(ret != msgapck::UNPACK_SUCCESS) {
// error check
exit(1);
}
// Print the deserialized object to stdout.
std::cout << obj << std::endl; // ["Hello," "World!"]
// Convert the deserialized object to staticaly typed object.
std::vector<std::string> result;
obj.convert(&result);
// If the type is mismatched, it throws msgpack::type_error.
obj.as<int>(); // type is mismatched, msgpack::type_error is thrown
}
API document and other example codes are available at the [wiki.](http://msgpack.sourceforge.net/start)
## License
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.
See also NOTICE file.

View File

@@ -1,188 +0,0 @@
#include <msgpack/unpack.hpp>
#include <msgpack/pack.hpp>
#include <string.h>
#include <sys/time.h>
#include <iostream>
#include <stdexcept>
#include <string>
static const unsigned int TASK_INT_NUM = 1<<24;
static const unsigned int TASK_STR_LEN = 1<<15;
//static const unsigned int TASK_INT_NUM = 1<<22;
//static const unsigned int TASK_STR_LEN = 1<<13;
static const char* TASK_STR_PTR;
class simple_timer {
public:
void reset() { gettimeofday(&m_timeval, NULL); }
void show_stat(size_t bufsz)
{
struct timeval endtime;
gettimeofday(&endtime, NULL);
double sec = (endtime.tv_sec - m_timeval.tv_sec)
+ (double)(endtime.tv_usec - m_timeval.tv_usec) / 1000 / 1000;
std::cout << sec << " sec" << std::endl;
std::cout << (double(bufsz)/1024/1024) << " MB" << std::endl;
std::cout << (bufsz/sec/1000/1000*8) << " Mbps" << std::endl;
}
private:
timeval m_timeval;
};
class simple_buffer {
public:
static const size_t DEFAULT_INITIAL_SIZE = 32*1024;//512*1024*1024*2;
simple_buffer(size_t initial_size = DEFAULT_INITIAL_SIZE) :
m_storage((char*)malloc(initial_size)),
m_allocated(initial_size),
m_used(0)
{
if(!m_storage) { throw std::bad_alloc(); }
}
~simple_buffer()
{
free(m_storage);
}
public:
inline void write(const char* buf, size_t len)
{
if(m_allocated - m_used < len) {
expand_buffer(len);
}
memcpy(m_storage + m_used, buf, len);
m_used += len;
}
void clear()
{
m_used = 0;
}
private:
void expand_buffer(size_t req)
{
size_t nsize = m_allocated * 2;
size_t at_least = m_used + req;
while(nsize < at_least) { nsize *= 2; }
char* tmp = (char*)realloc(m_storage, nsize);
if(!tmp) { throw std::bad_alloc(); }
m_storage = tmp;
m_allocated = nsize;
}
public:
size_t size() const { return m_used; }
const char* data() const { return m_storage; }
private:
char* m_storage;
size_t m_allocated;
size_t m_used;
};
void bench_msgpack_int()
{
simple_buffer buf;
simple_timer timer;
std::cout << "----" << std::endl;
std::cout << "pack integer" << std::endl;
timer.reset();
{
msgpack::packer<simple_buffer> pk(buf);
pk.pack_array(TASK_INT_NUM);
for(unsigned int i=0; i < TASK_INT_NUM; ++i) {
pk.pack_unsigned_int(i);
}
}
timer.show_stat(buf.size());
std::cout << "----" << std::endl;
std::cout << "unpack integer" << std::endl;
msgpack::zone z;
msgpack::object obj;
timer.reset();
{
obj = msgpack::unpack(buf.data(), buf.size(), z);
}
timer.show_stat(buf.size());
/*
std::cout << "----" << std::endl;
std::cout << "dynamic pack integer" << std::endl;
buf.clear();
timer.reset();
msgpack::pack(buf, obj);
timer.show_stat(buf.size());
*/
}
void bench_msgpack_str()
{
simple_buffer buf;
simple_timer timer;
std::cout << "----" << std::endl;
std::cout << "pack string" << std::endl;
timer.reset();
{
msgpack::packer<simple_buffer> pk(buf);
pk.pack_array(TASK_STR_LEN);
for(unsigned int i=0; i < TASK_STR_LEN; ++i) {
pk.pack_raw(i);
pk.pack_raw_body(TASK_STR_PTR, i);
}
}
timer.show_stat(buf.size());
std::cout << "----" << std::endl;
std::cout << "unpack string" << std::endl;
msgpack::zone z;
msgpack::object obj;
timer.reset();
{
obj = msgpack::unpack(buf.data(), buf.size(), z);
}
timer.show_stat(buf.size());
/*
std::cout << "----" << std::endl;
std::cout << "dynamic pack string" << std::endl;
buf.clear();
timer.reset();
msgpack::pack(buf, obj);
timer.show_stat(buf.size());
*/
}
int main(void)
{
char* str = (char*)malloc(TASK_STR_LEN);
memset(str, 'a', TASK_STR_LEN);
TASK_STR_PTR = str;
bench_msgpack_int();
bench_msgpack_str();
return 0;
}

View File

@@ -1,9 +0,0 @@
CXXFLAGS += -Wall -g -I. -I.. -O4
LDFLAGS +=
all: bench
bench: bench.o unpack.o zone.o object.o pack.hpp unpack.hpp zone.hpp object.hpp
$(CXX) bench.o unpack.o zone.o object.o $(CXXFLAGS) $(LDFLAGS) -o $@

View File

@@ -31,11 +31,17 @@ if test x"$1" = x"--help"; then
fi
#if [ -z "$NO_NEST" ];then
# cd c && ./bootstrap $@; cd ..
# cd cpp && ./bootstrap $@; cd ..
#fi
mkdir -p ac
test -f AUTHORS || touch AUTHORS
test -f COPYING || touch COPYING
test -f ChangeLog || touch ChangeLog
test -f NEWS || touch NEWS
test -f README || cp -f README.md README
if ! ./preprocess; then
exit 1
fi
ACLOCAL="aclocal"

75
cpp/configure.in Normal file
View File

@@ -0,0 +1,75 @@
AC_INIT(src/object.cpp)
AC_CONFIG_AUX_DIR(ac)
AM_INIT_AUTOMAKE(msgpack, 0.5.2)
AC_CONFIG_HEADER(config.h)
AC_SUBST(CFLAGS)
CFLAGS="-O4 -Wall $CFLAGS"
AC_SUBST(CXXFLAGS)
CXXFLAGS="-O4 -Wall $CXXFLAGS"
AC_PROG_CC
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
AC_MSG_CHECKING([if debug option is enabled])
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--disable-debug],
[disable assert macros and omit -g option]) )
AC_MSG_RESULT([$enable_debug])
if test "$enable_debug" != "no"; then
CXXFLAGS="$CXXFLAGS -g"
CFLAGS="$CFLAGS -g"
else
CXXFLAGS="$CXXFLAGS -DNDEBUG"
CFLAGS="$CFLAGS -DNDEBUG"
fi
AC_CACHE_CHECK([for __sync_* atomic operations], msgpack_cv_atomic_ops, [
AC_TRY_LINK([
int atomic_sub(int i) { return __sync_sub_and_fetch(&i, 1); }
int atomic_add(int i) { return __sync_add_and_fetch(&i, 1); }
], [], msgpack_cv_atomic_ops="yes")
])
if test "$msgpack_cv_atomic_ops" != "yes"; then
AC_MSG_ERROR([__sync_* atomic operations are not supported.
Note that gcc < 4.1 is not supported.
If you are using gcc >= 4.1 and the default target CPU architecture is "i386", try to
add CFLAGS="--march=i686" and CXXFLAGS="-march=i686" options to ./configure as follows:
$ ./configure CFLAGS="-march=i686" CXXFLAGS="-march=i686"
])
fi
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

@@ -1 +0,0 @@
.

View File

@@ -0,0 +1,44 @@
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 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\

20
cpp/msgpack_vc8.sln Normal file
View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MessagePack", "msgpack_vc8.vcproj", "{122A2EA4-B283-4241-9655-786DE78283B2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|Win32.ActiveCfg = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|Win32.Build.0 = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|Win32.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

299
cpp/msgpack_vc8.vcproj Normal file
View File

@@ -0,0 +1,299 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="MessagePack"
ProjectGUID="{122A2EA4-B283-4241-9655-786DE78283B2}"
RootNamespace="MessagePack"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
Description="Gathering header files"
CommandLine="msgpack_vc8.postbuild.bat"
Outputs="include"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="."
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="1"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="lib\msgpackd.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
Description="Gathering header files"
CommandLine="msgpack_vc8.postbuild.bat"
Outputs="include"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="."
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="lib\msgpack.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\src\objectc.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\unpack.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\version.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\vrefbuffer.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\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>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\src\msgpack\pack_define.h"
>
</File>
<File
RelativePath=".\src\msgpack\pack_template.h"
>
</File>
<File
RelativePath=".\src\msgpack\sysdep.h"
>
</File>
<File
RelativePath=".\src\msgpack\unpack_define.h"
>
</File>
<File
RelativePath=".\src\msgpack\unpack_template.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

31
cpp/preprocess Executable file
View File

@@ -0,0 +1,31 @@
#!/bin/sh
preprocess() {
ruby -r erb -e 'puts ERB.new(ARGF.read).result' $1.erb > $1.tmp
if [ "$?" != 0 ]; then
echo ""
echo "** preprocess failed **"
echo ""
exit 1
else
mv $1.tmp $1
fi
}
if [ "$1" == "clean" ];then
rm -f src/msgpack/type/tuple.hpp
rm -f src/msgpack/type/define.hpp
rm -f src/msgpack/zone.hpp
else
preprocess src/msgpack/type/tuple.hpp
preprocess src/msgpack/type/define.hpp
preprocess src/msgpack/zone.hpp
fi
cp -f ../msgpack/sysdep.h src/msgpack/
cp -f ../msgpack/pack_define.h src/msgpack/
cp -f ../msgpack/pack_template.h src/msgpack/
cp -f ../msgpack/unpack_define.h src/msgpack/
cp -f ../msgpack/unpack_template.h src/msgpack/
cp -f ../test/cases.mpac test/
cp -f ../test/cases_compact.mpac test/

100
cpp/src/Makefile.am Normal file
View File

@@ -0,0 +1,100 @@
lib_LTLIBRARIES = libmsgpack.la
libmsgpack_la_SOURCES = \
unpack.c \
objectc.c \
version.c \
vrefbuffer.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
# backward compatibility
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
nobase_include_HEADERS = \
msgpack/pack_define.h \
msgpack/pack_template.h \
msgpack/unpack_define.h \
msgpack/unpack_template.h \
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
if ENABLE_CXX
nobase_include_HEADERS += \
msgpack.hpp \
msgpack/sbuffer.hpp \
msgpack/vrefbuffer.hpp \
msgpack/zbuffer.hpp \
msgpack/pack.hpp \
msgpack/unpack.hpp \
msgpack/object.hpp \
msgpack/zone.hpp \
msgpack/type.hpp \
msgpack/type/bool.hpp \
msgpack/type/float.hpp \
msgpack/type/int.hpp \
msgpack/type/list.hpp \
msgpack/type/deque.hpp \
msgpack/type/map.hpp \
msgpack/type/nil.hpp \
msgpack/type/pair.hpp \
msgpack/type/raw.hpp \
msgpack/type/set.hpp \
msgpack/type/string.hpp \
msgpack/type/vector.hpp \
msgpack/type/tuple.hpp \
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
doxygen_c:
cat ../Doxyfile > Doxyfile_c
echo "FILE_PATTERNS = *.h" >> Doxyfile_c
echo "OUTPUT_DIRECTORY = doc_c" >> Doxyfile_c
echo "PROJECT_NAME = \"MessagePack for C\"" >> Doxyfile_c
doxygen Doxyfile_c
doxygen_cpp:
cat ../Doxyfile > Doxyfile_cpp
echo "FILE_PATTERNS = *.hpp" >> Doxyfile_cpp
echo "OUTPUT_DIRECTORY = doc_cpp" >> Doxyfile_cpp
echo "PROJECT_NAME = \"MessagePack for C++\"" >> Doxyfile_cpp
doxygen Doxyfile_cpp
doxygen: doxygen_c doxygen_cpp

View File

@@ -15,9 +15,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @defgroup msgpack MessagePack C
* @{
* @}
*/
#include "msgpack/object.h"
#include "msgpack/zone.h"
#include "msgpack/pack.h"
#include "msgpack/unpack.h"
#include "msgpack/sbuffer.h"
#include "msgpack/vrefbuffer.h"
#include "msgpack/version.h"

View File

@@ -19,9 +19,6 @@
#define MSGPACK_OBJECT_H__
#include "msgpack/zone.h"
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#ifdef __cplusplus
@@ -29,15 +26,21 @@ extern "C" {
#endif
/**
* @defgroup msgpack_object Dynamically typed object
* @ingroup msgpack
* @{
*/
typedef enum {
MSGPACK_OBJECT_NIL = 0x01,
MSGPACK_OBJECT_BOOLEAN = 0x02,
MSGPACK_OBJECT_POSITIVE_INTEGER = 0x03,
MSGPACK_OBJECT_NEGATIVE_INTEGER = 0x04,
MSGPACK_OBJECT_DOUBLE = 0x05,
MSGPACK_OBJECT_RAW = 0x06,
MSGPACK_OBJECT_ARRAY = 0x07,
MSGPACK_OBJECT_MAP = 0x08,
MSGPACK_OBJECT_NIL = 0x00,
MSGPACK_OBJECT_BOOLEAN = 0x01,
MSGPACK_OBJECT_POSITIVE_INTEGER = 0x02,
MSGPACK_OBJECT_NEGATIVE_INTEGER = 0x03,
MSGPACK_OBJECT_DOUBLE = 0x04,
MSGPACK_OBJECT_RAW = 0x05,
MSGPACK_OBJECT_ARRAY = 0x06,
MSGPACK_OBJECT_MAP = 0x07,
} msgpack_object_type;
@@ -82,6 +85,10 @@ typedef struct msgpack_object_kv {
void msgpack_object_print(FILE* out, msgpack_object o);
bool msgpack_object_equal(const msgpack_object x, const msgpack_object y);
/** @} */
#ifdef __cplusplus
}

View File

@@ -20,7 +20,7 @@
#include "msgpack/object.h"
#include "msgpack/pack.hpp"
#include <stdint.h>
#include "msgpack/zone.hpp"
#include <string.h>
#include <stdexcept>
#include <typeinfo>
@@ -35,14 +35,14 @@ class type_error : public std::bad_cast { };
namespace type {
enum object_type {
NIL = 0x01,
BOOLEAN = 0x02,
POSITIVE_INTEGER = 0x03,
NEGATIVE_INTEGER = 0x04,
DOUBLE = 0x05,
RAW = 0x06,
ARRAY = 0x07,
MAP = 0x08,
NIL = MSGPACK_OBJECT_NIL,
BOOLEAN = MSGPACK_OBJECT_BOOLEAN,
POSITIVE_INTEGER = MSGPACK_OBJECT_POSITIVE_INTEGER,
NEGATIVE_INTEGER = MSGPACK_OBJECT_NEGATIVE_INTEGER,
DOUBLE = MSGPACK_OBJECT_DOUBLE,
RAW = MSGPACK_OBJECT_RAW,
ARRAY = MSGPACK_OBJECT_ARRAY,
MAP = MSGPACK_OBJECT_MAP,
};
}
@@ -89,8 +89,21 @@ struct object {
void convert(T* v) const;
object();
object(msgpack_object obj);
operator msgpack_object();
object(msgpack_object o);
template <typename T>
explicit object(const T& v);
template <typename T>
object(const T& v, zone* z);
template <typename T>
object& operator=(const T& v);
operator msgpack_object() const;
struct with_zone;
private:
struct implicit_type;
@@ -104,18 +117,44 @@ struct object_kv {
object val;
};
struct object::with_zone : object {
with_zone(msgpack::zone* zone) : zone(zone) { }
msgpack::zone* zone;
private:
with_zone();
};
bool operator==(const object x, const object y);
bool operator!=(const object x, const object y);
template <typename T>
bool operator==(const object x, const T& y);
template <typename T>
bool operator==(const T& y, const object x);
template <typename T>
bool operator!=(const object x, const T& y);
template <typename T>
bool operator!=(const T& y, const object x);
std::ostream& operator<< (std::ostream& s, const object o);
// serialize operator
template <typename Stream, typename T>
packer<Stream>& operator<< (packer<Stream>& o, const T& v);
// convert operator
template <typename T>
T& operator>> (object o, T& v);
// deconvert operator
template <typename T>
void operator<< (object::with_zone& o, const T& v);
struct object::implicit_type {
implicit_type(object o) : obj(o) { }
@@ -129,6 +168,7 @@ private:
};
// obsolete
template <typename Type>
class define : public Type {
public:
@@ -179,26 +219,40 @@ inline packer<Stream>& operator<< (packer<Stream>& o, const T& v)
return o;
}
template <typename T>
void operator<< (object::with_zone& o, const T& v)
{
v.msgpack_object(static_cast<object*>(&o), o.zone);
}
inline bool operator==(const object x, const object y)
{
return msgpack_object_equal(x, y);
}
template <typename T>
inline bool operator==(const object x, const T& y)
try {
return x == object(y);
} catch (msgpack::type_error&) {
return false;
}
inline bool operator!=(const object x, const object y)
{ return !(x == y); }
template <typename T>
inline bool operator==(const T& y, const object x)
{ return x == y; }
inline object::object() { }
template <typename T>
inline bool operator!=(const object x, const T& y)
{ return !(x == y); }
inline object::object(msgpack_object obj)
{
// FIXME beter way?
::memcpy(this, &obj, sizeof(obj));
}
inline object::operator msgpack_object()
{
// FIXME beter way?
msgpack_object obj;
::memcpy(&obj, this, sizeof(obj));
return obj;
}
template <typename T>
inline bool operator!=(const T& y, const object x)
{ return x != y; }
inline object::implicit_type object::convert() const
@@ -221,6 +275,55 @@ inline T object::as() const
}
inline object::object()
{
type = type::NIL;
}
template <typename T>
inline object::object(const T& v)
{
*this << v;
}
template <typename T>
inline object& object::operator=(const T& v)
{
*this = object(v);
return *this;
}
template <typename T>
object::object(const T& v, zone* z)
{
with_zone oz(z);
oz << v;
type = oz.type;
via = oz.via;
}
inline object::object(msgpack_object o)
{
// FIXME beter way?
::memcpy(this, &o, sizeof(o));
}
inline void operator<< (object& o, msgpack_object v)
{
// FIXME beter way?
::memcpy(&o, &v, sizeof(v));
}
inline object::operator msgpack_object() const
{
// FIXME beter way?
msgpack_object obj;
::memcpy(&obj, this, sizeof(obj));
return obj;
}
// obsolete
template <typename T>
inline void convert(T& v, object o)
@@ -260,35 +363,15 @@ packer<Stream>& operator<< (packer<Stream>& o, const object& v)
return o;
case type::POSITIVE_INTEGER:
if(v.via.u64 <= (uint64_t)std::numeric_limits<uint16_t>::max()) {
if(v.via.u64 <= (uint16_t)std::numeric_limits<uint8_t>::max()) {
o.pack_uint8(v.via.u64);
} else {
o.pack_uint16(v.via.u64);
}
} else {
if(v.via.u64 <= (uint64_t)std::numeric_limits<uint32_t>::max()) {
o.pack_uint32(v.via.u64);
} else {
o.pack_uint64(v.via.u64);
}
}
o.pack_uint64(v.via.u64);
return o;
case type::NEGATIVE_INTEGER:
if(v.via.i64 >= (int64_t)std::numeric_limits<int16_t>::min()) {
if(v.via.i64 >= (int64_t)std::numeric_limits<int8_t>::min()) {
o.pack_int8(v.via.i64);
} else {
o.pack_int16(v.via.i64);
}
} else {
if(v.via.i64 >= (int64_t)std::numeric_limits<int32_t>::min()) {
o.pack_int64(v.via.i64);
} else {
o.pack_int64(v.via.i64);
}
}
o.pack_int64(v.via.i64);
return o;
case type::DOUBLE:
o.pack_double(v.via.dec);
return o;
case type::RAW:

View File

@@ -18,17 +18,28 @@
#ifndef MSGPACK_PACK_H__
#define MSGPACK_PACK_H__
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include "msgpack/pack_define.h"
#include "msgpack/object.h"
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_buffer Buffers
* @ingroup msgpack
* @{
* @}
*/
/**
* @defgroup msgpack_pack Serializer
* @ingroup msgpack
* @{
*/
typedef int (*msgpack_packer_write)(void* data, const char* buf, unsigned int len);
typedef struct msgpack_packer {
@@ -76,6 +87,8 @@ static int msgpack_pack_raw_body(msgpack_packer* pk, const void* b, size_t l);
int msgpack_pack_object(msgpack_packer* pk, msgpack_object d);
/** @} */
#define msgpack_pack_inline_func(name) \
inline int msgpack_pack ## name

View File

@@ -1,7 +1,7 @@
//
// MessagePack for C++ serializing 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.
@@ -18,10 +18,9 @@
#ifndef MSGPACK_PACK_HPP__
#define MSGPACK_PACK_HPP__
#include <arpa/inet.h> // __BYTE_ORDER
#include "msgpack/pack_define.h"
#include <stdexcept>
#include <limits.h>
#include "msgpack/pack_define.h"
namespace msgpack {
@@ -29,6 +28,7 @@ namespace msgpack {
template <typename Stream>
class packer {
public:
packer(Stream* s);
packer(Stream& s);
~packer();
@@ -40,12 +40,12 @@ public:
packer<Stream>& pack_uint16(uint16_t d);
packer<Stream>& pack_uint32(uint32_t d);
packer<Stream>& pack_uint64(uint64_t d);
packer<Stream>& pack_int8(uint8_t d);
packer<Stream>& pack_int16(uint16_t d);
packer<Stream>& pack_int32(uint32_t d);
packer<Stream>& pack_int64(uint64_t d);
packer<Stream>& pack_int8(int8_t d);
packer<Stream>& pack_int16(int16_t d);
packer<Stream>& pack_int32(int32_t d);
packer<Stream>& pack_int64(int64_t d);
packer<Stream>& pack_short(int d);
packer<Stream>& pack_short(short d);
packer<Stream>& pack_int(int d);
packer<Stream>& pack_long(long d);
packer<Stream>& pack_long_long(long long d);
@@ -112,6 +112,12 @@ private:
};
template <typename Stream, typename T>
inline void pack(Stream* s, const T& v)
{
packer<Stream>(s).pack(v);
}
template <typename Stream, typename T>
inline void pack(Stream& s, const T& v)
{
@@ -134,6 +140,9 @@ inline void pack(Stream& s, const T& v)
#include "msgpack/pack_template.h"
template <typename Stream>
packer<Stream>::packer(Stream* s) : m_stream(*s) { }
template <typename Stream>
packer<Stream>::packer(Stream& s) : m_stream(s) { }
@@ -157,24 +166,24 @@ inline packer<Stream>& packer<Stream>::pack_uint64(uint64_t d)
{ _pack_uint64(m_stream, d); return *this; }
template <typename Stream>
inline packer<Stream>& packer<Stream>::pack_int8(uint8_t d)
inline packer<Stream>& packer<Stream>::pack_int8(int8_t d)
{ _pack_int8(m_stream, d); return *this; }
template <typename Stream>
inline packer<Stream>& packer<Stream>::pack_int16(uint16_t d)
inline packer<Stream>& packer<Stream>::pack_int16(int16_t d)
{ _pack_int16(m_stream, d); return *this; }
template <typename Stream>
inline packer<Stream>& packer<Stream>::pack_int32(uint32_t d)
inline packer<Stream>& packer<Stream>::pack_int32(int32_t d)
{ _pack_int32(m_stream, d); return *this; }
template <typename Stream>
inline packer<Stream>& packer<Stream>::pack_int64(uint64_t d)
inline packer<Stream>& packer<Stream>::pack_int64(int64_t d)
{ _pack_int64(m_stream, d); return *this;}
template <typename Stream>
inline packer<Stream>& packer<Stream>::pack_short(int d)
inline packer<Stream>& packer<Stream>::pack_short(short d)
{ _pack_short(m_stream, d); return *this; }
template <typename Stream>

View File

@@ -21,14 +21,17 @@
#include <stdlib.h>
#include <string.h>
#ifndef MSGPACK_SBUFFER_INIT_SIZE
#define MSGPACK_SBUFFER_INIT_SIZE 2048
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_sbuffer Simple buffer
* @ingroup msgpack_buffer
* @{
*/
typedef struct msgpack_sbuffer {
size_t size;
char* data;
@@ -45,6 +48,22 @@ static inline void msgpack_sbuffer_destroy(msgpack_sbuffer* sbuf)
free(sbuf->data);
}
static inline msgpack_sbuffer* msgpack_sbuffer_new(void)
{
return (msgpack_sbuffer*)calloc(1, sizeof(msgpack_sbuffer));
}
static inline void msgpack_sbuffer_free(msgpack_sbuffer* sbuf)
{
if(sbuf == NULL) { return; }
msgpack_sbuffer_destroy(sbuf);
free(sbuf);
}
#ifndef MSGPACK_SBUFFER_INIT_SIZE
#define MSGPACK_SBUFFER_INIT_SIZE 8192
#endif
static inline int msgpack_sbuffer_write(void* data, const char* buf, unsigned int len)
{
msgpack_sbuffer* sbuf = (msgpack_sbuffer*)data;
@@ -76,6 +95,13 @@ static inline char* msgpack_sbuffer_release(msgpack_sbuffer* sbuf)
return tmp;
}
static inline void msgpack_sbuffer_clear(msgpack_sbuffer* sbuf)
{
sbuf->size = 0;
}
/** @} */
#ifdef __cplusplus
}

View File

@@ -72,6 +72,11 @@ public:
return msgpack_sbuffer_release(this);
}
void clear()
{
msgpack_sbuffer_clear(this);
}
private:
void expand_buffer(size_t len)
{

15
cpp/src/msgpack/type.hpp Normal file
View File

@@ -0,0 +1,15 @@
#include "msgpack/type/bool.hpp"
#include "msgpack/type/float.hpp"
#include "msgpack/type/int.hpp"
#include "msgpack/type/list.hpp"
#include "msgpack/type/deque.hpp"
#include "msgpack/type/map.hpp"
#include "msgpack/type/nil.hpp"
#include "msgpack/type/pair.hpp"
#include "msgpack/type/raw.hpp"
#include "msgpack/type/set.hpp"
#include "msgpack/type/string.hpp"
#include "msgpack/type/vector.hpp"
#include "msgpack/type/tuple.hpp"
#include "msgpack/type/define.hpp"

View File

@@ -15,8 +15,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef MSGPACK_TYPE_BOOLEAN_HPP__
#define MSGPACK_TYPE_BOOLEAN_HPP__
#ifndef MSGPACK_TYPE_BOOL_HPP__
#define MSGPACK_TYPE_BOOL_HPP__
#include "msgpack/object.hpp"
#include <vector>
@@ -31,7 +31,6 @@ inline bool& operator>> (object o, bool& v)
return v;
}
template <typename Stream>
inline packer<Stream>& operator<< (packer<Stream>& o, const bool& v)
{
@@ -40,6 +39,15 @@ inline packer<Stream>& operator<< (packer<Stream>& o, const bool& v)
return o;
}
inline void operator<< (object& o, bool v)
{
o.type = type::BOOLEAN;
o.via.boolean = v;
}
inline void operator<< (object::with_zone& o, bool v)
{ static_cast<object&>(o) << v; }
} // namespace msgpack

View File

@@ -0,0 +1,117 @@
//
// MessagePack for C++ static resolution routine
//
// 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_TYPE_DEFINE_HPP__
#define MSGPACK_TYPE_DEFINE_HPP__
#define MSGPACK_DEFINE(...) \
template <typename Packer> \
void msgpack_pack(Packer& pk) const \
{ \
msgpack::type::make_define(__VA_ARGS__).msgpack_pack(pk); \
} \
void msgpack_unpack(msgpack::object o) \
{ \
msgpack::type::make_define(__VA_ARGS__).msgpack_unpack(o); \
}\
template <typename MSGPACK_OBJECT> \
void msgpack_object(MSGPACK_OBJECT* o, msgpack::zone* z) const \
{ \
msgpack::type::make_define(__VA_ARGS__).msgpack_object(o, z); \
}
namespace msgpack {
namespace type {
<% GENERATION_LIMIT = 31 %>
template <typename A0 = void<%1.upto(GENERATION_LIMIT+1) {|i|%>, typename A<%=i%> = void<%}%>>
struct define;
template <>
struct define<> {
typedef define<> value_type;
typedef tuple<> tuple_type;
template <typename Packer>
void msgpack_pack(Packer& pk) const
{
pk.pack_array(1);
}
void msgpack_unpack(msgpack::object o)
{
if(o.type != type::ARRAY) { throw type_error(); }
}
void msgpack_object(msgpack::object* o, msgpack::zone* z) const
{
o->type = type::ARRAY;
o->via.array.ptr = NULL;
o->via.array.size = 0;
}
};
<%0.upto(GENERATION_LIMIT) {|i|%>
template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
struct define<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> {
typedef define<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> value_type;
typedef tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> tuple_type;
define(A0& _a0<%1.upto(i) {|j|%>, A<%=j%>& _a<%=j%><%}%>) :
a0(_a0)<%1.upto(i) {|j|%>, a<%=j%>(_a<%=j%>)<%}%> {}
template <typename Packer>
void msgpack_pack(Packer& pk) const
{
pk.pack_array(<%=i+1%>);
<%0.upto(i) {|j|%>
pk.pack(a<%=j%>);<%}%>
}
void msgpack_unpack(msgpack::object o)
{
if(o.type != type::ARRAY) { throw type_error(); }
const size_t size = o.via.array.size;
<%0.upto(i) {|j|%>
if(size <= <%=j%>) { return; } o.via.array.ptr[<%=j%>].convert(&a<%=j%>);<%}%>
}
void msgpack_object(msgpack::object* o, msgpack::zone* z) const
{
o->type = type::ARRAY;
o->via.array.ptr = (object*)z->malloc(sizeof(object)*<%=i+1%>);
o->via.array.size = <%=i+1%>;
<%0.upto(i) {|j|%>
o->via.array.ptr[<%=j%>] = object(a<%=j%>, z);<%}%>
}
<%0.upto(i) {|j|%>
A<%=j%>& a<%=j%>;<%}%>
};
<%}%>
inline define<> make_define()
{
return define<>();
}
<%0.upto(GENERATION_LIMIT) {|i|%>
template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
define<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> make_define(A0& a0<%1.upto(i) {|j|%>, A<%=j%>& a<%=j%><%}%>)
{
return define<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>(a0<%1.upto(i) {|j|%>, a<%=j%><%}%>);
}
<%}%>
} // namespace type
} // namespace msgpack
#endif /* msgpack/type/define.hpp */

View File

@@ -0,0 +1,77 @@
//
// MessagePack for C++ static resolution routine
//
// 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_TYPE_DEQUE_HPP__
#define MSGPACK_TYPE_DEQUE_HPP__
#include "msgpack/object.hpp"
#include <deque>
namespace msgpack {
template <typename T>
inline std::deque<T>& operator>> (object o, std::deque<T>& v)
{
if(o.type != type::ARRAY) { throw type_error(); }
v.resize(o.via.array.size);
object* p = o.via.array.ptr;
object* const pend = o.via.array.ptr + o.via.array.size;
typename std::deque<T>::iterator it = v.begin();
for(; p < pend; ++p, ++it) {
p->convert(&*it);
}
return v;
}
template <typename Stream, typename T>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::deque<T>& v)
{
o.pack_array(v.size());
for(typename std::deque<T>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) {
o.pack(*it);
}
return o;
}
template <typename T>
inline void operator<< (object::with_zone& o, const std::deque<T>& v)
{
o.type = type::ARRAY;
if(v.empty()) {
o.via.array.ptr = NULL;
o.via.array.size = 0;
} else {
object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
object* const pend = p + v.size();
o.via.array.ptr = p;
o.via.array.size = v.size();
typename std::deque<T>::const_iterator it(v.begin());
do {
*p = object(*it, o.zone);
++p;
++it;
} while(p < pend);
}
}
} // namespace msgpack
#endif /* msgpack/type/deque.hpp */

View File

@@ -34,7 +34,6 @@ inline float& operator>> (object o, float& v)
return v;
}
template <typename Stream>
inline packer<Stream>& operator<< (packer<Stream>& o, const float& v)
{
@@ -50,7 +49,6 @@ inline double& operator>> (object o, double& v)
return v;
}
template <typename Stream>
inline packer<Stream>& operator<< (packer<Stream>& o, const double& v)
{
@@ -59,6 +57,25 @@ inline packer<Stream>& operator<< (packer<Stream>& o, const double& v)
}
inline void operator<< (object& o, float v)
{
o.type = type::DOUBLE;
o.via.dec = v;
}
inline void operator<< (object& o, double v)
{
o.type = type::DOUBLE;
o.via.dec = v;
}
inline void operator<< (object::with_zone& o, float v)
{ static_cast<object&>(o) << v; }
inline void operator<< (object::with_zone& o, double v)
{ static_cast<object&>(o) << v; }
} // namespace msgpack
#endif /* msgpack/type/float.hpp */

View File

@@ -15,8 +15,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef MSGPACK_TYPE_INTEGER_HPP__
#define MSGPACK_TYPE_INTEGER_HPP__
#ifndef MSGPACK_TYPE_INT_HPP__
#define MSGPACK_TYPE_INT_HPP__
#include "msgpack/object.hpp"
#include <limits>
@@ -37,7 +37,7 @@ namespace detail {
{ throw type_error(); }
return o.via.u64;
} else if(o.type == type::NEGATIVE_INTEGER) {
if(o.via.i64 < (int64_t)-std::numeric_limits<T>::max())
if(o.via.i64 < (int64_t)std::numeric_limits<T>::min())
{ throw type_error(); }
return o.via.i64;
}
@@ -56,7 +56,7 @@ namespace detail {
throw type_error();
}
};
template <typename T>
static inline T convert_integer(object o)
{
@@ -141,7 +141,71 @@ inline packer<Stream>& operator<< (packer<Stream>& o, const unsigned long long&
{ o.pack_unsigned_long_long(v); return o; }
inline void operator<< (object& o, signed char v)
{ v < 0 ? o.type = type::NEGATIVE_INTEGER, o.via.i64 = v : o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
inline void operator<< (object& o, signed short v)
{ v < 0 ? o.type = type::NEGATIVE_INTEGER, o.via.i64 = v : o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
inline void operator<< (object& o, signed int v)
{ v < 0 ? o.type = type::NEGATIVE_INTEGER, o.via.i64 = v : o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
inline void operator<< (object& o, signed long v)
{ v < 0 ? o.type = type::NEGATIVE_INTEGER, o.via.i64 = v : o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
inline void operator<< (object& o, signed long long v)
{ v < 0 ? o.type = type::NEGATIVE_INTEGER, o.via.i64 = v : o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
inline void operator<< (object& o, unsigned char v)
{ o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
inline void operator<< (object& o, unsigned short v)
{ o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
inline void operator<< (object& o, unsigned int v)
{ o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
inline void operator<< (object& o, unsigned long v)
{ o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
inline void operator<< (object& o, unsigned long long v)
{ o.type = type::POSITIVE_INTEGER, o.via.u64 = v; }
inline void operator<< (object::with_zone& o, signed char v)
{ static_cast<object&>(o) << v; }
inline void operator<< (object::with_zone& o, signed short v)
{ static_cast<object&>(o) << v; }
inline void operator<< (object::with_zone& o, signed int v)
{ static_cast<object&>(o) << v; }
inline void operator<< (object::with_zone& o, signed long v)
{ static_cast<object&>(o) << v; }
inline void operator<< (object::with_zone& o, signed long long v)
{ static_cast<object&>(o) << v; }
inline void operator<< (object::with_zone& o, unsigned char v)
{ static_cast<object&>(o) << v; }
inline void operator<< (object::with_zone& o, unsigned short v)
{ static_cast<object&>(o) << v; }
inline void operator<< (object::with_zone& o, unsigned int v)
{ static_cast<object&>(o) << v; }
inline void operator<< (object::with_zone& o, unsigned long v)
{ static_cast<object&>(o) << v; }
inline void operator<< (object::with_zone& o, unsigned long long v)
{ static_cast<object&>(o) << v; }
} // namespace msgpack
#endif /* msgpack/type/integer.hpp */
#endif /* msgpack/type/int.hpp */

View File

@@ -15,43 +15,63 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef MSGPACK_TYPE_ARRAY_HPP__
#define MSGPACK_TYPE_ARRAY_HPP__
#ifndef MSGPACK_TYPE_LIST_HPP__
#define MSGPACK_TYPE_LIST_HPP__
#include "msgpack/object.hpp"
#include <vector>
#include <list>
namespace msgpack {
template <typename T>
inline std::vector<T> operator>> (object o, std::vector<T>& v)
inline std::list<T>& operator>> (object o, std::list<T>& v)
{
if(o.type != type::ARRAY) { throw type_error(); }
v.resize(o.via.array.size);
object* p = o.via.array.ptr;
object* const pend = o.via.array.ptr + o.via.array.size;
T* it = &v.front();
typename std::list<T>::iterator it = v.begin();
for(; p < pend; ++p, ++it) {
p->convert(it);
p->convert(&*it);
}
return v;
}
template <typename Stream, typename T>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::vector<T>& v)
inline packer<Stream>& operator<< (packer<Stream>& o, const std::list<T>& v)
{
o.pack_array(v.size());
for(typename std::vector<T>::const_iterator it(v.begin()), it_end(v.end());
for(typename std::list<T>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) {
o.pack(*it);
}
return o;
}
template <typename T>
inline void operator<< (object::with_zone& o, const std::list<T>& v)
{
o.type = type::ARRAY;
if(v.empty()) {
o.via.array.ptr = NULL;
o.via.array.size = 0;
} else {
object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
object* const pend = p + v.size();
o.via.array.ptr = p;
o.via.array.size = v.size();
typename std::list<T>::const_iterator it(v.begin());
do {
*p = object(*it, o.zone);
++p;
++it;
} while(p < pend);
}
}
} // namespace msgpack
#endif /* msgpack/type/array.hpp */
#endif /* msgpack/type/list.hpp */

View File

@@ -70,6 +70,28 @@ inline packer<Stream>& operator<< (packer<Stream>& o, const type::assoc_vector<K
return o;
}
template <typename K, typename V>
inline void operator<< (object::with_zone& o, const type::assoc_vector<K,V>& v)
{
o.type = type::MAP;
if(v.empty()) {
o.via.map.ptr = NULL;
o.via.map.size = 0;
} else {
object_kv* p = (object_kv*)o.zone->malloc(sizeof(object_kv)*v.size());
object_kv* const pend = p + v.size();
o.via.map.ptr = p;
o.via.map.size = v.size();
typename type::assoc_vector<K,V>::const_iterator it(v.begin());
do {
p->key = object(it->first, o.zone);
p->val = object(it->second, o.zone);
++p;
++it;
} while(p < pend);
}
}
template <typename K, typename V>
inline std::map<K, V> operator>> (object o, std::map<K, V>& v)
@@ -104,6 +126,28 @@ inline packer<Stream>& operator<< (packer<Stream>& o, const std::map<K,V>& v)
return o;
}
template <typename K, typename V>
inline void operator<< (object::with_zone& o, const std::map<K,V>& v)
{
o.type = type::MAP;
if(v.empty()) {
o.via.map.ptr = NULL;
o.via.map.size = 0;
} else {
object_kv* p = (object_kv*)o.zone->malloc(sizeof(object_kv)*v.size());
object_kv* const pend = p + v.size();
o.via.map.ptr = p;
o.via.map.size = v.size();
typename std::map<K,V>::const_iterator it(v.begin());
do {
p->key = object(it->first, o.zone);
p->val = object(it->second, o.zone);
++p;
++it;
} while(p < pend);
}
}
template <typename K, typename V>
inline std::multimap<K, V> operator>> (object o, std::multimap<K, V>& v)
@@ -132,6 +176,28 @@ inline packer<Stream>& operator<< (packer<Stream>& o, const std::multimap<K,V>&
return o;
}
template <typename K, typename V>
inline void operator<< (object::with_zone& o, const std::multimap<K,V>& v)
{
o.type = type::MAP;
if(v.empty()) {
o.via.map.ptr = NULL;
o.via.map.size = 0;
} else {
object_kv* p = (object_kv*)o.zone->malloc(sizeof(object_kv)*v.size());
object_kv* const pend = p + v.size();
o.via.map.ptr = p;
o.via.map.size = v.size();
typename std::multimap<K,V>::const_iterator it(v.begin());
do {
p->key = object(it->first, o.zone);
p->val = object(it->second, o.zone);
++p;
++it;
} while(p < pend);
}
}
} // namespace msgpack

View File

@@ -42,6 +42,22 @@ inline packer<Stream>& operator<< (packer<Stream>& o, const type::nil& v)
return o;
}
inline void operator<< (object& o, type::nil v)
{
o.type = type::NIL;
}
inline void operator<< (object::with_zone& o, type::nil v)
{ static_cast<object&>(o) << v; }
template <>
inline void object::as<void>() const
{
msgpack::type::nil v;
convert(&v);
}
} // namespace msgpack

View File

@@ -0,0 +1,61 @@
//
// MessagePack for C++ static resolution routine
//
// 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_TYPE_PAIR_HPP__
#define MSGPACK_TYPE_PAIR_HPP__
#include "msgpack/object.hpp"
#include <utility>
namespace msgpack {
template <typename T1, typename T2>
inline std::pair<T1, T2>& operator>> (object o, std::pair<T1, T2>& v)
{
if(o.type != type::ARRAY) { throw type_error(); }
if(o.via.array.size != 2) { throw type_error(); }
o.via.array.ptr[0].convert(&v.first);
o.via.array.ptr[1].convert(&v.second);
return v;
}
template <typename Stream, typename T1, typename T2>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::pair<T1, T2>& v)
{
o.pack_array(2);
o.pack(v.first);
o.pack(v.second);
return o;
}
template <typename T1, typename T2>
inline void operator<< (object::with_zone& o, const std::pair<T1, T2>& v)
{
o.type = type::ARRAY;
object* p = (object*)o.zone->malloc(sizeof(object)*2);
o.via.array.ptr = p;
o.via.array.size = 2;
p[0] = object(v.first, o.zone);
p[1] = object(v.second, o.zone);
}
} // namespace msgpack
#endif /* msgpack/type/pair.hpp */

View File

@@ -33,25 +33,25 @@ struct raw_ref {
uint32_t size;
const char* ptr;
std::string str() { return std::string(ptr, size); }
std::string str() const { return std::string(ptr, size); }
bool operator== (const raw_ref& x)
bool operator== (const raw_ref& x) const
{
return size == x.size && memcmp(ptr, x.ptr, size) == 0;
}
bool operator!= (const raw_ref& x)
bool operator!= (const raw_ref& x) const
{
return !(*this != x);
}
bool operator< (const raw_ref& x)
bool operator< (const raw_ref& x) const
{
if(size == x.size) { return memcmp(ptr, x.ptr, size) < 0; }
else { return size < x.size; }
}
bool operator> (const raw_ref& x)
bool operator> (const raw_ref& x) const
{
if(size == x.size) { return memcmp(ptr, x.ptr, size) > 0; }
else { return size > x.size; }
@@ -69,16 +69,6 @@ inline type::raw_ref& operator>> (object o, type::raw_ref& v)
return v;
}
inline std::string& operator>> (object o, std::string& v)
{
type::raw_ref r;
o >> r;
v.assign(r.ptr, r.size);
return v;
}
template <typename Stream>
inline packer<Stream>& operator<< (packer<Stream>& o, const type::raw_ref& v)
{
@@ -87,15 +77,16 @@ inline packer<Stream>& operator<< (packer<Stream>& o, const type::raw_ref& v)
return o;
}
template <typename Stream>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::string& v)
inline void operator<< (object& o, const type::raw_ref& v)
{
o.pack_raw(v.size());
o.pack_raw_body(v.data(), v.size());
return o;
o.type = type::RAW;
o.via.raw.ptr = v.ptr;
o.via.raw.size = v.size;
}
inline void operator<< (object::with_zone& o, const type::raw_ref& v)
{ static_cast<object&>(o) << v; }
} // namespace msgpack

View File

@@ -0,0 +1,122 @@
//
// MessagePack for C++ static resolution routine
//
// 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_TYPE_SET_HPP__
#define MSGPACK_TYPE_SET_HPP__
#include "msgpack/object.hpp"
#include <set>
namespace msgpack {
template <typename T>
inline std::set<T>& operator>> (object o, std::set<T>& v)
{
if(o.type != type::ARRAY) { throw type_error(); }
object* p = o.via.array.ptr + o.via.array.size;
object* const pbegin = o.via.array.ptr;
while(p > pbegin) {
--p;
v.insert(p->as<T>());
}
return v;
}
template <typename Stream, typename T>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::set<T>& v)
{
o.pack_array(v.size());
for(typename std::set<T>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) {
o.pack(*it);
}
return o;
}
template <typename T>
inline void operator<< (object::with_zone& o, const std::set<T>& v)
{
o.type = type::ARRAY;
if(v.empty()) {
o.via.array.ptr = NULL;
o.via.array.size = 0;
} else {
object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
object* const pend = p + v.size();
o.via.array.ptr = p;
o.via.array.size = v.size();
typename std::set<T>::const_iterator it(v.begin());
do {
*p = object(*it, o.zone);
++p;
++it;
} while(p < pend);
}
}
template <typename T>
inline std::multiset<T>& operator>> (object o, std::multiset<T>& v)
{
if(o.type != type::ARRAY) { throw type_error(); }
object* p = o.via.array.ptr + o.via.array.size;
object* const pbegin = o.via.array.ptr;
while(p > pbegin) {
--p;
v.insert(p->as<T>());
}
return v;
}
template <typename Stream, typename T>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::multiset<T>& v)
{
o.pack_array(v.size());
for(typename std::multiset<T>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) {
o.pack(*it);
}
return o;
}
template <typename T>
inline void operator<< (object::with_zone& o, const std::multiset<T>& v)
{
o.type = type::ARRAY;
if(v.empty()) {
o.via.array.ptr = NULL;
o.via.array.size = 0;
} else {
object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
object* const pend = p + v.size();
o.via.array.ptr = p;
o.via.array.size = v.size();
typename std::multiset<T>::const_iterator it(v.begin());
do {
*p = object(*it, o.zone);
++p;
++it;
} while(p < pend);
}
}
} // namespace msgpack
#endif /* msgpack/type/set.hpp */

View File

@@ -0,0 +1,62 @@
//
// MessagePack for C++ static resolution routine
//
// 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_TYPE_STRING_HPP__
#define MSGPACK_TYPE_STRING_HPP__
#include "msgpack/object.hpp"
#include <string>
namespace msgpack {
inline std::string& operator>> (object o, std::string& v)
{
if(o.type != type::RAW) { throw type_error(); }
v.assign(o.via.raw.ptr, o.via.raw.size);
return v;
}
template <typename Stream>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::string& v)
{
o.pack_raw(v.size());
o.pack_raw_body(v.data(), v.size());
return o;
}
inline void operator<< (object::with_zone& o, const std::string& v)
{
o.type = type::RAW;
char* ptr = (char*)o.zone->malloc(v.size());
o.via.raw.ptr = ptr;
o.via.raw.size = v.size();
memcpy(ptr, v.data(), v.size());
}
inline void operator<< (object& o, const std::string& v)
{
o.type = type::RAW;
o.via.raw.ptr = v.data();
o.via.raw.size = v.size();
}
} // namespace msgpack
#endif /* msgpack/type/string.hpp */

View File

@@ -0,0 +1,129 @@
//
// MessagePack for C++ static resolution routine
//
// 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_TYPE_TR1_UNORDERED_MAP_HPP__
#define MSGPACK_TYPE_TR1_UNORDERED_MAP_HPP__
#include "msgpack/object.hpp"
#include <tr1/unordered_map>
namespace msgpack {
template <typename K, typename V>
inline std::tr1::unordered_map<K, V> operator>> (object o, std::tr1::unordered_map<K, V>& v)
{
if(o.type != type::MAP) { throw type_error(); }
object_kv* p(o.via.map.ptr);
object_kv* const pend(o.via.map.ptr + o.via.map.size);
for(; p != pend; ++p) {
K key;
p->key.convert(&key);
p->val.convert(&v[key]);
}
return v;
}
template <typename Stream, typename K, typename V>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::tr1::unordered_map<K,V>& v)
{
o.pack_map(v.size());
for(typename std::tr1::unordered_map<K,V>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) {
o.pack(it->first);
o.pack(it->second);
}
return o;
}
template <typename K, typename V>
inline void operator<< (object::with_zone& o, const std::tr1::unordered_map<K,V>& v)
{
o.type = type::MAP;
if(v.empty()) {
o.via.map.ptr = NULL;
o.via.map.size = 0;
} else {
object_kv* p = (object_kv*)o.zone->malloc(sizeof(object_kv)*v.size());
object_kv* const pend = p + v.size();
o.via.map.ptr = p;
o.via.map.size = v.size();
typename std::tr1::unordered_map<K,V>::const_iterator it(v.begin());
do {
p->key = object(it->first, o.zone);
p->val = object(it->second, o.zone);
++p;
++it;
} while(p < pend);
}
}
template <typename K, typename V>
inline std::tr1::unordered_multimap<K, V> operator>> (object o, std::tr1::unordered_multimap<K, V>& v)
{
if(o.type != type::MAP) { throw type_error(); }
object_kv* p(o.via.map.ptr);
object_kv* const pend(o.via.map.ptr + o.via.map.size);
for(; p != pend; ++p) {
std::pair<K, V> value;
p->key.convert(&value.first);
p->val.convert(&value.second);
v.insert(value);
}
return v;
}
template <typename Stream, typename K, typename V>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::tr1::unordered_multimap<K,V>& v)
{
o.pack_map(v.size());
for(typename std::tr1::unordered_multimap<K,V>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) {
o.pack(it->first);
o.pack(it->second);
}
return o;
}
template <typename K, typename V>
inline void operator<< (object::with_zone& o, const std::tr1::unordered_multimap<K,V>& v)
{
o.type = type::MAP;
if(v.empty()) {
o.via.map.ptr = NULL;
o.via.map.size = 0;
} else {
object_kv* p = (object_kv*)o.zone->malloc(sizeof(object_kv)*v.size());
object_kv* const pend = p + v.size();
o.via.map.ptr = p;
o.via.map.size = v.size();
typename std::tr1::unordered_multimap<K,V>::const_iterator it(v.begin());
do {
p->key = object(it->first, o.zone);
p->val = object(it->second, o.zone);
++p;
++it;
} while(p < pend);
}
}
} // namespace msgpack
#endif /* msgpack/type/map.hpp */

View File

@@ -0,0 +1,122 @@
//
// MessagePack for C++ static resolution routine
//
// 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_TYPE_TR1_UNORDERED_SET_HPP__
#define MSGPACK_TYPE_TR1_UNORDERED_SET_HPP__
#include "msgpack/object.hpp"
#include <tr1/unordered_set>
namespace msgpack {
template <typename T>
inline std::tr1::unordered_set<T>& operator>> (object o, std::tr1::unordered_set<T>& v)
{
if(o.type != type::ARRAY) { throw type_error(); }
object* p = o.via.array.ptr + o.via.array.size;
object* const pbegin = o.via.array.ptr;
while(p > pbegin) {
--p;
v.insert(p->as<T>());
}
return v;
}
template <typename Stream, typename T>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::tr1::unordered_set<T>& v)
{
o.pack_array(v.size());
for(typename std::tr1::unordered_set<T>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) {
o.pack(*it);
}
return o;
}
template <typename T>
inline void operator<< (object::with_zone& o, const std::tr1::unordered_set<T>& v)
{
o.type = type::ARRAY;
if(v.empty()) {
o.via.array.ptr = NULL;
o.via.array.size = 0;
} else {
object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
object* const pend = p + v.size();
o.via.array.ptr = p;
o.via.array.size = v.size();
typename std::tr1::unordered_set<T>::const_iterator it(v.begin());
do {
*p = object(*it, o.zone);
++p;
++it;
} while(p < pend);
}
}
template <typename T>
inline std::tr1::unordered_multiset<T>& operator>> (object o, std::tr1::unordered_multiset<T>& v)
{
if(o.type != type::ARRAY) { throw type_error(); }
object* p = o.via.array.ptr + o.via.array.size;
object* const pbegin = o.via.array.ptr;
while(p > pbegin) {
--p;
v.insert(p->as<T>());
}
return v;
}
template <typename Stream, typename T>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::tr1::unordered_multiset<T>& v)
{
o.pack_array(v.size());
for(typename std::tr1::unordered_multiset<T>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) {
o.pack(*it);
}
return o;
}
template <typename T>
inline void operator<< (object::with_zone& o, const std::tr1::unordered_multiset<T>& v)
{
o.type = type::ARRAY;
if(v.empty()) {
o.via.array.ptr = NULL;
o.via.array.size = 0;
} else {
object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
object* const pend = p + v.size();
o.via.array.ptr = p;
o.via.array.size = v.size();
typename std::tr1::unordered_multiset<T>::const_iterator it(v.begin());
do {
*p = object(*it, o.zone);
++p;
++it;
} while(p < pend);
}
}
} // namespace msgpack
#endif /* msgpack/type/set.hpp */

View File

@@ -26,7 +26,7 @@ namespace type {
// FIXME operator==
// FIXME operator!=
<% GENERATION_LIMIT = 15 %>
<% GENERATION_LIMIT = 31 %>
template <typename A0 = void<%1.upto(GENERATION_LIMIT+1) {|i|%>, typename A<%=i%> = void<%}%>>
struct tuple;
@@ -64,7 +64,6 @@ struct tuple_type<const T&> {
typedef const T& transparent_reference;
};
<%0.upto(GENERATION_LIMIT) {|i|%>
<%0.upto(i) {|j|%>
template <typename A0<%1.upto(i) {|k|%>, typename A<%=k%><%}%>>
@@ -78,7 +77,6 @@ private:
<%}%>
<%}%>
<%0.upto(GENERATION_LIMIT) {|i|%>
<%0.upto(i) {|j|%>
template <typename A0<%1.upto(i) {|k|%>, typename A<%=k%><%}%>>
@@ -91,18 +89,11 @@ private:
<%}%>
<%}%>
<%0.upto(GENERATION_LIMIT) {|i|%>
template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> make_tuple(typename tuple_type<A0>::transparent_reference a0<%1.upto(i) {|j|%>, typename tuple_type<A<%=j%>>::transparent_reference a<%=j%><%}%>)
{
return tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>(a0<%1.upto(i) {|j|%>, a<%=j%><%}%>);
}
<%}%>
template <>
struct tuple<> {
tuple() {}
tuple(object o) { o.convert(this); }
typedef tuple<> value_type;
};
<%0.upto(GENERATION_LIMIT) {|i|%>
template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
@@ -121,6 +112,18 @@ struct tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> {
};
<%}%>
inline tuple<> make_tuple()
{
return tuple<>();
}
<%0.upto(GENERATION_LIMIT) {|i|%>
template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> make_tuple(typename tuple_type<A0>::transparent_reference a0<%1.upto(i) {|j|%>, typename tuple_type<A<%=j%>>::transparent_reference a<%=j%><%}%>)
{
return tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>(a0<%1.upto(i) {|j|%>, a<%=j%><%}%>);
}
<%}%>
} // namespace type
@@ -138,12 +141,11 @@ type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>& operator>> (
if(o.type != type::ARRAY) { throw type_error(); }
if(o.via.array.size < <%=i+1%>) { throw type_error(); }
<%0.upto(i) {|j|%>
o.via.array.ptr[<%=j%>].convert<A<%=j%>>(&v.template get<<%=j%>>());<%}%>
o.via.array.ptr[<%=j%>].convert<typename type::tuple_type<A<%=j%>>::type>(&v.template get<<%=j%>>());<%}%>
return v;
}
<%}%>
template <typename Stream>
const packer<Stream>& operator<< (
packer<Stream>& o,
@@ -163,8 +165,42 @@ const packer<Stream>& operator<< (
}
<%}%>
inline void operator<< (
object::with_zone& o,
const type::tuple<>& v) {
o.type = type::ARRAY;
o.via.array.ptr = NULL;
o.via.array.size = 0;
}
<%0.upto(GENERATION_LIMIT) {|i|%>
template <typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
inline void operator<< (
object::with_zone& o,
const type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>& v) {
o.type = type::ARRAY;
o.via.array.ptr = (object*)o.zone->malloc(sizeof(object)*<%=i+1%>);
o.via.array.size = <%=i+1%>;
<%0.upto(i) {|j|%>
o.via.array.ptr[<%=j%>] = object(v.template get<<%=j%>>(), o.zone);<%}%>
}
<%}%>
} // 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,81 @@
//
// MessagePack for C++ static resolution routine
//
// 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_TYPE_VECTOR_HPP__
#define MSGPACK_TYPE_VECTOR_HPP__
#include "msgpack/object.hpp"
#include <vector>
namespace msgpack {
template <typename T>
inline std::vector<T>& operator>> (object o, std::vector<T>& v)
{
if(o.type != type::ARRAY) { throw type_error(); }
v.resize(o.via.array.size);
if(o.via.array.size > 0) {
object* p = o.via.array.ptr;
object* const pend = o.via.array.ptr + o.via.array.size;
T* it = &v[0];
do {
p->convert(it);
++p;
++it;
} while(p < pend);
}
return v;
}
template <typename Stream, typename T>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::vector<T>& v)
{
o.pack_array(v.size());
for(typename std::vector<T>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) {
o.pack(*it);
}
return o;
}
template <typename T>
inline void operator<< (object::with_zone& o, const std::vector<T>& v)
{
o.type = type::ARRAY;
if(v.empty()) {
o.via.array.ptr = NULL;
o.via.array.size = 0;
} else {
object* p = (object*)o.zone->malloc(sizeof(object)*v.size());
object* const pend = p + v.size();
o.via.array.ptr = p;
o.via.array.size = v.size();
typename std::vector<T>::const_iterator it(v.begin());
do {
*p = object(*it, o.zone);
++p;
++it;
} while(p < pend);
}
}
} // namespace msgpack
#endif /* msgpack/type/vector.hpp */

260
cpp/src/msgpack/unpack.h Normal file
View File

@@ -0,0 +1,260 @@
/*
* MessagePack for C unpacking routine
*
* 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_UNPACKER_H__
#define MSGPACK_UNPACKER_H__
#include "msgpack/zone.h"
#include "msgpack/object.h"
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_unpack Deserializer
* @ingroup msgpack
* @{
*/
typedef struct msgpack_unpacked {
msgpack_zone* zone;
msgpack_object data;
} msgpack_unpacked;
bool msgpack_unpack_next(msgpack_unpacked* result,
const char* data, size_t len, size_t* off);
/** @} */
/**
* @defgroup msgpack_unpacker Streaming deserializer
* @ingroup msgpack
* @{
*/
typedef struct msgpack_unpacker {
char* buffer;
size_t used;
size_t free;
size_t off;
size_t parsed;
msgpack_zone* z;
size_t initial_buffer_size;
void* ctx;
} msgpack_unpacker;
#ifndef MSGPACK_UNPACKER_INIT_BUFFER_SIZE
#define MSGPACK_UNPACKER_INIT_BUFFER_SIZE (64*1024)
#endif
/**
* Initializes a streaming deserializer.
* The initialized deserializer must be destroyed by msgpack_unpacker_destroy(msgpack_unpacker*).
*/
bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size);
/**
* Destroys a streaming deserializer initialized by msgpack_unpacker_init(msgpack_unpacker*, size_t).
*/
void msgpack_unpacker_destroy(msgpack_unpacker* mpac);
/**
* Creates a streaming deserializer.
* The created deserializer must be destroyed by msgpack_unpacker_free(msgpack_unpacker*).
*/
msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size);
/**
* Frees a streaming deserializer created by msgpack_unpacker_new(size_t).
*/
void msgpack_unpacker_free(msgpack_unpacker* mpac);
#ifndef MSGPACK_UNPACKER_RESERVE_SIZE
#define MSGPACK_UNPACKER_RESERVE_SIZE (32*1024)
#endif
/**
* Reserves free space of the internal buffer.
* Use this function to fill the internal buffer with
* msgpack_unpacker_buffer(msgpack_unpacker*),
* msgpack_unpacker_buffer_capacity(const msgpack_unpacker*) and
* msgpack_unpacker_buffer_consumed(msgpack_unpacker*).
*/
static inline bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size);
/**
* Gets pointer to the free space of the internal buffer.
* Use this function to fill the internal buffer with
* msgpack_unpacker_reserve_buffer(msgpack_unpacker*, size_t),
* msgpack_unpacker_buffer_capacity(const msgpack_unpacker*) and
* msgpack_unpacker_buffer_consumed(msgpack_unpacker*).
*/
static inline char* msgpack_unpacker_buffer(msgpack_unpacker* mpac);
/**
* Gets size of the free space of the internal buffer.
* Use this function to fill the internal buffer with
* msgpack_unpacker_reserve_buffer(msgpack_unpacker*, size_t),
* msgpack_unpacker_buffer(const msgpack_unpacker*) and
* msgpack_unpacker_buffer_consumed(msgpack_unpacker*).
*/
static inline size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac);
/**
* Notifies the deserializer that the internal buffer filled.
* Use this function to fill the internal buffer with
* msgpack_unpacker_reserve_buffer(msgpack_unpacker*, size_t),
* msgpack_unpacker_buffer(msgpack_unpacker*) and
* msgpack_unpacker_buffer_capacity(const msgpack_unpacker*).
*/
static inline void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size);
/**
* Deserializes one object.
* Returns true if it successes. Otherwise false is returned.
* @param pac pointer to an initialized msgpack_unpacked object.
*/
bool msgpack_unpacker_next(msgpack_unpacker* mpac, msgpack_unpacked* pac);
/**
* Initializes a msgpack_unpacked object.
* The initialized object must be destroyed by msgpack_unpacked_destroy(msgpack_unpacker*).
* Use the object with msgpack_unpacker_next(msgpack_unpacker*, msgpack_unpacked*) or
* msgpack_unpack_next(msgpack_unpacked*, const char*, size_t, size_t*).
*/
static inline void msgpack_unpacked_init(msgpack_unpacked* result);
/**
* Destroys a streaming deserializer initialized by msgpack_unpacked().
*/
static inline void msgpack_unpacked_destroy(msgpack_unpacked* result);
/**
* Releases the memory zone from msgpack_unpacked object.
* The released zone must be freed by msgpack_zone_free(msgpack_zone*).
*/
static inline msgpack_zone* msgpack_unpacked_release_zone(msgpack_unpacked* result);
int msgpack_unpacker_execute(msgpack_unpacker* mpac);
msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac);
msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac);
void msgpack_unpacker_reset_zone(msgpack_unpacker* mpac);
void msgpack_unpacker_reset(msgpack_unpacker* mpac);
static inline size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac);
/** @} */
// obsolete
typedef enum {
MSGPACK_UNPACK_SUCCESS = 2,
MSGPACK_UNPACK_EXTRA_BYTES = 1,
MSGPACK_UNPACK_CONTINUE = 0,
MSGPACK_UNPACK_PARSE_ERROR = -1,
} msgpack_unpack_return;
// obsolete
msgpack_unpack_return
msgpack_unpack(const char* data, size_t len, size_t* off,
msgpack_zone* result_zone, msgpack_object* result);
static inline size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac);
bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac);
bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size);
bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size)
{
if(mpac->free >= size) { return true; }
return msgpack_unpacker_expand_buffer(mpac, size);
}
char* msgpack_unpacker_buffer(msgpack_unpacker* mpac)
{
return mpac->buffer + mpac->used;
}
size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac)
{
return mpac->free;
}
void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size)
{
mpac->used += size;
mpac->free -= size;
}
size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac)
{
return mpac->parsed - mpac->off + mpac->used;
}
size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac)
{
return mpac->parsed;
}
void msgpack_unpacked_init(msgpack_unpacked* result)
{
memset(result, 0, sizeof(msgpack_unpacked));
}
void msgpack_unpacked_destroy(msgpack_unpacked* result)
{
if(result->zone != NULL) {
msgpack_zone_free(result->zone);
result->zone = NULL;
memset(&result->data, 0, sizeof(msgpack_object));
}
}
msgpack_zone* msgpack_unpacked_release_zone(msgpack_unpacked* result)
{
if(result->zone != NULL) {
msgpack_zone* z = result->zone;
result->zone = NULL;
return z;
}
return NULL;
}
#ifdef __cplusplus
}
#endif
#endif /* msgpack/unpack.h */

View File

@@ -24,8 +24,9 @@
#include <memory>
#include <stdexcept>
// backward compatibility
#ifndef MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE
#define MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE (32*1024)
#define MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE MSGPACK_UNPACKER_INIT_BUFFER_SIZE
#endif
namespace msgpack {
@@ -37,14 +38,39 @@ struct unpack_error : public std::runtime_error {
};
class unpacked {
public:
unpacked() { }
unpacked(object obj, std::auto_ptr<msgpack::zone> z) :
m_obj(obj), m_zone(z) { }
object& get()
{ return m_obj; }
const object& get() const
{ return m_obj; }
std::auto_ptr<msgpack::zone>& zone()
{ return m_zone; }
const std::auto_ptr<msgpack::zone>& zone() const
{ return m_zone; }
private:
object m_obj;
std::auto_ptr<msgpack::zone> m_zone;
};
class unpacker : public msgpack_unpacker {
public:
unpacker(size_t init_buffer_size = MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE);
unpacker(size_t init_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
~unpacker();
public:
/*! 1. reserve buffer. at least `size' bytes of capacity will be ready */
void reserve_buffer(size_t size);
void reserve_buffer(size_t size = MSGPACK_UNPACKER_RESERVE_SIZE);
/*! 2. read data to the buffer() up to buffer_capacity() bytes */
char* buffer();
@@ -53,39 +79,22 @@ public:
/*! 3. specify the number of bytes actually copied */
void buffer_consumed(size_t size);
/*! 4. repeat execute() until it retunrs false */
bool execute();
/*! 4. repeat next() until it retunrs false */
bool next(unpacked* result);
/*! 5.1. if execute() returns true, take out the parsed object */
object data();
/*! 5.2. the object is valid until the zone is deleted */
// Note that once release_zone() from unpacker, you must delete it
// otherwise the memrory will leak.
zone* release_zone();
/*! 5.2. this method is equivalence to `delete release_zone()` */
void reset_zone();
/*! 5.3. after release_zone(), re-initialize unpacker */
void reset();
/*! 6. check if the size of message doesn't exceed assumption. */
/*! 5. check if the size of message doesn't exceed assumption. */
size_t message_size() const;
// Basic usage of the unpacker is as following:
//
// msgpack::unpacker pac;
//
// while( /* readable */ ) {
// while( /* input is readable */ ) {
//
// // 1.
// pac.reserve(1024);
// pac.reserve_buffer(32*1024);
//
// // 2.
// ssize_t bytes =
// read(the_source, pac.buffer(), pac.buffer_capacity());
// size_t bytes = input.readsome(pac.buffer(), pac.buffer_capacity());
//
// // error handling ...
//
@@ -93,25 +102,40 @@ public:
// pac.buffer_consumed(bytes);
//
// // 4.
// while(pac.execute()) {
// // 5.1
// object o = pac.data();
// msgpack::unpacked result;
// while(pac.next(&result)) {
// // do some with the object with the zone.
// msgpack::object obj = result.get();
// std::auto_ptr<msgpack:zone> z = result.zone();
// on_message(obj, z);
//
// // 5.2
// std::auto_ptr<msgpack::zone> olife( pac.release_zone() );
// //// boost::shared_ptr is also usable:
// // boost::shared_ptr<msgpack::zone> life(z.release());
// // on_message(result.get(), life);
// }
//
// // boost::shared_ptr is also usable:
// // boost::shared_ptr<msgpack::zone> olife( pac.release_zone() );
//
// // 5.3
// pac.reset();
//
// // do some with the object with the old zone.
// do_something(o, olife);
// // 5.
// if(pac.message_size() > 10*1024*1024) {
// throw std::runtime_error("message is too large");
// }
// }
//
/*! for backward compatibility */
bool execute();
/*! for backward compatibility */
object data();
/*! for backward compatibility */
zone* release_zone();
/*! for backward compatibility */
void reset_zone();
/*! for backward compatibility */
void reset();
public:
// These functions are usable when non-MessagePack message follows after
// MessagePack message.
@@ -137,6 +161,11 @@ private:
};
static void unpack(unpacked* result,
const char* data, size_t len, size_t* offset = NULL);
// obsolete
typedef enum {
UNPACK_SUCCESS = 2,
UNPACK_EXTRA_BYTES = 1,
@@ -144,6 +173,7 @@ typedef enum {
UNPACK_PARSE_ERROR = -1,
} unpack_return;
// obsolete
static unpack_return unpack(const char* data, size_t len, size_t* off,
zone* z, object* result);
@@ -187,6 +217,27 @@ inline void unpacker::buffer_consumed(size_t size)
return msgpack_unpacker_buffer_consumed(this, size);
}
inline bool unpacker::next(unpacked* result)
{
int ret = msgpack_unpacker_execute(this);
if(ret < 0) {
throw unpack_error("parse error");
}
if(ret == 0) {
result->zone().reset();
result->get() = object();
return false;
} else {
result->zone().reset( release_zone() );
result->get() = data();
reset();
return true;
}
}
inline bool unpacker::execute()
{
@@ -230,12 +281,12 @@ inline void unpacker::reset()
msgpack_unpacker_reset(this);
}
inline size_t unpacker::message_size() const
{
return msgpack_unpacker_message_size(this);
}
inline size_t unpacker::parsed_size() const
{
return msgpack_unpacker_parsed_size(this);
@@ -262,6 +313,38 @@ inline void unpacker::remove_nonparsed_buffer()
}
inline void unpack(unpacked* result,
const char* data, size_t len, size_t* offset)
{
msgpack::object obj;
std::auto_ptr<msgpack::zone> z(new zone());
unpack_return ret = (unpack_return)msgpack_unpack(
data, len, offset, z.get(),
reinterpret_cast<msgpack_object*>(&obj));
switch(ret) {
case UNPACK_SUCCESS:
result->get() = obj;
result->zone() = z;
return;
case UNPACK_EXTRA_BYTES:
result->get() = obj;
result->zone() = z;
return;
case UNPACK_CONTINUE:
throw unpack_error("insufficient bytes");
case UNPACK_PARSE_ERROR:
default:
throw unpack_error("parse error");
}
}
// obsolete
inline unpack_return unpack(const char* data, size_t len, size_t* off,
zone* z, object* result)
{

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 */

View File

@@ -19,43 +19,64 @@
#define MSGPACK_VREFBUFFER_H__
#include "msgpack/zone.h"
#include <stdlib.h>
#ifndef _WIN32
#include <sys/uio.h>
#else
struct iovec {
void *iov_base;
size_t iov_len;
};
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_vrefbuffer Vectored Referencing buffer
* @ingroup msgpack_buffer
* @{
*/
struct msgpack_vrefbuffer_chunk;
typedef struct msgpack_vrefbuffer_chunk msgpack_vrefbuffer_chunk;
typedef struct msgpack_vrefbuffer_inner_buffer {
size_t free;
char* ptr;
msgpack_vrefbuffer_chunk* head;
} msgpack_vrefbuffer_inner_buffer;
typedef struct msgpack_vrefbuffer {
struct iovec* tail;
struct iovec* end;
struct iovec* array;
size_t chunk_size;
size_t ref_size;
msgpack_vrefbuffer_inner_buffer inner_buffer;
} msgpack_vrefbuffer;
#ifndef MSGPACK_VREFBUFFER_REF_SIZE
#define MSGPACK_VREFBUFFER_REF_SIZE 32
#endif
#ifndef MSGPACK_VREFBUFFER_CHUNK_SIZE
#define MSGPACK_VREFBUFFER_CHUNK_SIZE 2048
#define MSGPACK_VREFBUFFER_CHUNK_SIZE 8192
#endif
typedef struct msgpack_vrefbuffer_chunk {
size_t free;
struct msgpack_vrefbuffer_chunk* next;
/* data ... */
} msgpack_vrefbuffer_chunk;
typedef struct msgpack_vrefbuffer {
size_t chunk_size;
size_t ref_size;
struct iovec* tail;
struct iovec* end;
struct iovec* array;
msgpack_vrefbuffer_chunk* chunk;
} msgpack_vrefbuffer;
bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
size_t ref_size, size_t chunk_size);
void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf);
static inline msgpack_vrefbuffer* msgpack_vrefbuffer_new(size_t ref_size, size_t chunk_size);
static inline void msgpack_vrefbuffer_free(msgpack_vrefbuffer* vbuf);
static inline int msgpack_vrefbuffer_write(void* data, const char* buf, unsigned int len);
static inline const struct iovec* msgpack_vrefbuffer_vec(const msgpack_vrefbuffer* vref);
@@ -67,6 +88,29 @@ int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
const char* buf, unsigned int len);
int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to);
void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vref);
/** @} */
msgpack_vrefbuffer* msgpack_vrefbuffer_new(size_t ref_size, size_t chunk_size)
{
msgpack_vrefbuffer* vbuf = (msgpack_vrefbuffer*)malloc(sizeof(msgpack_vrefbuffer));
if(!msgpack_vrefbuffer_init(vbuf, ref_size, chunk_size)) {
free(vbuf);
return NULL;
}
return vbuf;
}
void msgpack_vrefbuffer_free(msgpack_vrefbuffer* vbuf)
{
if(vbuf == NULL) { return; }
msgpack_vrefbuffer_destroy(vbuf);
free(vbuf);
}
int msgpack_vrefbuffer_write(void* data, const char* buf, unsigned int len)
{
@@ -89,6 +133,7 @@ size_t msgpack_vrefbuffer_veclen(const msgpack_vrefbuffer* vref)
return vref->tail - vref->array;
}
#ifdef __cplusplus
}
#endif

View File

@@ -71,6 +71,18 @@ public:
return msgpack_vrefbuffer_veclen(this);
}
void migrate(vrefbuffer* to)
{
if(msgpack_vrefbuffer_migrate(this, to) < 0) {
throw std::bad_alloc();
}
}
void clear()
{
msgpack_vrefbuffer_clear(this);
}
private:
typedef msgpack_vrefbuffer base;

207
cpp/src/msgpack/zbuffer.h Normal file
View File

@@ -0,0 +1,207 @@
/*
* MessagePack for C deflate buffer implementation
*
* Copyright (C) 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 MSGPACK_ZBUFFER_H__
#define MSGPACK_ZBUFFER_H__
#include "msgpack/sysdep.h"
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup msgpack_zbuffer Compressed buffer
* @ingroup msgpack_buffer
* @{
*/
typedef struct msgpack_zbuffer {
z_stream stream;
char* data;
size_t init_size;
} msgpack_zbuffer;
#ifndef MSGPACK_ZBUFFER_INIT_SIZE
#define MSGPACK_ZBUFFER_INIT_SIZE 8192
#endif
static inline bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf,
int level, size_t init_size);
static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf);
static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size);
static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf);
static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf);
static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf);
static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf);
static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf);
static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf);
static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf);
#ifndef MSGPACK_ZBUFFER_RESERVE_SIZE
#define MSGPACK_ZBUFFER_RESERVE_SIZE 512
#endif
static inline int msgpack_zbuffer_write(void* data, const char* buf, unsigned int len);
static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf);
bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf,
int level, size_t init_size)
{
memset(zbuf, 0, sizeof(msgpack_zbuffer));
zbuf->init_size = init_size;
if(deflateInit(&zbuf->stream, level) != Z_OK) {
free(zbuf->data);
return false;
}
return true;
}
void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf)
{
deflateEnd(&zbuf->stream);
free(zbuf->data);
}
msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size)
{
msgpack_zbuffer* zbuf = (msgpack_zbuffer*)malloc(sizeof(msgpack_zbuffer));
if(!msgpack_zbuffer_init(zbuf, level, init_size)) {
free(zbuf);
return NULL;
}
return zbuf;
}
void msgpack_zbuffer_free(msgpack_zbuffer* zbuf)
{
if(zbuf == NULL) { return; }
msgpack_zbuffer_destroy(zbuf);
free(zbuf);
}
bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf)
{
size_t used = (char*)zbuf->stream.next_out - zbuf->data;
size_t csize = used + zbuf->stream.avail_out;
size_t nsize = (csize == 0) ? zbuf->init_size : csize * 2;
char* tmp = (char*)realloc(zbuf->data, nsize);
if(tmp == NULL) {
return false;
}
zbuf->data = tmp;
zbuf->stream.next_out = (Bytef*)(tmp + used);
zbuf->stream.avail_out = nsize - used;
return true;
}
int msgpack_zbuffer_write(void* data, const char* buf, unsigned int len)
{
msgpack_zbuffer* zbuf = (msgpack_zbuffer*)data;
zbuf->stream.next_in = (Bytef*)buf;
zbuf->stream.avail_in = len;
do {
if(zbuf->stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) {
if(!msgpack_zbuffer_expand(zbuf)) {
return -1;
}
}
if(deflate(&zbuf->stream, Z_NO_FLUSH) != Z_OK) {
return -1;
}
} while(zbuf->stream.avail_in > 0);
return 0;
}
char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf)
{
while(true) {
switch(deflate(&zbuf->stream, Z_FINISH)) {
case Z_STREAM_END:
return zbuf->data;
case Z_OK:
if(!msgpack_zbuffer_expand(zbuf)) {
return NULL;
}
break;
default:
return NULL;
}
}
}
const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf)
{
return zbuf->data;
}
size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf)
{
return (char*)zbuf->stream.next_out - zbuf->data;
}
void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf)
{
zbuf->stream.avail_out += (char*)zbuf->stream.next_out - zbuf->data;
zbuf->stream.next_out = (Bytef*)zbuf->data;
}
bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf)
{
if(deflateReset(&zbuf->stream) != Z_OK) {
return false;
}
msgpack_zbuffer_reset_buffer(zbuf);
return true;
}
char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf)
{
char* tmp = zbuf->data;
zbuf->data = NULL;
zbuf->stream.next_out = NULL;
zbuf->stream.avail_out = 0;
return tmp;
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* msgpack/zbuffer.h */

100
cpp/src/msgpack/zbuffer.hpp Normal file
View File

@@ -0,0 +1,100 @@
//
// MessagePack for C++ deflate buffer implementation
//
// Copyright (C) 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 MSGPACK_ZBUFFER_HPP__
#define MSGPACK_ZBUFFER_HPP__
#include "msgpack/zbuffer.h"
#include <stdexcept>
namespace msgpack {
class zbuffer : public msgpack_zbuffer {
public:
zbuffer(int level = Z_DEFAULT_COMPRESSION,
size_t init_size = MSGPACK_ZBUFFER_INIT_SIZE)
{
msgpack_zbuffer_init(this, level, init_size);
}
~zbuffer()
{
msgpack_zbuffer_destroy(this);
}
public:
void write(const char* buf, unsigned int len)
{
if(msgpack_zbuffer_write(this, buf, len) < 0) {
throw std::bad_alloc();
}
}
char* flush()
{
char* buf = msgpack_zbuffer_flush(this);
if(!buf) {
throw std::bad_alloc();
}
return buf;
}
char* data()
{
return base::data;
}
const char* data() const
{
return base::data;
}
size_t size() const
{
return msgpack_zbuffer_size(this);
}
void reset()
{
if(!msgpack_zbuffer_reset(this)) {
throw std::bad_alloc();
}
}
void reset_buffer()
{
msgpack_zbuffer_reset_buffer(this);
}
char* release_buffer()
{
return msgpack_zbuffer_release_buffer(this);
}
private:
typedef msgpack_zbuffer base;
private:
zbuffer(const zbuffer&);
};
} // namespace msgpack
#endif /* msgpack/zbuffer.hpp */

View File

@@ -18,45 +18,47 @@
#ifndef MSGPACK_ZONE_H__
#define MSGPACK_ZONE_H__
#include <stddef.h>
#include <stdbool.h>
#include "msgpack/sysdep.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct msgpack_zone_chunk {
size_t free;
char* ptr;
void* alloc;
} msgpack_zone_chunk;
/**
* @defgroup msgpack_zone Memory zone
* @ingroup msgpack
* @{
*/
typedef struct msgpack_zone_finalizer {
void (*func)(void* data);
void* data;
} msgpack_zone_finalizer;
typedef struct msgpack_zone_chunk_array {
msgpack_zone_chunk* tail;
msgpack_zone_chunk* end;
msgpack_zone_chunk* array;
} msgpack_zone_chunk_array;
typedef struct msgpack_zone_finalizer_array {
msgpack_zone_finalizer* tail;
msgpack_zone_finalizer* end;
msgpack_zone_finalizer* array;
} msgpack_zone_finalizer_array;
struct msgpack_zone_chunk;
typedef struct msgpack_zone_chunk msgpack_zone_chunk;
typedef struct msgpack_zone_chunk_list {
size_t free;
char* ptr;
msgpack_zone_chunk* head;
} msgpack_zone_chunk_list;
typedef struct msgpack_zone {
msgpack_zone_chunk_array chunk_array;
msgpack_zone_chunk_list chunk_list;
msgpack_zone_finalizer_array finalizer_array;
size_t chunk_size;
} msgpack_zone;
#ifndef MSGPACK_ZONE_CHUNK_SIZE
#define MSGPACK_ZONE_CHUNK_SIZE 2048
#define MSGPACK_ZONE_CHUNK_SIZE 8192
#endif
bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size);
@@ -75,6 +77,7 @@ bool msgpack_zone_is_empty(msgpack_zone* zone);
void msgpack_zone_clear(msgpack_zone* zone);
/** @} */
#ifndef MSGPACK_ZONE_ALIGN
@@ -85,15 +88,15 @@ void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size);
void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size)
{
msgpack_zone_chunk* chunk = zone->chunk_array.tail;
msgpack_zone_chunk_list* cl = &zone->chunk_list;
if(chunk->free < size) {
if(zone->chunk_list.free < size) {
return msgpack_zone_malloc_expand(zone, size);
}
char* ptr = chunk->ptr;
chunk->ptr += size;
chunk->free -= size;
char* ptr = cl->ptr;
cl->free -= size;
cl->ptr += size;
return ptr;
}

View File

@@ -18,9 +18,9 @@
#ifndef MSGPACK_ZONE_HPP__
#define MSGPACK_ZONE_HPP__
#include "msgpack/object.hpp"
#include "msgpack/zone.h"
#include <cstdlib>
#include <memory>
#include <vector>
<% GENERATION_LIMIT = 15 %>
@@ -38,6 +38,9 @@ public:
void push_finalizer(void (*func)(void*), void* data);
template <typename T>
void push_finalizer(std::auto_ptr<T> obj);
void clear();
<%0.upto(GENERATION_LIMIT) {|i|%>
@@ -94,6 +97,15 @@ inline void zone::push_finalizer(void (*func)(void*), void* data)
}
}
template <typename T>
inline void zone::push_finalizer(std::auto_ptr<T> obj)
{
if(!msgpack_zone_push_finalizer(this, &zone::object_destructor<T>, obj.get())) {
throw std::bad_alloc();
}
obj.release();
}
inline void zone::clear()
{
msgpack_zone_clear(this);
@@ -107,9 +119,8 @@ void zone::object_destructor(void* obj)
inline void zone::undo_malloc(size_t size)
{
msgpack_zone_chunk* chunk = base::chunk_array.tail;
chunk->ptr -= size;
chunk->free += size;
base::chunk_list.ptr -= size;
base::chunk_list.free += size;
}
<%0.upto(GENERATION_LIMIT) {|i|%>

View File

@@ -17,8 +17,6 @@
//
#include "msgpack/object.hpp"
#include <string.h>
namespace msgpack {
@@ -62,7 +60,6 @@ std::ostream& operator<< (std::ostream& s, const object o)
}
s << "]";
break;
// FIXME loop optimiziation
case type::MAP:
s << "{";
@@ -77,7 +74,6 @@ std::ostream& operator<< (std::ostream& s, const object o)
}
s << "}";
break;
// FIXME loop optimiziation
default:
// FIXME
@@ -87,53 +83,5 @@ std::ostream& operator<< (std::ostream& s, const object o)
}
bool operator==(const object x, const object y)
{
if(x.type != y.type) { return false; }
switch(x.type) {
case type::NIL:
return true;
case type::BOOLEAN:
return x.via.boolean == y.via.boolean;
case type::POSITIVE_INTEGER:
return x.via.u64 == y.via.u64;
case type::NEGATIVE_INTEGER:
return x.via.i64 == y.via.i64;
case type::RAW:
return x.via.raw.size == y.via.raw.size &&
memcmp(x.via.raw.ptr, y.via.raw.ptr, x.via.raw.size) == 0;
case type::ARRAY:
if(x.via.array.size != y.via.array.size) { return false; }
for(object* px(x.via.array.ptr),
* const pxend(x.via.array.ptr + x.via.array.size),
* py(y.via.array.ptr);
px < pxend; ++px, ++py) {
if(*px != *py) { return false; }
}
return true;
// FIXME loop optimiziation
case type::MAP:
if(x.via.map.size != y.via.map.size) { return false; }
for(object_kv* px(x.via.map.ptr),
* const pxend(x.via.map.ptr + x.via.map.size),
* py(y.via.map.ptr);
px < pxend; ++px, ++py) {
if(px->key != py->key || px->val != py->val) { return false; }
}
return true;
default:
return false;
}
}
} // namespace msgpack

View File

@@ -18,7 +18,18 @@
#include "msgpack/object.h"
#include "msgpack/pack.h"
#include <stdio.h>
#include <string.h>
#ifndef _MSC_VER
#include <inttypes.h>
#else
#ifndef PRIu64
#define PRIu64 "I64u"
#endif
#ifndef PRIi64
#define PRIi64 "I64d"
#endif
#endif
int msgpack_pack_object(msgpack_packer* pk, msgpack_object d)
@@ -131,7 +142,6 @@ void msgpack_object_print(FILE* out, msgpack_object o)
}
fprintf(out, "]");
break;
// FIXME loop optimiziation
case MSGPACK_OBJECT_MAP:
fprintf(out, "{");
@@ -151,7 +161,6 @@ void msgpack_object_print(FILE* out, msgpack_object o)
}
fprintf(out, "}");
break;
// FIXME loop optimiziation
default:
// FIXME
@@ -159,3 +168,70 @@ void msgpack_object_print(FILE* out, msgpack_object o)
}
}
bool msgpack_object_equal(const msgpack_object x, const msgpack_object y)
{
if(x.type != y.type) { return false; }
switch(x.type) {
case MSGPACK_OBJECT_NIL:
return true;
case MSGPACK_OBJECT_BOOLEAN:
return x.via.boolean == y.via.boolean;
case MSGPACK_OBJECT_POSITIVE_INTEGER:
return x.via.u64 == y.via.u64;
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
return x.via.i64 == y.via.i64;
case MSGPACK_OBJECT_DOUBLE:
return x.via.dec == y.via.dec;
case MSGPACK_OBJECT_RAW:
return x.via.raw.size == y.via.raw.size &&
memcmp(x.via.raw.ptr, y.via.raw.ptr, x.via.raw.size) == 0;
case MSGPACK_OBJECT_ARRAY:
if(x.via.array.size != y.via.array.size) {
return false;
} else if(x.via.array.size == 0) {
return true;
} else {
msgpack_object* px = x.via.array.ptr;
msgpack_object* const pxend = x.via.array.ptr + x.via.array.size;
msgpack_object* py = y.via.array.ptr;
do {
if(!msgpack_object_equal(*px, *py)) {
return false;
}
++px;
++py;
} while(px < pxend);
return true;
}
case MSGPACK_OBJECT_MAP:
if(x.via.map.size != y.via.map.size) {
return false;
} else if(x.via.map.size == 0) {
return true;
} else {
msgpack_object_kv* px = x.via.map.ptr;
msgpack_object_kv* const pxend = x.via.map.ptr + x.via.map.size;
msgpack_object_kv* py = y.via.map.ptr;
do {
if(!msgpack_object_equal(px->key, py->key) || !msgpack_object_equal(px->val, py->val)) {
return false;
}
++px;
++py;
} while(px < pxend);
return true;
}
default:
return false;
}
}

View File

@@ -52,7 +52,7 @@ static int template_execute(template_context* ctx,
static inline msgpack_object template_callback_root(unpack_user* u)
{ msgpack_object o; return o; }
{ msgpack_object o = {}; return o; }
static inline int template_callback_uint8(unpack_user* u, uint8_t d, msgpack_object* o)
{ o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
@@ -101,7 +101,7 @@ static inline int template_callback_array(unpack_user* u, unsigned int n, msgpac
{
o->type = MSGPACK_OBJECT_ARRAY;
o->via.array.size = 0;
o->via.array.ptr = msgpack_zone_malloc(u->z, n*sizeof(msgpack_object));
o->via.array.ptr = (msgpack_object*)msgpack_zone_malloc(u->z, n*sizeof(msgpack_object));
if(o->via.array.ptr == NULL) { return -1; }
return 0;
}
@@ -141,31 +141,31 @@ static inline int template_callback_raw(unpack_user* u, const char* b, const cha
#define CTX_CAST(m) ((template_context*)(m))
#define CTX_REFERENCED(mpac) CTX_CAST((mpac)->ctx)->user.referenced
#define COUNTER_SIZE (sizeof(_msgpack_atomic_counter_t))
static const size_t COUNTER_SIZE = sizeof(unsigned int);
static inline void init_count(void* buffer)
{
*(volatile unsigned int*)buffer = 1;
*(volatile _msgpack_atomic_counter_t*)buffer = 1;
}
static inline void decl_count(void* buffer)
{
//if(--*(unsigned int*)buffer == 0) {
if(__sync_sub_and_fetch((unsigned int*)buffer, 1) == 0) {
// atomic if(--*(_msgpack_atomic_counter_t*)buffer == 0) { free(buffer); }
if(_msgpack_sync_decr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer) == 0) {
free(buffer);
}
}
static inline void incr_count(void* buffer)
{
//++*(unsigned int*)buffer;
__sync_add_and_fetch((unsigned int*)buffer, 1);
// atomic ++*(_msgpack_atomic_counter_t*)buffer;
_msgpack_sync_incr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer);
}
static inline unsigned int get_count(void* buffer)
static inline _msgpack_atomic_counter_t get_count(void* buffer)
{
return *(volatile unsigned int*)buffer;
return *(volatile _msgpack_atomic_counter_t*)buffer;
}
@@ -323,7 +323,7 @@ msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac)
msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac)
{
if(!msgpack_unpacker_flush_zone(mpac)) {
return false;
return NULL;
}
msgpack_zone* r = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
@@ -363,28 +363,54 @@ void msgpack_unpacker_reset(msgpack_unpacker* mpac)
mpac->parsed = 0;
}
bool msgpack_unpacker_next(msgpack_unpacker* mpac, msgpack_unpacked* result)
{
if(result->zone != NULL) {
msgpack_zone_free(result->zone);
}
int ret = msgpack_unpacker_execute(mpac);
if(ret <= 0) {
result->zone = NULL;
memset(&result->data, 0, sizeof(msgpack_object));
return false;
}
result->zone = msgpack_unpacker_release_zone(mpac);
result->data = msgpack_unpacker_data(mpac);
msgpack_unpacker_reset(mpac);
return true;
}
msgpack_unpack_return
msgpack_unpack(const char* data, size_t len, size_t* off,
msgpack_zone* z, msgpack_object* result)
msgpack_zone* result_zone, msgpack_object* result)
{
template_context ctx;
template_init(&ctx);
ctx.user.z = z;
ctx.user.referenced = false;
size_t noff = 0;
if(off != NULL) { noff = *off; }
int ret = template_execute(&ctx, data, len, &noff);
if(ret < 0) {
if(len <= noff) {
// FIXME
return MSGPACK_UNPACK_CONTINUE;
}
template_context ctx;
template_init(&ctx);
ctx.user.z = result_zone;
ctx.user.referenced = false;
int e = template_execute(&ctx, data, len, &noff);
if(e < 0) {
return MSGPACK_UNPACK_PARSE_ERROR;
}
if(off != NULL) { *off = noff; }
if(ret == 0) {
if(e == 0) {
return MSGPACK_UNPACK_CONTINUE;
}
@@ -397,3 +423,37 @@ msgpack_unpack(const char* data, size_t len, size_t* off,
return MSGPACK_UNPACK_SUCCESS;
}
bool msgpack_unpack_next(msgpack_unpacked* result,
const char* data, size_t len, size_t* off)
{
msgpack_unpacked_destroy(result);
size_t noff = 0;
if(off != NULL) { noff = *off; }
if(len <= noff) {
return false;
}
msgpack_zone* z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
template_context ctx;
template_init(&ctx);
ctx.user.z = z;
ctx.user.referenced = false;
int e = template_execute(&ctx, data, len, &noff);
if(e <= 0) {
msgpack_zone_free(z);
return false;
}
if(off != NULL) { *off = noff; }
result->zone = z;
result->data = template_data(&ctx);
return true;
}

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;
}

220
cpp/src/vrefbuffer.c Normal file
View File

@@ -0,0 +1,220 @@
/*
* MessagePack for C zero-copy buffer implementation
*
* 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.
*/
#include "msgpack/vrefbuffer.h"
#include <stdlib.h>
#include <string.h>
struct msgpack_vrefbuffer_chunk {
struct msgpack_vrefbuffer_chunk* next;
/* data ... */
};
bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
size_t ref_size, size_t chunk_size)
{
vbuf->chunk_size = chunk_size;
vbuf->ref_size = ref_size;
size_t nfirst = (sizeof(struct iovec) < 72/2) ?
72 / sizeof(struct iovec) : 8;
struct iovec* array = (struct iovec*)malloc(
sizeof(struct iovec) * nfirst);
if(array == NULL) {
return false;
}
vbuf->tail = array;
vbuf->end = array + nfirst;
vbuf->array = array;
msgpack_vrefbuffer_chunk* chunk = (msgpack_vrefbuffer_chunk*)malloc(
sizeof(msgpack_vrefbuffer_chunk) + chunk_size);
if(chunk == NULL) {
free(array);
return false;
}
msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
ib->free = chunk_size;
ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
ib->head = chunk;
chunk->next = NULL;
return true;
}
void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf)
{
msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head;
while(true) {
msgpack_vrefbuffer_chunk* n = c->next;
free(c);
if(n != NULL) {
c = n;
} else {
break;
}
}
free(vbuf->array);
}
void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vbuf)
{
msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head->next;
msgpack_vrefbuffer_chunk* n;
while(c != NULL) {
n = c->next;
free(c);
c = n;
}
msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
msgpack_vrefbuffer_chunk* chunk = ib->head;
chunk->next = NULL;
ib->free = vbuf->chunk_size;
ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
vbuf->tail = vbuf->array;
}
int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
const char* buf, unsigned int len)
{
if(vbuf->tail == vbuf->end) {
const size_t nused = vbuf->tail - vbuf->array;
const size_t nnext = nused * 2;
struct iovec* nvec = (struct iovec*)realloc(
vbuf->array, sizeof(struct iovec)*nnext);
if(nvec == NULL) {
return -1;
}
vbuf->array = nvec;
vbuf->end = nvec + nnext;
vbuf->tail = nvec + nused;
}
vbuf->tail->iov_base = (char*)buf;
vbuf->tail->iov_len = len;
++vbuf->tail;
return 0;
}
int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
const char* buf, unsigned int len)
{
msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
if(ib->free < len) {
size_t sz = vbuf->chunk_size;
if(sz < len) {
sz = len;
}
msgpack_vrefbuffer_chunk* chunk = (msgpack_vrefbuffer_chunk*)malloc(
sizeof(msgpack_vrefbuffer_chunk) + sz);
if(chunk == NULL) {
return -1;
}
chunk->next = ib->head;
ib->head = chunk;
ib->free = sz;
ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
}
char* m = ib->ptr;
memcpy(m, buf, len);
ib->free -= len;
ib->ptr += len;
if(vbuf->tail != vbuf->array && m ==
(const char*)((vbuf->tail-1)->iov_base) + (vbuf->tail-1)->iov_len) {
(vbuf->tail-1)->iov_len += len;
return 0;
} else {
return msgpack_vrefbuffer_append_ref(vbuf, m, len);
}
}
int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to)
{
size_t sz = vbuf->chunk_size;
msgpack_vrefbuffer_chunk* empty = (msgpack_vrefbuffer_chunk*)malloc(
sizeof(msgpack_vrefbuffer_chunk) + sz);
if(empty == NULL) {
return -1;
}
empty->next = NULL;
const size_t nused = vbuf->tail - vbuf->array;
if(to->tail + nused < vbuf->end) {
const size_t tosize = to->tail - to->array;
const size_t reqsize = nused + tosize;
size_t nnext = (to->end - to->array) * 2;
while(nnext < reqsize) {
nnext *= 2;
}
struct iovec* nvec = (struct iovec*)realloc(
to->array, sizeof(struct iovec)*nnext);
if(nvec == NULL) {
free(empty);
return -1;
}
to->array = nvec;
to->end = nvec + nnext;
to->tail = nvec + tosize;
}
memcpy(to->tail, vbuf->array, sizeof(struct iovec)*nused);
to->tail += nused;
vbuf->tail = vbuf->array;
msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
msgpack_vrefbuffer_inner_buffer* const toib = &to->inner_buffer;
msgpack_vrefbuffer_chunk* last = ib->head;
while(last->next != NULL) {
last = last->next;
}
last->next = toib->head;
toib->head = ib->head;
if(toib->free < ib->free) {
toib->free = ib->free;
toib->ptr = ib->ptr;
}
ib->head = empty;
ib->free = sz;
ib->ptr = ((char*)empty) + sizeof(msgpack_vrefbuffer_chunk);
return 0;
}

View File

@@ -19,83 +19,61 @@
#include <stdlib.h>
#include <string.h>
static inline bool init_chunk_array(msgpack_zone_chunk_array* ca, size_t chunk_size)
{
// glibcは72バイト以下のmallocが高速
const size_t nfirst = (sizeof(msgpack_zone_chunk) < 72/2) ?
72 / sizeof(msgpack_zone_chunk) : 8;
struct msgpack_zone_chunk {
struct msgpack_zone_chunk* next;
/* data ... */
};
msgpack_zone_chunk* array = (msgpack_zone_chunk*)malloc(
sizeof(msgpack_zone_chunk) * nfirst);
if(array == NULL) {
static inline bool init_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size)
{
msgpack_zone_chunk* chunk = (msgpack_zone_chunk*)malloc(
sizeof(msgpack_zone_chunk) + chunk_size);
if(chunk == NULL) {
return false;
}
const size_t sz = chunk_size;
char* ptr = (char*)malloc(sz);
if(ptr == NULL) {
free(array);
return NULL;
}
ca->tail = array;
ca->end = array + nfirst;
ca->array = array;
array[0].free = sz;
array[0].ptr = ptr;
array[0].alloc = ptr;
cl->head = chunk;
cl->free = chunk_size;
cl->ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk);
chunk->next = NULL;
return true;
}
static inline void destroy_chunk_array(msgpack_zone_chunk_array* ca)
static inline void destroy_chunk_list(msgpack_zone_chunk_list* cl)
{
msgpack_zone_chunk* chunk = ca->array;
for(; chunk != ca->tail+1; ++chunk) {
free(chunk->alloc);
msgpack_zone_chunk* c = cl->head;
while(true) {
msgpack_zone_chunk* n = c->next;
free(c);
if(n != NULL) {
c = n;
} else {
break;
}
}
free(ca->array);
}
static inline void clear_chunk_array(msgpack_zone_chunk_array* ca)
static inline void clear_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size)
{
msgpack_zone_chunk* chunk = ca->array + 1;
for(; chunk != ca->tail+1; ++chunk) {
free(chunk->alloc);
msgpack_zone_chunk* c = cl->head;
while(true) {
msgpack_zone_chunk* n = c->next;
if(n != NULL) {
free(c);
c = n;
} else {
break;
}
}
ca->tail = ca->array;
ca->array[0].free += ca->array[0].ptr - (char*)ca->array[0].alloc;
ca->array[0].ptr = (char*)ca->array[0].alloc;
cl->head->next = NULL;
cl->free = chunk_size;
cl->ptr = ((char*)cl->head) + sizeof(msgpack_zone_chunk);
}
void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size)
{
msgpack_zone_chunk_array* const ca = &zone->chunk_array;
msgpack_zone_chunk* chunk = ++ca->tail;
if(chunk == ca->end) {
// ca->arrayに空きがない
// ca->arrayを拡張する
const size_t nused = ca->end - ca->array;
const size_t nnext = (ca->end - ca->array) * 2;
chunk = (msgpack_zone_chunk*)realloc(ca->array,
sizeof(msgpack_zone_chunk) * nnext);
if(chunk == NULL) {
return NULL;
}
ca->array = chunk;
ca->end = chunk + nnext;
chunk = ca->tail = chunk + nused;
}
msgpack_zone_chunk_list* const cl = &zone->chunk_list;
size_t sz = zone->chunk_size;
@@ -103,14 +81,15 @@ void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size)
sz *= 2;
}
char* ptr = (char*)malloc(sz);
if(ptr == NULL) {
return NULL;
}
msgpack_zone_chunk* chunk = (msgpack_zone_chunk*)malloc(
sizeof(msgpack_zone_chunk) + sz);
chunk->free = sz - size;
chunk->ptr = ptr + size;
chunk->alloc = ptr;
char* ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk);
chunk->next = cl->head;
cl->head = chunk;
cl->free = sz - size;
cl->ptr = ptr + size;
return ptr;
}
@@ -125,7 +104,6 @@ static inline void init_finalizer_array(msgpack_zone_finalizer_array* fa)
static inline void call_finalizer_array(msgpack_zone_finalizer_array* fa)
{
// 逆順に呼び出し
msgpack_zone_finalizer* fin = fa->tail;
for(; fin != fa->array; --fin) {
(*(fin-1)->func)((fin-1)->data);
@@ -153,9 +131,6 @@ bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone,
size_t nnext;
if(nused == 0) {
// 初回の呼び出しfa->tail == fa->end == fa->array == NULL
// glibcは72バイト以下のmallocが高速
nnext = (sizeof(msgpack_zone_finalizer) < 72/2) ?
72 / sizeof(msgpack_zone_finalizer) : 8;
@@ -185,19 +160,30 @@ bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone,
bool msgpack_zone_is_empty(msgpack_zone* zone)
{
msgpack_zone_chunk_array* const ca = &zone->chunk_array;
msgpack_zone_chunk_list* const cl = &zone->chunk_list;
msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
return ca->array[0].ptr == ca->array[0].alloc &&
ca->tail == ca->array &&
return cl->free == zone->chunk_size && cl->head->next == NULL &&
fa->tail == fa->array;
}
void msgpack_zone_destroy(msgpack_zone* zone)
{
destroy_finalizer_array(&zone->finalizer_array);
destroy_chunk_list(&zone->chunk_list);
}
void msgpack_zone_clear(msgpack_zone* zone)
{
clear_finalizer_array(&zone->finalizer_array);
clear_chunk_list(&zone->chunk_list, zone->chunk_size);
}
bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size)
{
zone->chunk_size = chunk_size;
if(!init_chunk_array(&zone->chunk_array, chunk_size)) {
if(!init_chunk_list(&zone->chunk_list, chunk_size)) {
return false;
}
@@ -206,35 +192,29 @@ bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size)
return true;
}
void msgpack_zone_destroy(msgpack_zone* zone)
{
destroy_finalizer_array(&zone->finalizer_array);
destroy_chunk_array(&zone->chunk_array);
}
void msgpack_zone_clear(msgpack_zone* zone)
{
clear_finalizer_array(&zone->finalizer_array);
clear_chunk_array(&zone->chunk_array);
}
msgpack_zone* msgpack_zone_new(size_t chunk_size)
{
msgpack_zone* zone = (msgpack_zone*)malloc(sizeof(msgpack_zone));
msgpack_zone* zone = (msgpack_zone*)malloc(
sizeof(msgpack_zone) + chunk_size);
if(zone == NULL) {
return NULL;
}
if(!msgpack_zone_init(zone, chunk_size)) {
zone->chunk_size = chunk_size;
if(!init_chunk_list(&zone->chunk_list, chunk_size)) {
free(zone);
return NULL;
}
init_finalizer_array(&zone->finalizer_array);
return zone;
}
void msgpack_zone_free(msgpack_zone* zone)
{
if(zone == NULL) { return; }
msgpack_zone_destroy(zone);
free(zone);
}

View File

@@ -1,201 +0,0 @@
#include <iostream>
#include <string>
#include <msgpack.hpp>
#include <sstream>
#include <memory>
using namespace msgpack;
class checker {
public:
template <typename T>
void check(const char* d, size_t len, T should) {
try {
std::cout << "----" << std::endl;
object o;
try {
o = unpack(d, len, m_zone);
} catch (std::runtime_error& e) {
std::cout << o << std::endl;
std::cout << "**" << e.what() << "**" << std::endl;
return;
}
std::cout << o << std::endl;
try {
std::stringstream s;
pack(s, should);
std::string str(s.str());
object ro = unpack(str.data(), str.size(), m_zone);
std::cout << ro << std::endl;
if(ro != o) { throw std::runtime_error("NOT MATCH"); }
} catch (std::runtime_error& e) {
std::cout << "** REUNPACK FAILED **" << std::endl;
std::cout << e.what() << std::endl;
} catch (...) {
std::cout << "** REUNPACK FAILED **" << std::endl;
std::cout << "unknown error" << std::endl;
}
} catch (...) { m_zone.clear(); throw; }
m_zone.clear();
}
private:
zone m_zone;
};
int main(void)
{
checker c;
#if 0
{ // SimpleValue
const char d[] = {
0x93, 0xc0, 0xc2, 0xc3,
};
c.check(d, sizeof(d),
type::make_tuple(
type::nil(), false, true
)
);
}
{ // Fixnum
const char d[] = {
0x92,
0x93, 0x00, 0x40, 0x7f,
0x93, 0xe0, 0xf0, 0xff,
};
c.check(d, sizeof(d),
type::make_tuple(
type::make_tuple(
0, 64, 127
),
type::make_tuple(
-32, -16, -1
)
)
);
}
{ // FixArray
const char d[] = {
0x92,
0x90,
0x91,
0x91, 0xc0,
};
std::vector<int> empty;
c.check(d, sizeof(d),
type::make_tuple(
empty,
type::make_tuple(
type::make_tuple(
type::nil()
)
)
)
);
}
{ // FixRaw
const char d[] = {
0x94,
0xa0,
0xa1, 'a',
0xa2, 'b', 'c',
0xa3, 'd', 'e', 'f',
};
c.check(d, sizeof(d),
type::make_tuple(
std::string(""),
std::string("a"),
std::string("bc"),
type::raw_ref("def", 3)
)
);
}
#endif
static const unsigned TASK_ARRAY = 1000;
static const unsigned TASK_REPEAT = 10;
std::vector<std::string> task;
// create task
{
static char traw[64];
memset(traw, 'a', sizeof(traw));
task.resize(TASK_ARRAY);
for(unsigned i=0; i < TASK_ARRAY; ++i) {
task[i] = std::string(traw, sizeof(traw));
}
}
std::stringstream stream;
// send message
{
for(unsigned i=0; i < TASK_REPEAT; ++i) {
pack(stream, task);
}
std::cout << "send " << stream.str().size() << " bytes" << std::endl;
}
ssize_t total_bytes = stream.str().size();
stream.seekg(0);
// reserive message
{
unsigned num_msg = 0;
static const size_t RESERVE_SIZE = 32;//*1024;
unpacker pac;
while(stream.good() && total_bytes > 0) {
// 1. reserve buffer
pac.reserve_buffer(RESERVE_SIZE);
// 2. read data to buffer() up to buffer_capacity() bytes
size_t sz = stream.readsome(
pac.buffer(),
pac.buffer_capacity());
total_bytes -= sz;
std::cout << "read " << sz << " bytes to capacity "
<< pac.buffer_capacity() << " bytes"
<< std::endl;
// 3. specify the number of bytes actually copied
pac.buffer_consumed(sz);
// 4. repeat execute() until it returns false
while( pac.execute() ) {
// 5.1. take out the parsed object
object o = pac.data();
// 5.2 release the zone
std::auto_ptr<zone> olife( pac.release_zone() );
// 5.3 re-initialize the unpacker */
pac.reset();
// do some with the o and olife
std::cout << "message parsed: " << o << std::endl;
++num_msg;
}
}
std::cout << "stream finished" << std::endl;
std::cout << num_msg << " messages reached" << std::endl;
}
return 0;
}

View File

@@ -1,9 +0,0 @@
CXXFLAGS += -Wall -g -I. -I.. -O4
LDFLAGS +=
all: test
test: test.o unpack.o zone.o object.o pack.hpp unpack.hpp zone.hpp object.hpp
$(CXX) test.o unpack.o zone.o object.o $(CXXFLAGS) $(LDFLAGS) -o $@

48
cpp/test/Makefile.am Normal file
View File

@@ -0,0 +1,48 @@
AM_CPPFLAGS = -I../src
AM_C_CPPFLAGS = -I../src
AM_LDFLAGS = ../src/libmsgpack.la -lgtest_main
check_PROGRAMS = \
zone \
pack_unpack \
pack_unpack_c \
streaming \
streaming_c \
object \
convert \
buffer \
cases \
version \
msgpackc_test \
msgpack_test
TESTS = $(check_PROGRAMS)
zone_SOURCES = zone.cc
pack_unpack_SOURCES = pack_unpack.cc
pack_unpack_c_SOURCES = pack_unpack_c.cc
streaming_SOURCES = streaming.cc
streaming_c_SOURCES = streaming_c.cc
object_SOURCES = object.cc
convert_SOURCES = convert.cc
buffer_SOURCES = buffer.cc
buffer_LDADD = -lz
cases_SOURCES = cases.cc
version_SOURCES = version.cc
msgpackc_test_SOURCES = msgpackc_test.cpp
msgpack_test_SOURCES = msgpack_test.cpp
EXTRA_DIST = cases.mpac cases_compact.mpac

75
cpp/test/buffer.cc Normal file
View File

@@ -0,0 +1,75 @@
#include <msgpack.hpp>
#include <msgpack/zbuffer.hpp>
#include <gtest/gtest.h>
#include <string.h>
TEST(buffer, sbuffer)
{
msgpack::sbuffer sbuf;
sbuf.write("a", 1);
sbuf.write("a", 1);
sbuf.write("a", 1);
EXPECT_EQ(3, sbuf.size());
EXPECT_TRUE( memcmp(sbuf.data(), "aaa", 3) == 0 );
sbuf.clear();
sbuf.write("a", 1);
sbuf.write("a", 1);
sbuf.write("a", 1);
EXPECT_EQ(3, sbuf.size());
EXPECT_TRUE( memcmp(sbuf.data(), "aaa", 3) == 0 );
}
TEST(buffer, vrefbuffer)
{
msgpack::vrefbuffer vbuf;
vbuf.write("a", 1);
vbuf.write("a", 1);
vbuf.write("a", 1);
const struct iovec* vec = vbuf.vector();
size_t veclen = vbuf.vector_size();
msgpack::sbuffer sbuf;
for(size_t i=0; i < veclen; ++i) {
sbuf.write((const char*)vec[i].iov_base, vec[i].iov_len);
}
EXPECT_EQ(3, sbuf.size());
EXPECT_TRUE( memcmp(sbuf.data(), "aaa", 3) == 0 );
vbuf.clear();
vbuf.write("a", 1);
vbuf.write("a", 1);
vbuf.write("a", 1);
vec = vbuf.vector();
veclen = vbuf.vector_size();
sbuf.clear();
for(size_t i=0; i < veclen; ++i) {
sbuf.write((const char*)vec[i].iov_base, vec[i].iov_len);
}
EXPECT_EQ(3, sbuf.size());
EXPECT_TRUE( memcmp(sbuf.data(), "aaa", 3) == 0 );
}
TEST(buffer, zbuffer)
{
msgpack::zbuffer zbuf;
zbuf.write("a", 1);
zbuf.write("a", 1);
zbuf.write("a", 1);
zbuf.flush();
char* data = zbuf.data();
size_t size = zbuf.size();
}

36
cpp/test/cases.cc Normal file
View File

@@ -0,0 +1,36 @@
#include <msgpack.hpp>
#include <fstream>
#include <gtest/gtest.h>
static void feed_file(msgpack::unpacker& pac, const char* path)
{
std::ifstream fin(path);
while(true) {
pac.reserve_buffer(32*1024);
fin.read(pac.buffer(), pac.buffer_capacity());
if(fin.bad()) {
throw std::runtime_error("read failed");
}
pac.buffer_consumed(fin.gcount());
if(fin.fail()) {
break;
}
}
}
TEST(cases, format)
{
msgpack::unpacker pac;
msgpack::unpacker pac_compact;
feed_file(pac, "cases.mpac");
feed_file(pac_compact, "cases_compact.mpac");
msgpack::unpacked result;
while(pac.next(&result)) {
msgpack::unpacked result_compact;
EXPECT_TRUE( pac_compact.next(&result_compact) );
EXPECT_EQ(result_compact.get(), result.get());
}
}

74
cpp/test/convert.cc Normal file
View File

@@ -0,0 +1,74 @@
#include <msgpack.hpp>
#include <gtest/gtest.h>
class compatibility {
public:
compatibility() : str1("default"), str2("default") { }
std::string str1;
std::string str2;
MSGPACK_DEFINE(str1, str2);
};
TEST(convert, compatibility_less)
{
std::vector<std::string> src(1);
src[0] = "kumofs";
msgpack::zone z;
msgpack::object obj(src, &z);
compatibility c;
EXPECT_NO_THROW( obj.convert(&c) );
EXPECT_EQ("kumofs", c.str1);
EXPECT_EQ("default", c.str2);
}
TEST(convert, compatibility_more)
{
std::vector<std::string> src(3);
src[0] = "kumofs";
src[1] = "mpio";
src[2] = "cloudy";
msgpack::zone z;
msgpack::object obj(src, &z);
compatibility to;
EXPECT_NO_THROW( obj.convert(&to) );
EXPECT_EQ("kumofs", to.str1);
EXPECT_EQ("mpio", to.str2);
}
class enum_member {
public:
enum_member() : flag(A) { }
enum flags_t {
A = 0,
B = 1,
};
flags_t flag;
MSGPACK_DEFINE((int&)flag);
};
TEST(convert, enum_member)
{
enum_member src;
src.flag = enum_member::B;
msgpack::zone z;
msgpack::object obj(src, &z);
enum_member to;
EXPECT_NO_THROW( obj.convert(&to) );
EXPECT_EQ(enum_member::B, to.flag);
}

982
cpp/test/msgpack_test.cpp Normal file
View File

@@ -0,0 +1,982 @@
#include "msgpack.hpp"
#include <math.h>
#include <string>
#include <vector>
#include <map>
#include <deque>
#include <set>
#include <list>
#include <gtest/gtest.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
using namespace std;
const unsigned int kLoop = 10000;
const unsigned int kElements = 100;
const double kEPS = 1e-10;
#define GEN_TEST(test_type) \
do { \
vector<test_type> v; \
v.push_back(0); \
v.push_back(1); \
v.push_back(2); \
v.push_back(numeric_limits<test_type>::min()); \
v.push_back(numeric_limits<test_type>::max()); \
for (unsigned int i = 0; i < kLoop; i++) \
v.push_back(rand()); \
for (unsigned int i = 0; i < v.size() ; i++) { \
msgpack::sbuffer sbuf; \
test_type val1 = v[i]; \
msgpack::pack(sbuf, val1); \
msgpack::zone z; \
msgpack::object obj; \
msgpack::unpack_return ret = \
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj); \
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret); \
test_type val2; \
obj.convert(&val2); \
EXPECT_EQ(val1, val2); \
} \
} while(0)
TEST(MSGPACK, simple_buffer_short)
{
GEN_TEST(short);
}
TEST(MSGPACK, simple_buffer_int)
{
GEN_TEST(int);
}
TEST(MSGPACK, simple_buffer_long)
{
GEN_TEST(long);
}
TEST(MSGPACK, simple_buffer_long_long)
{
GEN_TEST(long long);
}
TEST(MSGPACK, simple_buffer_unsigned_short)
{
GEN_TEST(unsigned short);
}
TEST(MSGPACK, simple_buffer_unsigned_int)
{
GEN_TEST(unsigned int);
}
TEST(MSGPACK, simple_buffer_unsigned_long)
{
GEN_TEST(unsigned long);
}
TEST(MSGPACK, simple_buffer_unsigned_long_long)
{
GEN_TEST(unsigned long long);
}
TEST(MSGPACK, simple_buffer_uint8)
{
GEN_TEST(uint8_t);
}
TEST(MSGPACK, simple_buffer_uint16)
{
GEN_TEST(uint16_t);
}
TEST(MSGPACK, simple_buffer_uint32)
{
GEN_TEST(uint32_t);
}
TEST(MSGPACK, simple_buffer_uint64)
{
GEN_TEST(uint64_t);
}
TEST(MSGPACK, simple_buffer_int8)
{
GEN_TEST(int8_t);
}
TEST(MSGPACK, simple_buffer_int16)
{
GEN_TEST(int16_t);
}
TEST(MSGPACK, simple_buffer_int32)
{
GEN_TEST(int32_t);
}
TEST(MSGPACK, simple_buffer_int64)
{
GEN_TEST(int64_t);
}
TEST(MSGPACK, simple_buffer_float)
{
vector<float> v;
v.push_back(0.0);
v.push_back(-0.0);
v.push_back(1.0);
v.push_back(-1.0);
v.push_back(numeric_limits<float>::min());
v.push_back(numeric_limits<float>::max());
v.push_back(nanf("tag"));
v.push_back(1.0/0.0); // inf
v.push_back(-(1.0/0.0)); // -inf
for (unsigned int i = 0; i < kLoop; i++) {
v.push_back(drand48());
v.push_back(-drand48());
}
for (unsigned int i = 0; i < v.size() ; i++) {
msgpack::sbuffer sbuf;
float val1 = v[i];
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
float val2;
obj.convert(&val2);
if (isnan(val1))
EXPECT_TRUE(isnan(val2));
else if (isinf(val1))
EXPECT_TRUE(isinf(val2));
else
EXPECT_TRUE(fabs(val2 - val1) <= kEPS);
}
}
TEST(MSGPACK, simple_buffer_double)
{
vector<double> v;
v.push_back(0.0);
v.push_back(-0.0);
v.push_back(1.0);
v.push_back(-1.0);
v.push_back(numeric_limits<double>::min());
v.push_back(numeric_limits<double>::max());
v.push_back(nanf("tag"));
v.push_back(1.0/0.0); // inf
v.push_back(-(1.0/0.0)); // -inf
for (unsigned int i = 0; i < kLoop; i++) {
v.push_back(drand48());
v.push_back(-drand48());
}
for (unsigned int i = 0; i < v.size() ; i++) {
msgpack::sbuffer sbuf;
double val1 = v[i];
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
double val2;
obj.convert(&val2);
if (isnan(val1))
EXPECT_TRUE(isnan(val2));
else if (isinf(val1))
EXPECT_TRUE(isinf(val2));
else
EXPECT_TRUE(fabs(val2 - val1) <= kEPS);
}
}
TEST(MSGPACK, simple_buffer_true)
{
msgpack::sbuffer sbuf;
bool val1 = true;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
bool val2;
obj.convert(&val2);
EXPECT_EQ(val1, val2);
}
TEST(MSGPACK, simple_buffer_false)
{
msgpack::sbuffer sbuf;
bool val1 = false;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
bool val2;
obj.convert(&val2);
EXPECT_EQ(val1, val2);
}
//-----------------------------------------------------------------------------
// STL
TEST(MSGPACK_STL, simple_buffer_string)
{
for (unsigned int k = 0; k < kLoop; k++) {
string val1;
for (unsigned int i = 0; i < kElements; i++)
val1 += 'a' + rand() % 26;
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
string val2;
obj.convert(&val2);
EXPECT_EQ(val1.size(), val2.size());
EXPECT_EQ(val1, val2);
}
}
TEST(MSGPACK_STL, simple_buffer_vector)
{
for (unsigned int k = 0; k < kLoop; k++) {
vector<int> val1;
for (unsigned int i = 0; i < kElements; i++)
val1.push_back(rand());
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
vector<int> val2;
obj.convert(&val2);
EXPECT_EQ(val1.size(), val2.size());
EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin()));
}
}
TEST(MSGPACK_STL, simple_buffer_map)
{
for (unsigned int k = 0; k < kLoop; k++) {
map<int, int> val1;
for (unsigned int i = 0; i < kElements; i++)
val1[rand()] = rand();
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
map<int, int> val2;
obj.convert(&val2);
EXPECT_EQ(val1.size(), val2.size());
EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin()));
}
}
TEST(MSGPACK_STL, simple_buffer_deque)
{
for (unsigned int k = 0; k < kLoop; k++) {
deque<int> val1;
for (unsigned int i = 0; i < kElements; i++)
val1.push_back(rand());
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
deque<int> val2;
obj.convert(&val2);
EXPECT_EQ(val1.size(), val2.size());
EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin()));
}
}
TEST(MSGPACK_STL, simple_buffer_list)
{
for (unsigned int k = 0; k < kLoop; k++) {
list<int> val1;
for (unsigned int i = 0; i < kElements; i++)
val1.push_back(rand());
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
list<int> val2;
obj.convert(&val2);
EXPECT_EQ(val1.size(), val2.size());
EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin()));
}
}
TEST(MSGPACK_STL, simple_buffer_set)
{
for (unsigned int k = 0; k < kLoop; k++) {
set<int> val1;
for (unsigned int i = 0; i < kElements; i++)
val1.insert(rand());
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
set<int> val2;
obj.convert(&val2);
EXPECT_EQ(val1.size(), val2.size());
EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin()));
}
}
TEST(MSGPACK_STL, simple_buffer_pair)
{
for (unsigned int k = 0; k < kLoop; k++) {
pair<int, int> val1 = make_pair(rand(), rand());
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
pair<int, int> val2;
obj.convert(&val2);
EXPECT_EQ(val1.first, val2.first);
EXPECT_EQ(val1.second, val2.second);
}
}
TEST(MSGPACK_STL, simple_buffer_multimap)
{
for (unsigned int k = 0; k < kLoop; k++) {
multimap<int, int> val1;
for (unsigned int i = 0; i < kElements; i++) {
int i1 = rand();
val1.insert(make_pair(i1, rand()));
val1.insert(make_pair(i1, rand()));
}
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
multimap<int, int> val2;
obj.convert(&val2);
vector<pair<int, int> > v1, v2;
multimap<int, int>::const_iterator it;
for (it = val1.begin(); it != val1.end(); ++it)
v1.push_back(make_pair(it->first, it->second));
for (it = val2.begin(); it != val2.end(); ++it)
v2.push_back(make_pair(it->first, it->second));
EXPECT_EQ(val1.size(), val2.size());
EXPECT_EQ(v1.size(), v2.size());
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
EXPECT_TRUE(v1 == v2);
}
}
TEST(MSGPACK_STL, simple_buffer_multiset)
{
for (unsigned int k = 0; k < kLoop; k++) {
multiset<int> val1;
for (unsigned int i = 0; i < kElements; i++)
val1.insert(rand());
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
multiset<int> val2;
obj.convert(&val2);
vector<int> v1, v2;
multiset<int>::const_iterator it;
for (it = val1.begin(); it != val1.end(); ++it)
v1.push_back(*it);
for (it = val2.begin(); it != val2.end(); ++it)
v2.push_back(*it);
EXPECT_EQ(val1.size(), val2.size());
EXPECT_EQ(v1.size(), v2.size());
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
EXPECT_TRUE(v1 == v2);
}
}
// TR1
#ifdef HAVE_TR1_UNORDERED_MAP
#include <tr1/unordered_map>
#include "msgpack/type/tr1/unordered_map.hpp"
TEST(MSGPACK_TR1, simple_buffer_unordered_map)
{
for (unsigned int k = 0; k < kLoop; k++) {
tr1::unordered_map<int, int> val1;
for (unsigned int i = 0; i < kElements; i++)
val1[rand()] = rand();
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
tr1::unordered_map<int, int> val2;
obj.convert(&val2);
EXPECT_EQ(val1.size(), val2.size());
tr1::unordered_map<int, int>::const_iterator it;
for (it = val1.begin(); it != val1.end(); ++it) {
EXPECT_TRUE(val2.find(it->first) != val2.end());
EXPECT_EQ(it->second, val2.find(it->first)->second);
}
}
}
TEST(MSGPACK_TR1, simple_buffer_unordered_multimap)
{
for (unsigned int k = 0; k < kLoop; k++) {
tr1::unordered_multimap<int, int> val1;
for (unsigned int i = 0; i < kElements; i++) {
int i1 = rand();
val1.insert(make_pair(i1, rand()));
val1.insert(make_pair(i1, rand()));
}
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
tr1::unordered_multimap<int, int> val2;
obj.convert(&val2);
vector<pair<int, int> > v1, v2;
tr1::unordered_multimap<int, int>::const_iterator it;
for (it = val1.begin(); it != val1.end(); ++it)
v1.push_back(make_pair(it->first, it->second));
for (it = val2.begin(); it != val2.end(); ++it)
v2.push_back(make_pair(it->first, it->second));
EXPECT_EQ(val1.size(), val2.size());
EXPECT_EQ(v1.size(), v2.size());
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
EXPECT_TRUE(v1 == v2);
}
}
#endif
#ifdef HAVE_TR1_UNORDERED_SET
#include <tr1/unordered_set>
#include "msgpack/type/tr1/unordered_set.hpp"
TEST(MSGPACK_TR1, simple_buffer_unordered_set)
{
for (unsigned int k = 0; k < kLoop; k++) {
tr1::unordered_set<int> val1;
for (unsigned int i = 0; i < kElements; i++)
val1.insert(rand());
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
tr1::unordered_set<int> val2;
obj.convert(&val2);
EXPECT_EQ(val1.size(), val2.size());
tr1::unordered_set<int>::const_iterator it;
for (it = val1.begin(); it != val1.end(); ++it)
EXPECT_TRUE(val2.find(*it) != val2.end());
}
}
TEST(MSGPACK_TR1, simple_buffer_unordered_multiset)
{
for (unsigned int k = 0; k < kLoop; k++) {
tr1::unordered_multiset<int> val1;
for (unsigned int i = 0; i < kElements; i++)
val1.insert(rand());
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
tr1::unordered_multiset<int> val2;
obj.convert(&val2);
vector<int> v1, v2;
tr1::unordered_multiset<int>::const_iterator it;
for (it = val1.begin(); it != val1.end(); ++it)
v1.push_back(*it);
for (it = val2.begin(); it != val2.end(); ++it)
v2.push_back(*it);
EXPECT_EQ(val1.size(), val2.size());
EXPECT_EQ(v1.size(), v2.size());
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
EXPECT_TRUE(v1 == v2);
}
}
#endif
// User-Defined Structures
class TestClass
{
public:
TestClass() : i(0), s("kzk") {}
int i;
string s;
MSGPACK_DEFINE(i, s);
};
TEST(MSGPACK_USER_DEFINED, simple_buffer_class)
{
for (unsigned int k = 0; k < kLoop; k++) {
TestClass val1;
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
TestClass val2;
val2.i = -1;
val2.s = "";
obj.convert(&val2);
EXPECT_EQ(val1.i, val2.i);
EXPECT_EQ(val1.s, val2.s);
}
}
class TestClass2
{
public:
TestClass2() : i(0), s("kzk") {
for (unsigned int i = 0; i < kElements; i++)
v.push_back(rand());
}
int i;
string s;
vector<int> v;
MSGPACK_DEFINE(i, s, v);
};
TEST(MSGPACK_USER_DEFINED, simple_buffer_class_old_to_new)
{
for (unsigned int k = 0; k < kLoop; k++) {
TestClass val1;
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
TestClass2 val2;
val2.i = -1;
val2.s = "";
val2.v = vector<int>();
obj.convert(&val2);
EXPECT_EQ(val1.i, val2.i);
EXPECT_EQ(val1.s, val2.s);
EXPECT_FALSE(val2.s.empty());
}
}
TEST(MSGPACK_USER_DEFINED, simple_buffer_class_new_to_old)
{
for (unsigned int k = 0; k < kLoop; k++) {
TestClass2 val1;
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
TestClass val2;
val2.i = -1;
val2.s = "";
obj.convert(&val2);
EXPECT_EQ(val1.i, val2.i);
EXPECT_EQ(val1.s, val2.s);
EXPECT_FALSE(val2.s.empty());
}
}
class TestEnumMemberClass
{
public:
TestEnumMemberClass()
: t1(STATE_A), t2(STATE_B), t3(STATE_C) {}
enum TestEnumType {
STATE_INVALID = 0,
STATE_A = 1,
STATE_B = 2,
STATE_C = 3
};
TestEnumType t1;
TestEnumType t2;
TestEnumType t3;
MSGPACK_DEFINE((int&)t1, (int&)t2, (int&)t3);
};
TEST(MSGPACK_USER_DEFINED, simple_buffer_enum_member)
{
TestEnumMemberClass val1;
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
TestEnumMemberClass val2;
val2.t1 = TestEnumMemberClass::STATE_INVALID;
val2.t2 = TestEnumMemberClass::STATE_INVALID;
val2.t3 = TestEnumMemberClass::STATE_INVALID;
obj.convert(&val2);
EXPECT_EQ(val1.t1, val2.t1);
EXPECT_EQ(val1.t2, val2.t2);
EXPECT_EQ(val1.t3, val2.t3);
}
class TestUnionMemberClass
{
public:
TestUnionMemberClass() {}
TestUnionMemberClass(double f) {
is_double = true;
value.f = f;
}
TestUnionMemberClass(int i) {
is_double = false;
value.i = i;
}
union {
double f;
int i;
} value;
bool is_double;
template <typename Packer>
void msgpack_pack(Packer& pk) const
{
if (is_double)
pk.pack(msgpack::type::tuple<bool, double>(true, value.f));
else
pk.pack(msgpack::type::tuple<bool, int>(false, value.i));
}
void msgpack_unpack(msgpack::object o)
{
msgpack::type::tuple<bool, msgpack::object> tuple;
o.convert(&tuple);
is_double = tuple.get<0>();
if (is_double)
tuple.get<1>().convert(&value.f);
else
tuple.get<1>().convert(&value.i);
}
};
TEST(MSGPACK_USER_DEFINED, simple_buffer_union_member)
{
{
// double
TestUnionMemberClass val1(1.0);
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
TestUnionMemberClass val2;
obj.convert(&val2);
EXPECT_EQ(val1.is_double, val2.is_double);
EXPECT_TRUE(fabs(val1.value.f - val2.value.f) < kEPS);
}
{
// int
TestUnionMemberClass val1(1);
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, val1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret);
TestUnionMemberClass val2;
obj.convert(&val2);
EXPECT_EQ(val1.is_double, val2.is_double);
EXPECT_EQ(val1.value.i, 1);
EXPECT_EQ(val1.value.i, val2.value.i);
}
}
//-----------------------------------------------------------------------------
#define GEN_TEST_VREF(test_type) \
do { \
vector<test_type> v; \
v.push_back(0); \
for (unsigned int i = 0; i < v.size(); i++) { \
test_type val1 = v[i]; \
msgpack::vrefbuffer vbuf; \
msgpack::pack(vbuf, val1); \
msgpack::sbuffer sbuf; \
const struct iovec* cur = vbuf.vector(); \
const struct iovec* end = cur + vbuf.vector_size(); \
for(; cur != end; ++cur) \
sbuf.write((const char*)cur->iov_base, cur->iov_len); \
msgpack::zone z; \
msgpack::object obj; \
msgpack::unpack_return ret = \
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj); \
EXPECT_EQ(msgpack::UNPACK_SUCCESS, ret); \
test_type val2; \
obj.convert(&val2); \
EXPECT_EQ(val1, val2); \
} \
} while(0);
TEST(MSGPACK, vrefbuffer_short)
{
GEN_TEST_VREF(short);
}
TEST(MSGPACK, vrefbuffer_int)
{
GEN_TEST_VREF(int);
}
TEST(MSGPACK, vrefbuffer_long)
{
GEN_TEST_VREF(long);
}
TEST(MSGPACK, vrefbuffer_long_long)
{
GEN_TEST_VREF(long long);
}
TEST(MSGPACK, vrefbuffer_unsigned_short)
{
GEN_TEST_VREF(unsigned short);
}
TEST(MSGPACK, vrefbuffer_unsigned_int)
{
GEN_TEST_VREF(unsigned int);
}
TEST(MSGPACK, vrefbuffer_unsigned_long)
{
GEN_TEST_VREF(unsigned long);
}
TEST(MSGPACK, vrefbuffer_unsigned_long_long)
{
GEN_TEST_VREF(unsigned long long);
}
TEST(MSGPACK, vrefbuffer_uint8)
{
GEN_TEST_VREF(uint8_t);
}
TEST(MSGPACK, vrefbuffer_uint16)
{
GEN_TEST_VREF(uint16_t);
}
TEST(MSGPACK, vrefbuffer_uint32)
{
GEN_TEST_VREF(uint32_t);
}
TEST(MSGPACK, vrefbuffer_uint64)
{
GEN_TEST_VREF(uint64_t);
}
TEST(MSGPACK, vrefbuffer_int8)
{
GEN_TEST_VREF(int8_t);
}
TEST(MSGPACK, vrefbuffer_int16)
{
GEN_TEST_VREF(int16_t);
}
TEST(MSGPACK, vrefbuffer_int32)
{
GEN_TEST_VREF(int32_t);
}
TEST(MSGPACK, vrefbuffer_int64)
{
GEN_TEST_VREF(int64_t);
}
//-----------------------------------------------------------------------------
#define GEN_TEST_STREAM(test_type) \
for (unsigned int k = 0; k < kLoop; k++) { \
msgpack::sbuffer sbuf; \
msgpack::packer<msgpack::sbuffer> pk(sbuf); \
typedef std::vector<test_type> vec_type; \
vec_type vec; \
for(unsigned int i = 0; i < rand() % kLoop; ++i) { \
vec_type::value_type r = rand(); \
vec.push_back(r); \
pk.pack(r); \
} \
msgpack::unpacker pac; \
vec_type::const_iterator it = vec.begin(); \
const char *p = sbuf.data(); \
const char * const pend = p + sbuf.size(); \
while (p < pend) { \
const size_t sz = std::min<size_t>(pend - p, rand() % 128); \
pac.reserve_buffer(sz); \
memcpy(pac.buffer(), p, sz); \
pac.buffer_consumed(sz); \
while (pac.execute()) { \
if (it == vec.end()) goto out; \
msgpack::object obj = pac.data(); \
msgpack::zone *life = pac.release_zone(); \
EXPECT_TRUE(life != NULL); \
pac.reset(); \
vec_type::value_type val; \
obj.convert(&val); \
EXPECT_EQ(*it, val); \
++it; \
delete life; \
} \
p += sz; \
} \
out: \
; \
}
TEST(MSGPACK, stream_short)
{
GEN_TEST_STREAM(short);
}
TEST(MSGPACK, stream_int)
{
GEN_TEST_STREAM(int);
}
TEST(MSGPACK, stream_long)
{
GEN_TEST_STREAM(long);
}
TEST(MSGPACK, stream_long_long)
{
GEN_TEST_STREAM(long long);
}
TEST(MSGPACK, stream_unsigned_short)
{
GEN_TEST_STREAM(unsigned short);
}
TEST(MSGPACK, stream_unsigned_int)
{
GEN_TEST_STREAM(unsigned int);
}
TEST(MSGPACK, stream_unsigned_long)
{
GEN_TEST_STREAM(unsigned long);
}
TEST(MSGPACK, stream_unsigned_long_long)
{
GEN_TEST_STREAM(unsigned long long);
}
TEST(MSGPACK, stream_uint8)
{
GEN_TEST_STREAM(uint8_t);
}
TEST(MSGPACK, stream_uint16)
{
GEN_TEST_STREAM(uint16_t);
}
TEST(MSGPACK, stream_uint32)
{
GEN_TEST_STREAM(uint32_t);
}
TEST(MSGPACK, stream_uint64)
{
GEN_TEST_STREAM(uint64_t);
}
TEST(MSGPACK, stream_int8)
{
GEN_TEST_STREAM(int8_t);
}
TEST(MSGPACK, stream_int16)
{
GEN_TEST_STREAM(int16_t);
}
TEST(MSGPACK, stream_int32)
{
GEN_TEST_STREAM(int32_t);
}
TEST(MSGPACK, stream_int64)
{
GEN_TEST_STREAM(int64_t);
}

424
cpp/test/msgpackc_test.cpp Normal file
View File

@@ -0,0 +1,424 @@
#include "msgpack.h"
#include <math.h>
#include <vector>
#include <limits>
#include <gtest/gtest.h>
using namespace std;
const unsigned int kLoop = 10000;
const double kEPS = 1e-10;
#define GEN_TEST_SIGNED(test_type, func_type) \
do { \
vector<test_type> v; \
v.push_back(0); \
v.push_back(1); \
v.push_back(-1); \
v.push_back(numeric_limits<test_type>::min()); \
v.push_back(numeric_limits<test_type>::max()); \
for (unsigned int i = 0; i < kLoop; i++) \
v.push_back(rand()); \
for (unsigned int i = 0; i < v.size() ; i++) { \
test_type val = v[i]; \
msgpack_sbuffer sbuf; \
msgpack_sbuffer_init(&sbuf); \
msgpack_packer pk; \
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); \
msgpack_pack_##func_type(&pk, val); \
msgpack_zone z; \
msgpack_zone_init(&z, 2048); \
msgpack_object obj; \
msgpack_unpack_return ret = \
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); \
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); \
if (val < 0) { \
EXPECT_EQ(MSGPACK_OBJECT_NEGATIVE_INTEGER, obj.type); \
EXPECT_EQ(val, obj.via.i64); \
} else { \
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, obj.type); \
EXPECT_EQ(val, obj.via.u64); \
} \
msgpack_zone_destroy(&z); \
msgpack_sbuffer_destroy(&sbuf); \
} \
} while(0)
#define GEN_TEST_UNSIGNED(test_type, func_type) \
do { \
vector<test_type> v; \
v.push_back(0); \
v.push_back(1); \
v.push_back(2); \
v.push_back(numeric_limits<test_type>::min()); \
v.push_back(numeric_limits<test_type>::max()); \
for (unsigned int i = 0; i < kLoop; i++) \
v.push_back(rand()); \
for (unsigned int i = 0; i < v.size() ; i++) { \
test_type val = v[i]; \
msgpack_sbuffer sbuf; \
msgpack_sbuffer_init(&sbuf); \
msgpack_packer pk; \
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); \
msgpack_pack_##func_type(&pk, val); \
msgpack_zone z; \
msgpack_zone_init(&z, 2048); \
msgpack_object obj; \
msgpack_unpack_return ret = \
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj); \
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret); \
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, obj.type); \
EXPECT_EQ(val, obj.via.u64); \
msgpack_zone_destroy(&z); \
msgpack_sbuffer_destroy(&sbuf); \
} \
} while(0)
TEST(MSGPACKC, simple_buffer_short)
{
GEN_TEST_SIGNED(short, short);
}
TEST(MSGPACKC, simple_buffer_int)
{
GEN_TEST_SIGNED(int, int);
}
TEST(MSGPACKC, simple_buffer_long)
{
GEN_TEST_SIGNED(long, long);
}
TEST(MSGPACKC, simple_buffer_long_long)
{
GEN_TEST_SIGNED(long long, long_long);
}
TEST(MSGPACKC, simple_buffer_unsigned_short)
{
GEN_TEST_UNSIGNED(unsigned short, unsigned_short);
}
TEST(MSGPACKC, simple_buffer_unsigned_int)
{
GEN_TEST_UNSIGNED(unsigned int, unsigned_int);
}
TEST(MSGPACKC, simple_buffer_unsigned_long)
{
GEN_TEST_UNSIGNED(unsigned long, unsigned_long);
}
TEST(MSGPACKC, simple_buffer_unsigned_long_long)
{
GEN_TEST_UNSIGNED(unsigned long long, unsigned_long_long);
}
TEST(MSGPACKC, simple_buffer_uint8)
{
GEN_TEST_UNSIGNED(uint8_t, uint8);
}
TEST(MSGPACKC, simple_buffer_uint16)
{
GEN_TEST_UNSIGNED(uint16_t, uint16);
}
TEST(MSGPACKC, simple_buffer_uint32)
{
GEN_TEST_UNSIGNED(uint32_t, uint32);
}
TEST(MSGPACKC, simple_buffer_uint64)
{
GEN_TEST_UNSIGNED(uint64_t, uint64);
}
TEST(MSGPACKC, simple_buffer_int8)
{
GEN_TEST_SIGNED(int8_t, int8);
}
TEST(MSGPACKC, simple_buffer_int16)
{
GEN_TEST_SIGNED(int16_t, int16);
}
TEST(MSGPACKC, simple_buffer_int32)
{
GEN_TEST_SIGNED(int32_t, int32);
}
TEST(MSGPACKC, simple_buffer_int64)
{
GEN_TEST_SIGNED(int64_t, int64);
}
TEST(MSGPACKC, simple_buffer_float)
{
vector<float> v;
v.push_back(0.0);
v.push_back(1.0);
v.push_back(-1.0);
v.push_back(numeric_limits<float>::min());
v.push_back(numeric_limits<float>::max());
v.push_back(nanf("tag"));
v.push_back(1.0/0.0); // inf
v.push_back(-(1.0/0.0)); // -inf
for (unsigned int i = 0; i < kLoop; i++) {
v.push_back(drand48());
v.push_back(-drand48());
}
for (unsigned int i = 0; i < v.size() ; i++) {
float val = v[i];
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
msgpack_packer pk;
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
msgpack_pack_float(&pk, val);
msgpack_zone z;
msgpack_zone_init(&z, 2048);
msgpack_object obj;
msgpack_unpack_return ret =
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
EXPECT_EQ(MSGPACK_OBJECT_DOUBLE, obj.type);
if (isnan(val))
EXPECT_TRUE(isnan(obj.via.dec));
else if (isinf(val))
EXPECT_TRUE(isinf(obj.via.dec));
else
EXPECT_TRUE(fabs(obj.via.dec - val) <= kEPS);
msgpack_zone_destroy(&z);
msgpack_sbuffer_destroy(&sbuf);
}
}
TEST(MSGPACKC, simple_buffer_double)
{
vector<double> v;
v.push_back(0.0);
v.push_back(-0.0);
v.push_back(1.0);
v.push_back(-1.0);
v.push_back(numeric_limits<double>::min());
v.push_back(numeric_limits<double>::max());
v.push_back(nan("tag"));
v.push_back(1.0/0.0); // inf
v.push_back(-(1.0/0.0)); // -inf
for (unsigned int i = 0; i < kLoop; i++) {
v.push_back(drand48());
v.push_back(-drand48());
}
for (unsigned int i = 0; i < v.size() ; i++) {
double val = v[i];
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
msgpack_packer pk;
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
msgpack_pack_double(&pk, val);
msgpack_zone z;
msgpack_zone_init(&z, 2048);
msgpack_object obj;
msgpack_unpack_return ret =
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
EXPECT_EQ(MSGPACK_OBJECT_DOUBLE, obj.type);
if (isnan(val))
EXPECT_TRUE(isnan(obj.via.dec));
else if (isinf(val))
EXPECT_TRUE(isinf(obj.via.dec));
else
EXPECT_TRUE(fabs(obj.via.dec - val) <= kEPS);
msgpack_zone_destroy(&z);
msgpack_sbuffer_destroy(&sbuf);
}
}
TEST(MSGPACKC, simple_buffer_nil)
{
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
msgpack_packer pk;
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
msgpack_pack_nil(&pk);
msgpack_zone z;
msgpack_zone_init(&z, 2048);
msgpack_object obj;
msgpack_unpack_return ret =
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
EXPECT_EQ(MSGPACK_OBJECT_NIL, obj.type);
msgpack_zone_destroy(&z);
msgpack_sbuffer_destroy(&sbuf);
}
TEST(MSGPACKC, simple_buffer_true)
{
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
msgpack_packer pk;
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
msgpack_pack_true(&pk);
msgpack_zone z;
msgpack_zone_init(&z, 2048);
msgpack_object obj;
msgpack_unpack_return ret =
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
EXPECT_EQ(MSGPACK_OBJECT_BOOLEAN, obj.type);
EXPECT_EQ(true, obj.via.boolean);
msgpack_zone_destroy(&z);
msgpack_sbuffer_destroy(&sbuf);
}
TEST(MSGPACKC, simple_buffer_false)
{
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
msgpack_packer pk;
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
msgpack_pack_false(&pk);
msgpack_zone z;
msgpack_zone_init(&z, 2048);
msgpack_object obj;
msgpack_unpack_return ret =
msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
EXPECT_EQ(MSGPACK_OBJECT_BOOLEAN, obj.type);
EXPECT_EQ(false, obj.via.boolean);
msgpack_zone_destroy(&z);
msgpack_sbuffer_destroy(&sbuf);
}
TEST(MSGPACKC, simple_buffer_array)
{
unsigned int array_size = 5;
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
msgpack_packer pk;
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
msgpack_pack_array(&pk, array_size);
msgpack_pack_nil(&pk);
msgpack_pack_true(&pk);
msgpack_pack_false(&pk);
msgpack_pack_int(&pk, 10);
msgpack_pack_int(&pk, -10);
msgpack_zone z;
msgpack_zone_init(&z, 2048);
msgpack_object obj;
msgpack_unpack_return ret;
ret = msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
EXPECT_EQ(MSGPACK_OBJECT_ARRAY, obj.type);
EXPECT_EQ(array_size, obj.via.array.size);
for (unsigned int i = 0; i < obj.via.array.size; i++) {
msgpack_object o = obj.via.array.ptr[i];
switch (i) {
case 0:
EXPECT_EQ(MSGPACK_OBJECT_NIL, o.type);
break;
case 1:
EXPECT_EQ(MSGPACK_OBJECT_BOOLEAN, o.type);
EXPECT_EQ(true, o.via.boolean);
break;
case 2:
EXPECT_EQ(MSGPACK_OBJECT_BOOLEAN, o.type);
EXPECT_EQ(false, o.via.boolean);
break;
case 3:
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, o.type);
EXPECT_EQ(10, o.via.u64);
break;
case 4:
EXPECT_EQ(MSGPACK_OBJECT_NEGATIVE_INTEGER, o.type);
EXPECT_EQ(-10, o.via.i64);
break;
}
}
msgpack_zone_destroy(&z);
msgpack_sbuffer_destroy(&sbuf);
}
TEST(MSGPACKC, simple_buffer_map)
{
unsigned int map_size = 2;
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
msgpack_packer pk;
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
msgpack_pack_map(&pk, map_size);
msgpack_pack_true(&pk);
msgpack_pack_false(&pk);
msgpack_pack_int(&pk, 10);
msgpack_pack_int(&pk, -10);
msgpack_zone z;
msgpack_zone_init(&z, 2048);
msgpack_object obj;
msgpack_unpack_return ret;
ret = msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
EXPECT_EQ(MSGPACK_OBJECT_MAP, obj.type);
EXPECT_EQ(map_size, obj.via.map.size);
for (unsigned int i = 0; i < map_size; i++) {
msgpack_object key = obj.via.map.ptr[i].key;
msgpack_object val = obj.via.map.ptr[i].val;
switch (i) {
case 0:
EXPECT_EQ(MSGPACK_OBJECT_BOOLEAN, key.type);
EXPECT_EQ(true, key.via.boolean);
EXPECT_EQ(MSGPACK_OBJECT_BOOLEAN, val.type);
EXPECT_EQ(false, val.via.boolean);
break;
case 1:
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, key.type);
EXPECT_EQ(10, key.via.u64);
EXPECT_EQ(MSGPACK_OBJECT_NEGATIVE_INTEGER, val.type);
EXPECT_EQ(-10, val.via.i64);
break;
}
}
msgpack_zone_destroy(&z);
msgpack_sbuffer_destroy(&sbuf);
}
TEST(MSGPACKC, simple_buffer_raw)
{
unsigned int raw_size = 7;
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
msgpack_packer pk;
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
msgpack_pack_raw(&pk, raw_size);
msgpack_pack_raw_body(&pk, "fr", 2);
msgpack_pack_raw_body(&pk, "syuki", 5);
// invalid data
msgpack_pack_raw_body(&pk, "", 0);
msgpack_pack_raw_body(&pk, "kzk", 0);
msgpack_zone z;
msgpack_zone_init(&z, 2048);
msgpack_object obj;
msgpack_unpack_return ret;
ret = msgpack_unpack(sbuf.data, sbuf.size, NULL, &z, &obj);
EXPECT_EQ(MSGPACK_UNPACK_SUCCESS, ret);
EXPECT_EQ(MSGPACK_OBJECT_RAW, obj.type);
EXPECT_EQ(raw_size, obj.via.raw.size);
EXPECT_EQ(0, memcmp("frsyuki", obj.via.raw.ptr, raw_size));
msgpack_zone_destroy(&z);
msgpack_sbuffer_destroy(&sbuf);
}

134
cpp/test/object.cc Normal file
View File

@@ -0,0 +1,134 @@
#include <msgpack.hpp>
#include <gtest/gtest.h>
struct myclass {
myclass() : num(0), str("default") { }
myclass(int num, const std::string& str) :
num(0), str("default") { }
~myclass() { }
int num;
std::string str;
MSGPACK_DEFINE(num, str);
bool operator==(const myclass& o) const
{
return num == o.num && str == o.str;
}
};
std::ostream& operator<<(std::ostream& o, const myclass& m)
{
return o << "myclass("<<m.num<<",\""<<m.str<<"\")";
}
TEST(object, convert)
{
myclass m1;
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, m1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(ret, msgpack::UNPACK_SUCCESS);
myclass m2;
obj.convert(&m2);
EXPECT_EQ(m1, m2);
}
TEST(object, as)
{
myclass m1;
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, m1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(ret, msgpack::UNPACK_SUCCESS);
EXPECT_EQ(m1, obj.as<myclass>());
}
TEST(object, print)
{
msgpack::object obj;
std::cout << obj << std::endl;
}
TEST(object, is_nil)
{
msgpack::object obj;
EXPECT_TRUE(obj.is_nil());
}
TEST(object, type_error)
{
msgpack::object obj(1);
EXPECT_THROW(obj.as<std::string>(), msgpack::type_error);
EXPECT_THROW(obj.as<std::vector<int> >(), msgpack::type_error);
EXPECT_EQ(1, obj.as<int>());
EXPECT_EQ(1, obj.as<short>());
EXPECT_EQ(1u, obj.as<unsigned int>());
EXPECT_EQ(1u, obj.as<unsigned long>());
}
TEST(object, equal_primitive)
{
msgpack::object obj_nil;
EXPECT_EQ(obj_nil, msgpack::object());
msgpack::object obj_int(1);
EXPECT_EQ(obj_int, msgpack::object(1));
EXPECT_EQ(obj_int, 1);
msgpack::object obj_double(1.2);
EXPECT_EQ(obj_double, msgpack::object(1.2));
EXPECT_EQ(obj_double, 1.2);
msgpack::object obj_bool(true);
EXPECT_EQ(obj_bool, msgpack::object(true));
EXPECT_EQ(obj_bool, true);
}
TEST(object, construct_primitive)
{
msgpack::object obj_nil;
EXPECT_EQ(msgpack::type::NIL, obj_nil.type);
msgpack::object obj_uint(1);
EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj_uint.type);
EXPECT_EQ(1u, obj_uint.via.u64);
msgpack::object obj_int(-1);
EXPECT_EQ(msgpack::type::NEGATIVE_INTEGER, obj_int.type);
EXPECT_EQ(-1, obj_int.via.i64);
msgpack::object obj_double(1.2);
EXPECT_EQ(msgpack::type::DOUBLE, obj_double.type);
EXPECT_EQ(1.2, obj_double.via.dec);
msgpack::object obj_bool(true);
EXPECT_EQ(msgpack::type::BOOLEAN, obj_bool.type);
EXPECT_EQ(true, obj_bool.via.boolean);
}

123
cpp/test/pack_unpack.cc Normal file
View File

@@ -0,0 +1,123 @@
#include <msgpack.hpp>
#include <gtest/gtest.h>
#include <sstream>
TEST(pack, num)
{
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, 1);
}
TEST(pack, vector)
{
msgpack::sbuffer sbuf;
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
msgpack::pack(sbuf, vec);
}
TEST(pack, to_ostream)
{
std::ostringstream stream;
msgpack::pack(stream, 1);
}
struct myclass {
myclass() : num(0), str("default") { }
myclass(int num, const std::string& str) :
num(0), str("default") { }
~myclass() { }
int num;
std::string str;
MSGPACK_DEFINE(num, str);
};
TEST(pack, myclass)
{
msgpack::sbuffer sbuf;
myclass m(1, "msgpack");
msgpack::pack(sbuf, m);
}
TEST(unpack, myclass)
{
msgpack::sbuffer sbuf;
myclass m1(1, "phraser");
msgpack::pack(sbuf, m1);
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret =
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &obj);
EXPECT_EQ(ret, msgpack::UNPACK_SUCCESS);
myclass m2 = obj.as<myclass>();
EXPECT_EQ(m1.num, m2.num);
EXPECT_EQ(m1.str, m2.str);
}
TEST(unpack, sequence)
{
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, 1);
msgpack::pack(sbuf, 2);
msgpack::pack(sbuf, 3);
size_t offset = 0;
msgpack::unpacked msg;
msgpack::unpack(&msg, sbuf.data(), sbuf.size(), &offset);
EXPECT_EQ(1, msg.get().as<int>());
msgpack::unpack(&msg, sbuf.data(), sbuf.size(), &offset);
EXPECT_EQ(2, msg.get().as<int>());
msgpack::unpack(&msg, sbuf.data(), sbuf.size(), &offset);
EXPECT_EQ(3, msg.get().as<int>());
}
TEST(unpack, sequence_compat)
{
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, 1);
msgpack::pack(sbuf, 2);
msgpack::pack(sbuf, 3);
size_t offset = 0;
msgpack::zone z;
msgpack::object obj;
msgpack::unpack_return ret;
ret = msgpack::unpack(sbuf.data(), sbuf.size(), &offset, &z, &obj);
EXPECT_TRUE(ret >= 0);
EXPECT_EQ(ret, msgpack::UNPACK_EXTRA_BYTES);
EXPECT_EQ(1, obj.as<int>());
ret = msgpack::unpack(sbuf.data(), sbuf.size(), &offset, &z, &obj);
EXPECT_TRUE(ret >= 0);
EXPECT_EQ(ret, msgpack::UNPACK_EXTRA_BYTES);
EXPECT_EQ(2, obj.as<int>());
ret = msgpack::unpack(sbuf.data(), sbuf.size(), &offset, &z, &obj);
EXPECT_TRUE(ret >= 0);
EXPECT_EQ(ret, msgpack::UNPACK_SUCCESS);
EXPECT_EQ(3, obj.as<int>());
}

70
cpp/test/pack_unpack_c.cc Normal file
View File

@@ -0,0 +1,70 @@
#include <msgpack.h>
#include <gtest/gtest.h>
#include <stdio.h>
TEST(pack, num)
{
msgpack_sbuffer* sbuf = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(sbuf, msgpack_sbuffer_write);
EXPECT_EQ(0, msgpack_pack_int(pk, 1));
msgpack_sbuffer_free(sbuf);
msgpack_packer_free(pk);
}
TEST(pack, array)
{
msgpack_sbuffer* sbuf = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(sbuf, msgpack_sbuffer_write);
EXPECT_EQ(0, msgpack_pack_array(pk, 3));
EXPECT_EQ(0, msgpack_pack_int(pk, 1));
EXPECT_EQ(0, msgpack_pack_int(pk, 2));
EXPECT_EQ(0, msgpack_pack_int(pk, 3));
msgpack_sbuffer_free(sbuf);
msgpack_packer_free(pk);
}
TEST(unpack, sequence)
{
msgpack_sbuffer* sbuf = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(sbuf, msgpack_sbuffer_write);
EXPECT_EQ(0, msgpack_pack_int(pk, 1));
EXPECT_EQ(0, msgpack_pack_int(pk, 2));
EXPECT_EQ(0, msgpack_pack_int(pk, 3));
msgpack_packer_free(pk);
bool success;
size_t offset = 0;
msgpack_unpacked msg;
msgpack_unpacked_init(&msg);
success = msgpack_unpack_next(&msg, sbuf->data, sbuf->size, &offset);
EXPECT_TRUE(success);
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, msg.data.type);
EXPECT_EQ(1, msg.data.via.u64);
success = msgpack_unpack_next(&msg, sbuf->data, sbuf->size, &offset);
EXPECT_TRUE(success);
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, msg.data.type);
EXPECT_EQ(2, msg.data.via.u64);
success = msgpack_unpack_next(&msg, sbuf->data, sbuf->size, &offset);
EXPECT_TRUE(success);
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, msg.data.type);
EXPECT_EQ(3, msg.data.via.u64);
success = msgpack_unpack_next(&msg, sbuf->data, sbuf->size, &offset);
EXPECT_FALSE(success);
msgpack_sbuffer_free(sbuf);
msgpack_unpacked_destroy(&msg);
}

220
cpp/test/streaming.cc Normal file
View File

@@ -0,0 +1,220 @@
#include <msgpack.hpp>
#include <gtest/gtest.h>
#include <sstream>
TEST(streaming, basic)
{
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack(1);
pk.pack(2);
pk.pack(3);
const char* input = buffer.data();
const char* const eof = input + buffer.size();
msgpack::unpacker pac;
msgpack::unpacked result;
int count = 0;
while(count < 3) {
pac.reserve_buffer(32*1024);
// read buffer into pac.buffer() upto
// pac.buffer_capacity() bytes.
size_t len = 1;
memcpy(pac.buffer(), input, len);
input += len;
pac.buffer_consumed(len);
while(pac.next(&result)) {
msgpack::object obj = result.get();
switch(count++) {
case 0:
EXPECT_EQ(1, obj.as<int>());
break;
case 1:
EXPECT_EQ(2, obj.as<int>());
break;
case 2:
EXPECT_EQ(3, obj.as<int>());
return;
}
}
EXPECT_TRUE(input < eof);
}
}
class event_handler {
public:
event_handler(std::istream& input) : input(input) { }
~event_handler() { }
void on_read()
{
while(true) {
pac.reserve_buffer(32*1024);
size_t len = input.readsome(pac.buffer(), pac.buffer_capacity());
if(len == 0) {
return;
}
pac.buffer_consumed(len);
msgpack::unpacked result;
while(pac.next(&result)) {
on_message(result.get(), result.zone());
}
if(pac.message_size() > 10*1024*1024) {
throw std::runtime_error("message is too large");
}
}
}
void on_message(msgpack::object obj, std::auto_ptr<msgpack::zone> z)
{
EXPECT_EQ(expect, obj.as<int>());
}
int expect;
private:
std::istream& input;
msgpack::unpacker pac;
};
TEST(streaming, event)
{
std::stringstream stream;
msgpack::packer<std::ostream> pk(&stream);
event_handler handler(stream);
pk.pack(1);
handler.expect = 1;
handler.on_read();
pk.pack(2);
handler.expect = 2;
handler.on_read();
pk.pack(3);
handler.expect = 3;
handler.on_read();
}
// backward compatibility
TEST(streaming, basic_compat)
{
std::ostringstream stream;
msgpack::packer<std::ostream> pk(&stream);
pk.pack(1);
pk.pack(2);
pk.pack(3);
std::istringstream input(stream.str());
msgpack::unpacker pac;
int count = 0;
while(count < 3) {
pac.reserve_buffer(32*1024);
size_t len = input.readsome(pac.buffer(), pac.buffer_capacity());
pac.buffer_consumed(len);
while(pac.execute()) {
std::auto_ptr<msgpack::zone> z(pac.release_zone());
msgpack::object obj = pac.data();
pac.reset();
switch(count++) {
case 0:
EXPECT_EQ(1, obj.as<int>());
break;
case 1:
EXPECT_EQ(2, obj.as<int>());
break;
case 2:
EXPECT_EQ(3, obj.as<int>());
return;
}
}
}
}
// backward compatibility
class event_handler_compat {
public:
event_handler_compat(std::istream& input) : input(input) { }
~event_handler_compat() { }
void on_read()
{
while(true) {
pac.reserve_buffer(32*1024);
size_t len = input.readsome(pac.buffer(), pac.buffer_capacity());
if(len == 0) {
return;
}
pac.buffer_consumed(len);
while(pac.execute()) {
std::auto_ptr<msgpack::zone> z(pac.release_zone());
msgpack::object obj = pac.data();
pac.reset();
on_message(obj, z);
}
if(pac.message_size() > 10*1024*1024) {
throw std::runtime_error("message is too large");
}
}
}
void on_message(msgpack::object obj, std::auto_ptr<msgpack::zone> z)
{
EXPECT_EQ(expect, obj.as<int>());
}
int expect;
private:
std::istream& input;
msgpack::unpacker pac;
};
TEST(streaming, event_compat)
{
std::stringstream stream;
msgpack::packer<std::ostream> pk(&stream);
event_handler_compat handler(stream);
pk.pack(1);
handler.expect = 1;
handler.on_read();
pk.pack(2);
handler.expect = 2;
handler.on_read();
pk.pack(3);
handler.expect = 3;
handler.on_read();
}

57
cpp/test/streaming_c.cc Normal file
View File

@@ -0,0 +1,57 @@
#include <msgpack.h>
#include <gtest/gtest.h>
#include <stdio.h>
TEST(streaming, basic)
{
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
EXPECT_EQ(0, msgpack_pack_int(pk, 1));
EXPECT_EQ(0, msgpack_pack_int(pk, 2));
EXPECT_EQ(0, msgpack_pack_int(pk, 3));
msgpack_packer_free(pk);
const char* input = buffer->data;
const char* const eof = input + buffer->size;
msgpack_unpacker pac;
msgpack_unpacker_init(&pac, MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
msgpack_unpacked result;
msgpack_unpacked_init(&result);
int count = 0;
while(count < 3) {
msgpack_unpacker_reserve_buffer(&pac, 32*1024);
/* read buffer into msgpack_unapcker_buffer(&pac) upto
* msgpack_unpacker_buffer_capacity(&pac) bytes. */
size_t len = 1;
memcpy(msgpack_unpacker_buffer(&pac), input, len);
input += len;
msgpack_unpacker_buffer_consumed(&pac, len);
while(msgpack_unpacker_next(&pac, &result)) {
msgpack_object obj = result.data;
switch(count++) {
case 0:
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, result.data.type);
EXPECT_EQ(1, result.data.via.u64);
break;
case 1:
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, result.data.type);
EXPECT_EQ(2, result.data.via.u64);
break;
case 2:
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, result.data.type);
EXPECT_EQ(3, result.data.via.u64);
return;
}
}
EXPECT_TRUE(input < eof);
}
}

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());
}

78
cpp/test/zone.cc Normal file
View File

@@ -0,0 +1,78 @@
#include <msgpack.hpp>
#include <gtest/gtest.h>
TEST(zone, malloc)
{
msgpack::zone z;
char* buf1 = (char*)z.malloc(4);
memcpy(buf1, "test", 4);
char* buf2 = (char*)z.malloc(4);
memcpy(buf2, "test", 4);
}
class myclass {
public:
myclass() : num(0), str("default") { }
myclass(int num, const std::string& str) :
num(num), str(str) { }
~myclass() { }
int num;
std::string str;
private:
myclass(const myclass&);
};
TEST(zone, allocate)
{
msgpack::zone z;
myclass* m = z.allocate<myclass>();
EXPECT_EQ(m->num, 0);
EXPECT_EQ(m->str, "default");
}
TEST(zone, allocate_constructor)
{
msgpack::zone z;
myclass* m = z.allocate<myclass>(7, "msgpack");
EXPECT_EQ(m->num, 7);
EXPECT_EQ(m->str, "msgpack");
}
static void custom_finalizer_func(void* user)
{
myclass* m = (myclass*)user;
delete m;
}
TEST(zone, push_finalizer)
{
msgpack::zone z;
myclass* m = new myclass();
z.push_finalizer(custom_finalizer_func, (void*)m);
}
TEST(zone, push_finalizer_auto_ptr)
{
msgpack::zone z;
std::auto_ptr<myclass> am(new myclass());
z.push_finalizer(am);
}
TEST(zone, malloc_no_align)
{
msgpack::zone z;
char* buf1 = (char*)z.malloc_no_align(4);
char* buf2 = (char*)z.malloc_no_align(4);
EXPECT_EQ(buf1+4, buf2);
}

View File

@@ -1,9 +0,0 @@
#include "msgpack/type/array.hpp"
#include "msgpack/type/boolean.hpp"
#include "msgpack/type/float.hpp"
#include "msgpack/type/integer.hpp"
#include "msgpack/type/map.hpp"
#include "msgpack/type/nil.hpp"
#include "msgpack/type/raw.hpp"
#include "msgpack/type/tuple.hpp"

4
erlang/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
MANIFEST
*.beam
.omakedb*
*.omc

42
erlang/OMakefile Normal file
View File

@@ -0,0 +1,42 @@
########################################################################
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this file, to deal in the File without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the File, and to permit persons to whom the
# File is furnished to do so, subject to the following condition:
#
# THE FILE 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 FILE OR
# THE USE OR OTHER DEALINGS IN THE FILE.
########################################################################
# The standard OMakefile.
# You will usually need to modify this file for your project.
########################################################################
# Phony targets are scoped, so you probably want to declare them first.
#
.PHONY: all clean test #install
########################################################################
# Subdirectories.
# You may want to include some subdirectories in this project.
# If so, define the subdirectory targets and uncomment this section.
#
.DEFAULT: msgpack.beam
msgpack.beam: msgpack.erl
erlc $<
test: msgpack.beam
erl -noshell -s msgpack test -s init stop
clean:
-rm *.beam

45
erlang/OMakeroot Normal file
View File

@@ -0,0 +1,45 @@
########################################################################
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this file, to deal in the File without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the File, and to permit persons to whom the
# File is furnished to do so, subject to the following condition:
#
# THE FILE 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 FILE OR
# THE USE OR OTHER DEALINGS IN THE FILE.
########################################################################
# The standard OMakeroot file.
# You will not normally need to modify this file.
# By default, your changes should be placed in the
# OMakefile in this directory.
#
# If you decide to modify this file, note that it uses exactly
# the same syntax as the OMakefile.
#
#
# Include the standard installed configuration files.
# Any of these can be deleted if you are not using them,
# but you probably want to keep the Common file.
#
open build/C
open build/OCaml
open build/LaTeX
#
# The command-line variables are defined *after* the
# standard configuration has been loaded.
#
DefineCommandVars()
#
# Include the OMakefile in this directory.
#
.SUBDIRS: .

9
erlang/README.md Normal file
View File

@@ -0,0 +1,9 @@
MessagePack for Erlang
======================
Binary-based efficient object serialization library.
see wiki ( http://redmine.msgpack.org/projects/msgpack/wiki/QuickStartErlang ) for details
# Status
0.1.0 released.

362
erlang/msgpack.erl Normal file
View File

@@ -0,0 +1,362 @@
%%
%% MessagePack for Erlang
%%
%% Copyright (C) 2009-2010 UENISHI Kota
%%
%% 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.
-module(msgpack).
-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)
%% 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 | no_code_matches.
-type msgpack_term() :: [msgpack_term()]
| {[{msgpack_term(),msgpack_term()}]}
| integer() | float() | binary().
% ===== external APIs ===== %
-spec pack(Term::msgpack_term()) -> binary().
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) ->
{error, undefined}.
% 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()} |
{more, non_neg_integer()} | {more, undefined} |
{error, reason()}.
unpack(Bin) when not is_binary(Bin)->
{error, badarg};
unpack(Bin) when bit_size(Bin) >= 8 ->
unpack_(Bin);
unpack(<<>>)->
{more, 1};
unpack(_) ->
{more, undefined}.
-spec unpack_all( binary() ) -> [msgpack_term()].
unpack_all(Data)->
case unpack(Data) of
{ Term, Binary } when bit_size(Binary) =:= 0 ->
[Term];
{ Term, Binary } when is_binary(Binary) ->
[Term|unpack_all(Binary)]
end.
-spec pack_map(M::[{msgpack_term(),msgpack_term()}])-> binary().
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 ===== %
% positive fixnum
pack_uint_(N) when N < 128 ->
<< 2#0:1, N:7 >>;
% uint 8
pack_uint_(N) when N < 256 ->
<< 16#CC:8, N:8 >>;
% uint 16
pack_uint_(N) when N < 65536 ->
<< 16#CD:8, N:16/big-unsigned-integer-unit:1 >>;
% uint 32
pack_uint_(N) when N < 16#FFFFFFFF->
<< 16#CE:8, N:32/big-unsigned-integer-unit:1 >>;
% uint 64
pack_uint_(N) ->
<< 16#CF:8, N:64/big-unsigned-integer-unit:1 >>.
% negative fixnum
pack_int_(N) when is_integer(N) , N >= -32->
<< 2#111:3, N:5 >>;
% int 8
pack_int_(N) when N > -128 ->
<< 16#D0:8, N:8/big-signed-integer-unit:1 >>;
% int 16
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 ->
<< 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 >>.
% float : erlang's float is always IEEE 754 64bit format.
%pack_float(F) when is_float(F)->
% << 16#CA:8, F:32/big-float-unit:1 >>.
% pack_double(F).
% double
pack_double(F) ->
<< 16#CB:8, F:64/big-float-unit:1 >>.
% raw bytes
pack_raw(Bin) ->
case byte_size(Bin) of
Len when Len < 6->
<< 2#101:3, Len:5, Bin/binary >>;
Len when Len < 16#10000 -> % 65536
<< 16#DA:8, Len:16/big-unsigned-integer-unit:1, Bin/binary >>;
Len ->
<< 16#DB:8, Len:32/big-unsigned-integer-unit:1, Bin/binary >>
end.
% list / tuple
pack_array(L) ->
case length(L) of
Len when Len < 16 ->
<< 2#1001:4, Len:4/integer-unit:1, (pack_array_(L, <<>>))/binary >>;
Len when Len < 16#10000 -> % 65536
<< 16#DC:8, Len:16/big-unsigned-integer-unit:1,(pack_array_(L, <<>>))/binary >>;
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>>).
% FIXME! this should be without lists:reverse/1
unpack_array_(<<>>, 0, RetList) -> {lists:reverse(RetList), <<>>};
unpack_array_(Remain, 0, RetList) when is_binary(Remain)-> {lists:reverse(RetList), Remain};
unpack_array_(<<>>, RestLen, _RetList) when RestLen > 0 -> {more, undefined};
unpack_array_(Bin, RestLen, RetList) when is_binary(Bin)->
case unpack(Bin) of
{more, _} -> {more, undefined};
{Term, Rest}-> unpack_array_(Rest, RestLen-1, [Term|RetList])
end.
pack_map_([], Acc) -> Acc;
pack_map_([{Key,Value}|Tail], Acc) ->
pack_map_(Tail, << Acc/binary, (pack(Key))/binary, (pack(Value))/binary>>).
% FIXME! this should be without lists:reverse/1
-spec unpack_map_(binary(), non_neg_integer(), [{term(), msgpack_term()}])->
{more, non_neg_integer()} | { any(), binary()}.
unpack_map_(Bin, 0, Acc) -> {{lists:reverse(Acc)}, Bin};
unpack_map_(Bin, Len, Acc) ->
case unpack(Bin) of
{more, _} -> {more, undefined};
{Key, Rest} ->
case unpack(Rest) of
{more, _} -> {more, undefined};
{Value, Rest2} ->
unpack_map_(Rest2,Len-1,[{Key,Value}|Acc])
end
end.
-spec unpack_(Payload::binary()) ->
{more, pos_integer()} | {msgpack_term(), binary()} | {error, reason()}.
unpack_(Binary)->
case Binary of
% ATOMS
<<16#C0, Rest/binary>> -> {nil, Rest};
<<16#C2, Rest/binary>> -> {false, Rest};
<<16#C3, Rest/binary>> -> {true, Rest};
% Floats
<<16#CA, V:32/float-unit:1, Rest/binary>> -> {V, Rest};
<<16#CB, V:64/float-unit:1, Rest/binary>> -> {V, Rest};
% Unsigned integers
<<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
<<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
<<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
<<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
<<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)
<<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
<<16#CA, Rest/binary>> -> {more, 4-byte_size(Rest)};
<<16#CB, Rest/binary>> -> {more, 8-byte_size(Rest)};
<<16#CC>> -> {more, 1};
<<16#CD, Rest/binary>> -> {more, 2-byte_size(Rest)};
<<16#CE, Rest/binary>> -> {more, 4-byte_size(Rest)};
<<16#CF, Rest/binary>> -> {more, 8-byte_size(Rest)};
<<16#D0>> -> {more, 1};
<<16#D1, Rest/binary>> -> {more, 2-byte_size(Rest)};
<<16#D2, Rest/binary>> -> {more, 4-byte_size(Rest)};
<<16#D3, Rest/binary>> -> {more, 8-byte_size(Rest)};
<<16#DA, Rest/binary>> -> {more, 16-byte_size(Rest)};
<<16#DB, Rest/binary>> -> {more, 32-byte_size(Rest)};
<<16#DC, Rest/binary>> -> {more, 2-byte_size(Rest)};
<<16#DD, Rest/binary>> -> {more, 4-byte_size(Rest)};
<<16#DE, Rest/binary>> -> {more, 2-byte_size(Rest)};
<<16#DF, Rest/binary>> -> {more, 4-byte_size(Rest)};
<<2#101:3, L:5, Rest/binary>> -> {more, L-byte_size(Rest)};
<<>> -> {more, 1};
<<2#101:3, _/binary>> -> {more, undefined};
<<F:8, Rest/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->
{error, {badarg, <<F, Rest/binary>>}};
Other ->
{error, {badarg, Other}}
end.
% ===== 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([LH|LTL], [RH|RTL]) ->
LH=RH,
compare_all(LTL, RTL).
test_data()->
[true, false, nil,
0, 1, 2, 123, 512, 1230, 678908, 16#FFFFFFFFFF,
-1, -23, -512, -1230, -567898, -16#FFFFFFFFFF,
123.123, -234.4355, 1.0e-34, 1.0e64,
[23, 234, 0.23],
<<"hogehoge">>, <<"243546rf7g68h798j", 0, 23, 255>>,
<<"hoasfdafdas][">>,
[0,42, <<"sum">>, [1,2]], [1,42, nil, [3]],
-234, -40000, -16#10000000, -16#100000000,
42
].
basic_test()->
Tests = test_data(),
Passed = test_(Tests),
Passed = length(Tests).
port_test()->
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)
after 1024-> ?assert(false) end,
port_close(Port).
test_p(Len,Term,OrigBin,Len) ->
{Term, <<>>}=msgpack:unpack(OrigBin);
test_p(I,_,OrigBin,Len) when I < Len->
<<Bin:I/binary, _/binary>> = OrigBin,
case msgpack:unpack(Bin) of
{more, N} when not is_integer(N) ->
?assertEqual(undefined, N);
{more, N} ->
?assert( N < Len )
end.
partial_test()-> % error handling test.
Term = lists:seq(0, 45),
Bin=msgpack:pack(Term),
BinLen = byte_size(Bin),
[test_p(X, Term, Bin, BinLen) || X <- lists:seq(0,BinLen)].
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.
map_test()->
Ints = lists:seq(0, 65),
Map = {[ {X, X*2} || X <- Ints ] ++ [{<<"hage">>, 324}, {43542, [nil, true, false]}]},
{Map2, <<>>} = msgpack:unpack(msgpack:pack(Map)),
?assertEqual(Map, Map2),
ok.
unknown_test()->
Tests = [0, 1, 2, 123, 512, 1230, 678908,
-1, -23, -512, -1230, -567898,
<<"hogehoge">>, <<"243546rf7g68h798j">>,
123.123,
-234.4355, 1.0e-34, 1.0e64,
[23, 234, 0.23],
[0,42,<<"sum">>, [1,2]], [1,42, nil, [3]],
{[{1,2},{<<"hoge">>,nil}]},
-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_close(Port).
test_([]) -> 0;
test_([Before|Rest])->
Pack = msgpack:pack(Before),
{After, <<>>} = msgpack:unpack( Pack ),
?assertEqual(Before, After),
1+test_(Rest).
other_test()->
{more,1}=msgpack:unpack(<<>>).
-endif.

View File

@@ -0,0 +1,65 @@
begin
require 'rubygems'
rescue LoadError
end
require 'msgpack'
def usage
puts <<EOF
Usage: #{$0} [out-file]
This tool is for testing of accepting MessagePack random-term.
This does following behavior:
1. serializes the objects in this file, using Ruby implementation
of MessagePack (Note that Ruby implementation is considered valid)
2. Writes the serialized binaries into <out-file> (default: stdout)
EOF
exit 1
end
code = 1
outio = $stdout
if ARGV.length > 2
usage
end
if fname = ARGV[0]
unless fname == "-"
begin
outio = File.open(fname, "w")
rescue
puts "can't open output file: #{$!}"
exit 1
end
end
end
objs = [0, 1, 2, 123, 512, 1230, 678908,
-1, -23, -512, -1230, -567898,
"hogehoge", "243546rf7g68h798j",
123.123,
-234.4355, 1.0e-34, 1.0e64,
[23, 234, 0.23],
[0,42,"sum", [1,2]], [1,42, nil, [3]],
{ 1 => 2, "hoge" => nil },
-234, -50000,
42
]
begin
objs.each do |obj|
outio.write MessagePack.pack(obj)
outio.flush
end
rescue EOFError
code=0
rescue
$stderr.puts $!
code=1
end
outio.close
exit code

58
example/custom.cc Normal file
View File

@@ -0,0 +1,58 @@
#include <msgpack.hpp>
#include <string>
#include <iostream>
class old_class {
public:
old_class() : value("default") { }
std::string value;
MSGPACK_DEFINE(value);
};
class new_class {
public:
new_class() : value("default"), flag(-1) { }
std::string value;
int flag;
MSGPACK_DEFINE(value, flag);
};
int main(void)
{
{
old_class oc;
new_class nc;
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, oc);
msgpack::zone zone;
msgpack::object obj;
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &zone, &obj);
obj.convert(&nc);
std::cout << obj << " value=" << nc.value << " flag=" << nc.flag << std::endl;
}
{
new_class nc;
old_class oc;
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, nc);
msgpack::zone zone;
msgpack::object obj;
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &zone, &obj);
obj.convert(&oc);
std::cout << obj << " value=" << oc.value << std::endl;
}
}

View File

@@ -22,14 +22,14 @@ public:
ssize_t count =
read(m_sock, m_pac.buffer(), m_pac.buffer_capacity());
if(count < 0) {
if(count <= 0) {
if(count == 0) {
throw std::runtime_error("connection closed");
}
if(errno == EAGAIN || errno == EINTR) {
return;
} else {
throw std::runtime_error(strerror(errno));
}
} else if(count == 0) {
throw std::runtime_error("connection closed");
throw std::runtime_error(strerror(errno));
}
m_pac.buffer_consumed(count);

24
haskell/LICENSE Normal file
View File

@@ -0,0 +1,24 @@
Copyright (c) 2009, Hideyuki Tanaka
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Hideyuki Tanaka nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY Hideyuki Tanaka ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

3
haskell/Setup.lhs Normal file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env runhaskell
> import Distribution.Simple
> main = defaultMain

137
haskell/cbits/msgpack.c Normal file
View File

@@ -0,0 +1,137 @@
#include <msgpack.h>
void msgpack_sbuffer_init_wrap(msgpack_sbuffer* sbuf)
{
msgpack_sbuffer_init(sbuf);
}
void msgpack_sbuffer_destroy_wrap(msgpack_sbuffer* sbuf)
{
msgpack_sbuffer_destroy(sbuf);
}
int msgpack_sbuffer_write_wrap(void* data, const char* buf, unsigned int len)
{
return msgpack_sbuffer_write(data, buf, len);
}
msgpack_packer* msgpack_packer_new_wrap(void *data, msgpack_packer_write callback)
{
return msgpack_packer_new(data, callback);
}
void msgpack_packer_free_wrap(msgpack_packer* pk)
{
msgpack_packer_free(pk);
}
int msgpack_pack_uint8_wrap(msgpack_packer* pk, uint8_t d)
{
return msgpack_pack_uint8(pk, d);
}
int msgpack_pack_uint16_wrap(msgpack_packer* pk, uint16_t d)
{
return msgpack_pack_uint16(pk, d);
}
int msgpack_pack_uint32_wrap(msgpack_packer* pk, uint32_t d)
{
return msgpack_pack_uint32(pk, d);
}
int msgpack_pack_uint64_wrap(msgpack_packer* pk, uint64_t d)
{
return msgpack_pack_uint64(pk, d);
}
int msgpack_pack_int8_wrap(msgpack_packer* pk, int8_t d)
{
return msgpack_pack_int8(pk, d);
}
int msgpack_pack_int16_wrap(msgpack_packer* pk, int16_t d)
{
return msgpack_pack_int16(pk, d);
}
int msgpack_pack_int32_wrap(msgpack_packer* pk, int32_t d)
{
return msgpack_pack_int32(pk, d);
}
int msgpack_pack_int64_wrap(msgpack_packer* pk, int64_t d)
{
return msgpack_pack_int64(pk, d);
}
int msgpack_pack_double_wrap(msgpack_packer* pk, double d)
{
return msgpack_pack_double(pk, d);
}
int msgpack_pack_nil_wrap(msgpack_packer* pk)
{
return msgpack_pack_nil(pk);
}
int msgpack_pack_true_wrap(msgpack_packer* pk)
{
return msgpack_pack_true(pk);
}
int msgpack_pack_false_wrap(msgpack_packer* pk)
{
return msgpack_pack_false(pk);
}
int msgpack_pack_array_wrap(msgpack_packer* pk, unsigned int n)
{
return msgpack_pack_array(pk, n);
}
int msgpack_pack_map_wrap(msgpack_packer* pk, unsigned int n)
{
return msgpack_pack_map(pk, n);
}
int msgpack_pack_raw_wrap(msgpack_packer* pk, size_t l)
{
return msgpack_pack_raw(pk, l);
}
int msgpack_pack_raw_body_wrap(msgpack_packer* pk, const void *b, size_t l)
{
return msgpack_pack_raw_body(pk, b, l);
}
bool msgpack_unpacker_reserve_buffer_wrap(msgpack_unpacker *mpac, size_t size)
{
return msgpack_unpacker_reserve_buffer(mpac, size);
}
char *msgpack_unpacker_buffer_wrap(msgpack_unpacker *mpac)
{
return msgpack_unpacker_buffer(mpac);
}
size_t msgpack_unpacker_buffer_capacity_wrap(const msgpack_unpacker *mpac)
{
return msgpack_unpacker_buffer_capacity(mpac);
}
void msgpack_unpacker_buffer_consumed_wrap(msgpack_unpacker *mpac, size_t size)
{
msgpack_unpacker_buffer_consumed(mpac, size);
}
void msgpack_unpacker_data_wrap(msgpack_unpacker *mpac, msgpack_object *obj)
{
*obj=msgpack_unpacker_data(mpac);
}
size_t msgpack_unpacker_message_size_wrap(const msgpack_unpacker *mpac)
{
return msgpack_unpacker_message_size(mpac);
}

32
haskell/msgpack.cabal Normal file
View File

@@ -0,0 +1,32 @@
Name: msgpack
Version: 0.2.2
License: BSD3
License-File: LICENSE
Author: Hideyuki Tanaka
Maintainer: Hideyuki Tanaka <tanaka.hideyuki@gmail.com>
Category: Data
Synopsis: A Haskell binding to MessagePack
Description:
A Haskell binding to MessagePack <http://msgpack.sourceforge.jp/>
Homepage: http://github.com/tanakh/hsmsgpack
Stability: Experimental
Tested-with: GHC==6.10.4
Cabal-Version: >=1.2
Build-Type: Simple
library
build-depends: base>=4 && <5, mtl, bytestring
ghc-options: -O2 -Wall
hs-source-dirs: src
extra-libraries: msgpackc
Exposed-modules:
Data.MessagePack
Data.MessagePack.Base
Data.MessagePack.Class
Data.MessagePack.Feed
Data.MessagePack.Monad
Data.MessagePack.Stream
C-Sources:
cbits/msgpack.c

View File

@@ -0,0 +1,63 @@
--------------------------------------------------------------------
-- |
-- Module : Data.MessagePack
-- Copyright : (c) Hideyuki Tanaka, 2009
-- License : BSD3
--
-- Maintainer: tanaka.hideyuki@gmail.com
-- Stability : experimental
-- Portability: portable
--
-- Simple interface to pack and unpack MessagePack data.
--
--------------------------------------------------------------------
module Data.MessagePack(
module Data.MessagePack.Base,
module Data.MessagePack.Class,
module Data.MessagePack.Feed,
module Data.MessagePack.Monad,
module Data.MessagePack.Stream,
-- * Pack and Unpack
packb,
unpackb,
-- * Pure version of Pack and Unpack
packb',
unpackb',
) where
import Data.ByteString (ByteString)
import System.IO.Unsafe
import Data.MessagePack.Base
import Data.MessagePack.Class
import Data.MessagePack.Feed
import Data.MessagePack.Monad
import Data.MessagePack.Stream
-- | Pack Haskell data to MessagePack string.
packb :: OBJECT a => a -> IO ByteString
packb dat = do
sb <- newSimpleBuffer
pc <- newPacker sb
pack pc dat
simpleBufferData sb
-- | Unpack MessagePack string to Haskell data.
unpackb :: OBJECT a => ByteString -> IO (Result a)
unpackb bs = do
withZone $ \z -> do
r <- unpackObject z bs
return $ case r of
Left err -> Left (show err)
Right (_, dat) -> fromObject dat
-- | Pure version of 'packb'.
packb' :: OBJECT a => a -> ByteString
packb' dat = unsafePerformIO $ packb dat
-- | Pure version of 'unpackb'.
unpackb' :: OBJECT a => ByteString -> Result a
unpackb' bs = unsafePerformIO $ unpackb bs

View File

@@ -0,0 +1,584 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE ForeignFunctionInterface #-}
--------------------------------------------------------------------
-- |
-- Module : Data.MessagePack.Base
-- Copyright : (c) Hideyuki Tanaka, 2009
-- License : BSD3
--
-- Maintainer: tanaka.hideyuki@gmail.com
-- Stability : experimental
-- Portability: portable
--
-- Low Level Interface to MessagePack C API
--
--------------------------------------------------------------------
module Data.MessagePack.Base(
-- * Simple Buffer
SimpleBuffer,
newSimpleBuffer,
simpleBufferData,
-- * Serializer
Packer,
newPacker,
packU8,
packU16,
packU32,
packU64,
packS8,
packS16,
packS32,
packS64,
packTrue,
packFalse,
packInt,
packDouble,
packNil,
packBool,
packArray,
packMap,
packRAW,
packRAWBody,
packRAW',
-- * Stream Deserializer
Unpacker,
defaultInitialBufferSize,
newUnpacker,
unpackerReserveBuffer,
unpackerBuffer,
unpackerBufferCapacity,
unpackerBufferConsumed,
unpackerFeed,
unpackerExecute,
unpackerData,
unpackerReleaseZone,
unpackerResetZone,
unpackerReset,
unpackerMessageSize,
-- * MessagePack Object
Object(..),
packObject,
UnpackReturn(..),
unpackObject,
-- * Memory Zone
Zone,
newZone,
freeZone,
withZone,
) where
import Control.Exception
import Control.Monad
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS hiding (pack, unpack)
import Data.Int
import Data.Word
import Foreign.C
import Foreign.Concurrent
import Foreign.ForeignPtr hiding (newForeignPtr)
import Foreign.Marshal.Alloc
import Foreign.Marshal.Array
import Foreign.Ptr
import Foreign.Storable
#include <msgpack.h>
type SimpleBuffer = ForeignPtr ()
type WriteCallback = Ptr () -> CString -> CUInt -> IO CInt
-- | Create a new Simple Buffer. It will be deleted automatically.
newSimpleBuffer :: IO SimpleBuffer
newSimpleBuffer = do
ptr <- mallocBytes (#size msgpack_sbuffer)
fptr <- newForeignPtr ptr $ do
msgpack_sbuffer_destroy ptr
free ptr
withForeignPtr fptr $ \p ->
msgpack_sbuffer_init p
return fptr
-- | Get data of Simple Buffer.
simpleBufferData :: SimpleBuffer -> IO ByteString
simpleBufferData sb =
withForeignPtr sb $ \ptr -> do
size <- (#peek msgpack_sbuffer, size) ptr
dat <- (#peek msgpack_sbuffer, data) ptr
BS.packCStringLen (dat, fromIntegral (size :: CSize))
foreign import ccall "msgpack_sbuffer_init_wrap" msgpack_sbuffer_init ::
Ptr () -> IO ()
foreign import ccall "msgpack_sbuffer_destroy_wrap" msgpack_sbuffer_destroy ::
Ptr () -> IO ()
foreign import ccall "msgpack_sbuffer_write_wrap" msgpack_sbuffer_write ::
WriteCallback
type Packer = ForeignPtr ()
-- | Create new Packer. It will be deleted automatically.
newPacker :: SimpleBuffer -> IO Packer
newPacker sbuf = do
cb <- wrap_callback msgpack_sbuffer_write
ptr <- withForeignPtr sbuf $ \ptr ->
msgpack_packer_new ptr cb
fptr <- newForeignPtr ptr $ do
msgpack_packer_free ptr
return fptr
foreign import ccall "msgpack_packer_new_wrap" msgpack_packer_new ::
Ptr () -> FunPtr WriteCallback -> IO (Ptr ())
foreign import ccall "msgpack_packer_free_wrap" msgpack_packer_free ::
Ptr () -> IO ()
foreign import ccall "wrapper" wrap_callback ::
WriteCallback -> IO (FunPtr WriteCallback)
packU8 :: Packer -> Word8 -> IO Int
packU8 pc n =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_uint8 ptr n
foreign import ccall "msgpack_pack_uint8_wrap" msgpack_pack_uint8 ::
Ptr () -> Word8 -> IO CInt
packU16 :: Packer -> Word16 -> IO Int
packU16 pc n =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_uint16 ptr n
foreign import ccall "msgpack_pack_uint16_wrap" msgpack_pack_uint16 ::
Ptr () -> Word16 -> IO CInt
packU32 :: Packer -> Word32 -> IO Int
packU32 pc n =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_uint32 ptr n
foreign import ccall "msgpack_pack_uint32_wrap" msgpack_pack_uint32 ::
Ptr () -> Word32 -> IO CInt
packU64 :: Packer -> Word64 -> IO Int
packU64 pc n =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_uint64 ptr n
foreign import ccall "msgpack_pack_uint64_wrap" msgpack_pack_uint64 ::
Ptr () -> Word64 -> IO CInt
packS8 :: Packer -> Int8 -> IO Int
packS8 pc n =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_int8 ptr n
foreign import ccall "msgpack_pack_int8_wrap" msgpack_pack_int8 ::
Ptr () -> Int8 -> IO CInt
packS16 :: Packer -> Int16 -> IO Int
packS16 pc n =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_int16 ptr n
foreign import ccall "msgpack_pack_int16_wrap" msgpack_pack_int16 ::
Ptr () -> Int16 -> IO CInt
packS32 :: Packer -> Int32 -> IO Int
packS32 pc n =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_int32 ptr n
foreign import ccall "msgpack_pack_int32_wrap" msgpack_pack_int32 ::
Ptr () -> Int32 -> IO CInt
packS64 :: Packer -> Int64 -> IO Int
packS64 pc n =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_int64 ptr n
foreign import ccall "msgpack_pack_int64_wrap" msgpack_pack_int64 ::
Ptr () -> Int64 -> IO CInt
-- | Pack an integral data.
packInt :: Integral a => Packer -> a -> IO Int
packInt pc n = packS64 pc $ fromIntegral n
-- | Pack a double data.
packDouble :: Packer -> Double -> IO Int
packDouble pc d =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_double ptr (realToFrac d)
foreign import ccall "msgpack_pack_double_wrap" msgpack_pack_double ::
Ptr () -> CDouble -> IO CInt
-- | Pack a nil.
packNil :: Packer -> IO Int
packNil pc =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_nil ptr
foreign import ccall "msgpack_pack_nil_wrap" msgpack_pack_nil ::
Ptr () -> IO CInt
packTrue :: Packer -> IO Int
packTrue pc =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_true ptr
foreign import ccall "msgpack_pack_true_wrap" msgpack_pack_true ::
Ptr () -> IO CInt
packFalse :: Packer -> IO Int
packFalse pc =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_false ptr
foreign import ccall "msgpack_pack_false_wrap" msgpack_pack_false ::
Ptr () -> IO CInt
-- | Pack a bool data.
packBool :: Packer -> Bool -> IO Int
packBool pc True = packTrue pc
packBool pc False = packFalse pc
-- | 'packArray' @p n@ starts packing an array.
-- Next @n@ data will consist this array.
packArray :: Packer -> Int -> IO Int
packArray pc n =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_array ptr (fromIntegral n)
foreign import ccall "msgpack_pack_array_wrap" msgpack_pack_array ::
Ptr () -> CUInt -> IO CInt
-- | 'packMap' @p n@ starts packing a map.
-- Next @n@ pairs of data (2*n data) will consist this map.
packMap :: Packer -> Int -> IO Int
packMap pc n =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_map ptr (fromIntegral n)
foreign import ccall "msgpack_pack_map_wrap" msgpack_pack_map ::
Ptr () -> CUInt -> IO CInt
-- | 'packRAW' @p n@ starts packing a byte sequence.
-- Next total @n@ bytes of 'packRAWBody' call will consist this sequence.
packRAW :: Packer -> Int -> IO Int
packRAW pc n =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
msgpack_pack_raw ptr (fromIntegral n)
foreign import ccall "msgpack_pack_raw_wrap" msgpack_pack_raw ::
Ptr () -> CSize -> IO CInt
-- | Pack a byte sequence.
packRAWBody :: Packer -> ByteString -> IO Int
packRAWBody pc bs =
liftM fromIntegral $ withForeignPtr pc $ \ptr ->
BS.useAsCStringLen bs $ \(str, len) ->
msgpack_pack_raw_body ptr (castPtr str) (fromIntegral len)
foreign import ccall "msgpack_pack_raw_body_wrap" msgpack_pack_raw_body ::
Ptr () -> Ptr () -> CSize -> IO CInt
-- | Pack a single byte stream. It calls 'packRAW' and 'packRAWBody'.
packRAW' :: Packer -> ByteString -> IO Int
packRAW' pc bs = do
_ <- packRAW pc (BS.length bs)
packRAWBody pc bs
type Unpacker = ForeignPtr ()
defaultInitialBufferSize :: Int
defaultInitialBufferSize = 32 * 1024 -- #const MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE
-- | 'newUnpacker' @initialBufferSize@ creates a new Unpacker. It will be deleted automatically.
newUnpacker :: Int -> IO Unpacker
newUnpacker initialBufferSize = do
ptr <- msgpack_unpacker_new (fromIntegral initialBufferSize)
fptr <- newForeignPtr ptr $ do
msgpack_unpacker_free ptr
return fptr
foreign import ccall "msgpack_unpacker_new" msgpack_unpacker_new ::
CSize -> IO (Ptr ())
foreign import ccall "msgpack_unpacker_free" msgpack_unpacker_free ::
Ptr() -> IO ()
-- | 'unpackerReserveBuffer' @up size@ reserves at least @size@ bytes of buffer.
unpackerReserveBuffer :: Unpacker -> Int -> IO Bool
unpackerReserveBuffer up size =
withForeignPtr up $ \ptr ->
liftM (/=0) $ msgpack_unpacker_reserve_buffer ptr (fromIntegral size)
foreign import ccall "msgpack_unpacker_reserve_buffer_wrap" msgpack_unpacker_reserve_buffer ::
Ptr () -> CSize -> IO CChar
-- | Get a pointer of unpacker buffer.
unpackerBuffer :: Unpacker -> IO (Ptr CChar)
unpackerBuffer up =
withForeignPtr up $ \ptr ->
msgpack_unpacker_buffer ptr
foreign import ccall "msgpack_unpacker_buffer_wrap" msgpack_unpacker_buffer ::
Ptr () -> IO (Ptr CChar)
-- | Get size of allocated buffer.
unpackerBufferCapacity :: Unpacker -> IO Int
unpackerBufferCapacity up =
withForeignPtr up $ \ptr ->
liftM fromIntegral $ msgpack_unpacker_buffer_capacity ptr
foreign import ccall "msgpack_unpacker_buffer_capacity_wrap" msgpack_unpacker_buffer_capacity ::
Ptr () -> IO CSize
-- | 'unpackerBufferConsumed' @up size@ notices that writed @size@ bytes to buffer.
unpackerBufferConsumed :: Unpacker -> Int -> IO ()
unpackerBufferConsumed up size =
withForeignPtr up $ \ptr ->
msgpack_unpacker_buffer_consumed ptr (fromIntegral size)
foreign import ccall "msgpack_unpacker_buffer_consumed_wrap" msgpack_unpacker_buffer_consumed ::
Ptr () -> CSize -> IO ()
-- | Write byte sequence to Unpacker. It is utility funciton, calls 'unpackerReserveBuffer', 'unpackerBuffer' and 'unpackerBufferConsumed'.
unpackerFeed :: Unpacker -> ByteString -> IO ()
unpackerFeed up bs =
BS.useAsCStringLen bs $ \(str, len) -> do
True <- unpackerReserveBuffer up len
ptr <- unpackerBuffer up
copyArray ptr str len
unpackerBufferConsumed up len
-- | Execute deserializing. It returns 0 when buffer contains not enough bytes, returns 1 when succeeded, returns negative value when it failed.
unpackerExecute :: Unpacker -> IO Int
unpackerExecute up =
withForeignPtr up $ \ptr ->
liftM fromIntegral $ msgpack_unpacker_execute ptr
foreign import ccall "msgpack_unpacker_execute" msgpack_unpacker_execute ::
Ptr () -> IO CInt
-- | Returns a deserialized object when 'unpackerExecute' returned 1.
unpackerData :: Unpacker -> IO Object
unpackerData up =
withForeignPtr up $ \ptr ->
allocaBytes (#size msgpack_object) $ \pobj -> do
msgpack_unpacker_data ptr pobj
peekObject pobj
foreign import ccall "msgpack_unpacker_data_wrap" msgpack_unpacker_data ::
Ptr () -> Ptr () -> IO ()
-- | Release memory zone. The returned zone must be freed by calling 'freeZone'.
unpackerReleaseZone :: Unpacker -> IO Zone
unpackerReleaseZone up =
withForeignPtr up $ \ptr ->
msgpack_unpacker_release_zone ptr
foreign import ccall "msgpack_unpacker_release_zone" msgpack_unpacker_release_zone ::
Ptr () -> IO (Ptr ())
-- | Free memory zone used by Unapcker.
unpackerResetZone :: Unpacker -> IO ()
unpackerResetZone up =
withForeignPtr up $ \ptr ->
msgpack_unpacker_reset_zone ptr
foreign import ccall "msgpack_unpacker_reset_zone" msgpack_unpacker_reset_zone ::
Ptr () -> IO ()
-- | Reset Unpacker state except memory zone.
unpackerReset :: Unpacker -> IO ()
unpackerReset up =
withForeignPtr up $ \ptr ->
msgpack_unpacker_reset ptr
foreign import ccall "msgpack_unpacker_reset" msgpack_unpacker_reset ::
Ptr () -> IO ()
-- | Returns number of bytes of sequence of deserializing object.
unpackerMessageSize :: Unpacker -> IO Int
unpackerMessageSize up =
withForeignPtr up $ \ptr ->
liftM fromIntegral $ msgpack_unpacker_message_size ptr
foreign import ccall "msgpack_unpacker_message_size_wrap" msgpack_unpacker_message_size ::
Ptr () -> IO CSize
type Zone = Ptr ()
-- | Create a new memory zone. It must be freed manually.
newZone :: IO Zone
newZone =
msgpack_zone_new (#const MSGPACK_ZONE_CHUNK_SIZE)
-- | Free a memory zone.
freeZone :: Zone -> IO ()
freeZone z =
msgpack_zone_free z
-- | Create a memory zone, then execute argument, then free memory zone.
withZone :: (Zone -> IO a) -> IO a
withZone z =
bracket newZone freeZone z
foreign import ccall "msgpack_zone_new" msgpack_zone_new ::
CSize -> IO Zone
foreign import ccall "msgpack_zone_free" msgpack_zone_free ::
Zone -> IO ()
-- | Object Representation of MessagePack data.
data Object =
ObjectNil
| ObjectBool Bool
| ObjectInteger Int
| ObjectDouble Double
| ObjectRAW ByteString
| ObjectArray [Object]
| ObjectMap [(Object, Object)]
deriving (Show)
peekObject :: Ptr a -> IO Object
peekObject ptr = do
typ <- (#peek msgpack_object, type) ptr
case (typ :: CInt) of
(#const MSGPACK_OBJECT_NIL) ->
return ObjectNil
(#const MSGPACK_OBJECT_BOOLEAN) ->
peekObjectBool ptr
(#const MSGPACK_OBJECT_POSITIVE_INTEGER) ->
peekObjectPositiveInteger ptr
(#const MSGPACK_OBJECT_NEGATIVE_INTEGER) ->
peekObjectNegativeInteger ptr
(#const MSGPACK_OBJECT_DOUBLE) ->
peekObjectDouble ptr
(#const MSGPACK_OBJECT_RAW) ->
peekObjectRAW ptr
(#const MSGPACK_OBJECT_ARRAY) ->
peekObjectArray ptr
(#const MSGPACK_OBJECT_MAP) ->
peekObjectMap ptr
_ ->
fail $ "peekObject: unknown object type (" ++ show typ ++ ")"
peekObjectBool :: Ptr a -> IO Object
peekObjectBool ptr = do
b <- (#peek msgpack_object, via.boolean) ptr
return $ ObjectBool $ (b :: CUChar) /= 0
peekObjectPositiveInteger :: Ptr a -> IO Object
peekObjectPositiveInteger ptr = do
n <- (#peek msgpack_object, via.u64) ptr
return $ ObjectInteger $ fromIntegral (n :: Word64)
peekObjectNegativeInteger :: Ptr a -> IO Object
peekObjectNegativeInteger ptr = do
n <- (#peek msgpack_object, via.i64) ptr
return $ ObjectInteger $ fromIntegral (n :: Int64)
peekObjectDouble :: Ptr a -> IO Object
peekObjectDouble ptr = do
d <- (#peek msgpack_object, via.dec) ptr
return $ ObjectDouble $ realToFrac (d :: CDouble)
peekObjectRAW :: Ptr a -> IO Object
peekObjectRAW ptr = do
size <- (#peek msgpack_object, via.raw.size) ptr
p <- (#peek msgpack_object, via.raw.ptr) ptr
bs <- BS.packCStringLen (p, fromIntegral (size :: Word32))
return $ ObjectRAW bs
peekObjectArray :: Ptr a -> IO Object
peekObjectArray ptr = do
csize <- (#peek msgpack_object, via.array.size) ptr
let size = fromIntegral (csize :: Word32)
p <- (#peek msgpack_object, via.array.ptr) ptr
objs <- mapM (\i -> peekObject $ p `plusPtr`
((#size msgpack_object) * i))
[0..size-1]
return $ ObjectArray objs
peekObjectMap :: Ptr a -> IO Object
peekObjectMap ptr = do
csize <- (#peek msgpack_object, via.map.size) ptr
let size = fromIntegral (csize :: Word32)
p <- (#peek msgpack_object, via.map.ptr) ptr
dat <- mapM (\i -> peekObjectKV $ p `plusPtr`
((#size msgpack_object_kv) * i))
[0..size-1]
return $ ObjectMap dat
peekObjectKV :: Ptr a -> IO (Object, Object)
peekObjectKV ptr = do
k <- peekObject $ ptr `plusPtr` (#offset msgpack_object_kv, key)
v <- peekObject $ ptr `plusPtr` (#offset msgpack_object_kv, val)
return (k, v)
-- | Pack a Object.
packObject :: Packer -> Object -> IO ()
packObject pc ObjectNil = packNil pc >> return ()
packObject pc (ObjectBool b) = packBool pc b >> return ()
packObject pc (ObjectInteger n) = packInt pc n >> return ()
packObject pc (ObjectDouble d) = packDouble pc d >> return ()
packObject pc (ObjectRAW bs) = packRAW' pc bs >> return ()
packObject pc (ObjectArray ls) = do
_ <- packArray pc (length ls)
mapM_ (packObject pc) ls
packObject pc (ObjectMap ls) = do
_ <- packMap pc (length ls)
mapM_ (\(a, b) -> packObject pc a >> packObject pc b) ls
data UnpackReturn =
UnpackContinue -- ^ not enough bytes to unpack object
| UnpackParseError -- ^ got invalid bytes
| UnpackError -- ^ other error
deriving (Eq, Show)
-- | Unpack a single MessagePack object from byte sequence.
unpackObject :: Zone -> ByteString -> IO (Either UnpackReturn (Int, Object))
unpackObject z dat =
allocaBytes (#size msgpack_object) $ \ptr ->
BS.useAsCStringLen dat $ \(str, len) ->
alloca $ \poff -> do
poke poff 0
ret <- msgpack_unpack str (fromIntegral len) poff z ptr
case ret of
(#const MSGPACK_UNPACK_SUCCESS) -> do
off <- peek poff
obj <- peekObject ptr
return $ Right (fromIntegral off, obj)
(#const MSGPACK_UNPACK_EXTRA_BYTES) -> do
off <- peek poff
obj <- peekObject ptr
return $ Right (fromIntegral off, obj)
(#const MSGPACK_UNPACK_CONTINUE) ->
return $ Left UnpackContinue
(#const MSGPACK_UNPACK_PARSE_ERROR) ->
return $ Left UnpackParseError
_ ->
return $ Left UnpackError
foreign import ccall "msgpack_unpack" msgpack_unpack ::
Ptr CChar -> CSize -> Ptr CSize -> Zone -> Ptr () -> IO CInt

View File

@@ -0,0 +1,101 @@
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverlappingInstances #-}
{-# LANGUAGE IncoherentInstances #-}
--------------------------------------------------------------------
-- |
-- Module : Data.MessagePack.Class
-- Copyright : (c) Hideyuki Tanaka, 2009
-- License : BSD3
--
-- Maintainer: tanaka.hideyuki@gmail.com
-- Stability : experimental
-- Portability: portable
--
-- Serializing Haskell values to and from MessagePack Objects.
--
--------------------------------------------------------------------
module Data.MessagePack.Class(
-- * Serialization to and from Object
OBJECT(..),
Result,
pack,
) where
import Control.Monad.Error
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as C8
import Data.MessagePack.Base
-- | The class of types serializable to and from MessagePack object
class OBJECT a where
toObject :: a -> Object
fromObject :: Object -> Result a
-- | A type for parser results
type Result a = Either String a
instance OBJECT Object where
toObject = id
fromObject = Right
fromObjectError :: String
fromObjectError = "fromObject: cannot cast"
instance OBJECT () where
toObject = const ObjectNil
fromObject ObjectNil = Right ()
fromObject _ = Left fromObjectError
instance OBJECT Int where
toObject = ObjectInteger
fromObject (ObjectInteger n) = Right n
fromObject _ = Left fromObjectError
instance OBJECT Bool where
toObject = ObjectBool
fromObject (ObjectBool b) = Right b
fromObject _ = Left fromObjectError
instance OBJECT Double where
toObject = ObjectDouble
fromObject (ObjectDouble d) = Right d
fromObject _ = Left fromObjectError
instance OBJECT ByteString where
toObject = ObjectRAW
fromObject (ObjectRAW bs) = Right bs
fromObject _ = Left fromObjectError
instance OBJECT String where
toObject = toObject . C8.pack
fromObject obj = liftM C8.unpack $ fromObject obj
instance OBJECT a => OBJECT [a] where
toObject = ObjectArray . map toObject
fromObject (ObjectArray arr) =
mapM fromObject arr
fromObject _ =
Left fromObjectError
instance (OBJECT a, OBJECT b) => OBJECT [(a, b)] where
toObject =
ObjectMap . map (\(a, b) -> (toObject a, toObject b))
fromObject (ObjectMap mem) = do
mapM (\(a, b) -> liftM2 (,) (fromObject a) (fromObject b)) mem
fromObject _ =
Left fromObjectError
instance OBJECT a => OBJECT (Maybe a) where
toObject (Just a) = toObject a
toObject Nothing = ObjectNil
fromObject ObjectNil = return Nothing
fromObject obj = liftM Just $ fromObject obj
-- | Pack a serializable Haskell value.
pack :: OBJECT a => Packer -> a -> IO ()
pack pc = packObject pc . toObject

Some files were not shown because too many files have changed in this diff Show More