mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-20 22:31:33 +02:00
Compare commits
431 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0c331d2887 | ||
![]() |
39facd5dc6 | ||
![]() |
a2bd5ae638 | ||
![]() |
c57f616141 | ||
![]() |
3af10a1d00 | ||
![]() |
b3987e2402 | ||
![]() |
71dd44f430 | ||
![]() |
584462f9b9 | ||
![]() |
ff5d5d7cbc | ||
![]() |
370e92b1a6 | ||
![]() |
2469768a85 | ||
![]() |
acb8fa613e | ||
![]() |
83b4b7d83d | ||
![]() |
20de730541 | ||
![]() |
134c27c900 | ||
![]() |
123ae024c6 | ||
![]() |
34a29cd0a5 | ||
![]() |
9fffa9800a | ||
![]() |
358457f49d | ||
![]() |
90e305d789 | ||
![]() |
b471e52e28 | ||
![]() |
9b5fc37399 | ||
![]() |
537322e3b5 | ||
![]() |
279121f87f | ||
![]() |
a1b2b41cdc | ||
![]() |
0cca90c21d | ||
![]() |
ad052cb510 | ||
![]() |
57f0598373 | ||
![]() |
92d192277e | ||
![]() |
2cdfbd8970 | ||
![]() |
bc0c5f0cdc | ||
![]() |
230ee3a03b | ||
![]() |
ab0bf37d30 | ||
![]() |
b1e66256ce | ||
![]() |
fd80693420 | ||
![]() |
f222f5ed9b | ||
![]() |
59603b902a | ||
![]() |
82a5dd6cf9 | ||
![]() |
a97f9081a3 | ||
![]() |
b3e0ad1303 | ||
![]() |
251090406a | ||
![]() |
9c3ed173b1 | ||
![]() |
7cd41aeb72 | ||
![]() |
8ecaf7ad4c | ||
![]() |
d4049fe593 | ||
![]() |
989b14b519 | ||
![]() |
fb3e11408c | ||
![]() |
3d3af3284e | ||
![]() |
eabcf15790 | ||
![]() |
684bca203a | ||
![]() |
d42ecccf6f | ||
![]() |
5a92c861e3 | ||
![]() |
103b14ea3c | ||
![]() |
e49f091b4e | ||
![]() |
6056f93910 | ||
![]() |
18fa2d1af4 | ||
![]() |
062ed8a4c4 | ||
![]() |
49f3872d04 | ||
![]() |
d9b467098a | ||
![]() |
7d1e51437e | ||
![]() |
f5a7d444e2 | ||
![]() |
a0071c2f9f | ||
![]() |
98a5e43883 | ||
![]() |
f40ebe5b43 | ||
![]() |
d7d78d9a2b | ||
![]() |
5a12d36a0a | ||
![]() |
e61dc76ae1 | ||
![]() |
0da22193bd | ||
![]() |
d43921823e | ||
![]() |
6b5b76b0c9 | ||
![]() |
602971408b | ||
![]() |
2f5d83f07d | ||
![]() |
81b0c316cd | ||
![]() |
6df86384ca | ||
![]() |
3fbcde4bd7 | ||
![]() |
293293c23c | ||
![]() |
47185d757e | ||
![]() |
94c3998507 | ||
![]() |
5fa589691c | ||
![]() |
26bc835c7e | ||
![]() |
fc7da17fa2 | ||
![]() |
dbebe9771b | ||
![]() |
d0af8aa9f1 | ||
![]() |
f8173e93f5 | ||
![]() |
fa6ea6848f | ||
![]() |
5982970e21 | ||
![]() |
c43e5e0c95 | ||
![]() |
b4fc79c38e | ||
![]() |
b9cb270b8f | ||
![]() |
1fe35d7efe | ||
![]() |
ec8c19b1f0 | ||
![]() |
c2525bcc05 | ||
![]() |
985c31b378 | ||
![]() |
135a9f5586 | ||
![]() |
979ff80982 | ||
![]() |
6cde9f3a9d | ||
![]() |
5cad81bf4c | ||
![]() |
18967162cf | ||
![]() |
6ea75f3a9f | ||
![]() |
f51123d009 | ||
![]() |
be6376ee2d | ||
![]() |
120a85a3e5 | ||
![]() |
262fe96c29 | ||
![]() |
1864df5ed0 | ||
![]() |
09bae0a9e8 | ||
![]() |
ebe41a24f1 | ||
![]() |
f0f574a15b | ||
![]() |
9420436c09 | ||
![]() |
2b8f853b96 | ||
![]() |
2c2bf60d0c | ||
![]() |
62b82448d5 | ||
![]() |
2f12e6c3d0 | ||
![]() |
8ce23f8e3e | ||
![]() |
dbe760d6e2 | ||
![]() |
674c26d9c7 | ||
![]() |
7b68b04efd | ||
![]() |
e0b65bf196 | ||
![]() |
77f5cb1f1f | ||
![]() |
2a222737f8 | ||
![]() |
77d48f9cee | ||
![]() |
c77eac325e | ||
![]() |
517ced2a54 | ||
![]() |
70d2c47367 | ||
![]() |
e57084f6df | ||
![]() |
8783cf8ec3 | ||
![]() |
2af7a7c6ac | ||
![]() |
91a1f8d9e1 | ||
![]() |
fc5e8ddca1 | ||
![]() |
6352472c5f | ||
![]() |
833ee6484c | ||
![]() |
dda3d24bca | ||
![]() |
f77d76a320 | ||
![]() |
c51fabf6ed | ||
![]() |
b10cb658ca | ||
![]() |
68f60568ac | ||
![]() |
9fbca83ac0 | ||
![]() |
d19bfaa2cb | ||
![]() |
53d5ddb345 | ||
![]() |
0a5c2e7ab9 | ||
![]() |
35802ba949 | ||
![]() |
72160aac9a | ||
![]() |
9df6916029 | ||
![]() |
9bfa2354ff | ||
![]() |
7d945d3c8e | ||
![]() |
05e28752f1 | ||
![]() |
01b6673528 | ||
![]() |
4e85ebbf98 | ||
![]() |
120e8bffd7 | ||
![]() |
8335823748 | ||
![]() |
c9fcf4020f | ||
![]() |
b10a736744 | ||
![]() |
60fbaf7612 | ||
![]() |
d24193630e | ||
![]() |
354af69f62 | ||
![]() |
bccac610a4 | ||
![]() |
5aa6209664 | ||
![]() |
d693d92702 | ||
![]() |
f2622e54e3 | ||
![]() |
20fe9b6dde | ||
![]() |
11f7aa4212 | ||
![]() |
f53c351fd2 | ||
![]() |
fb96617377 | ||
![]() |
05b8c00ee7 | ||
![]() |
58854fdae9 | ||
![]() |
fd31ff772f | ||
![]() |
ab8e0c9e31 | ||
![]() |
abeed3be84 | ||
![]() |
a65438c6fe | ||
![]() |
c3f43fb0cf | ||
![]() |
2807504a81 | ||
![]() |
08b716c96d | ||
![]() |
b4b1f0a2c9 | ||
![]() |
228f742b2f | ||
![]() |
a55affe4d5 | ||
![]() |
a6ec726ed7 | ||
![]() |
87835a4e60 | ||
![]() |
1f18af4395 | ||
![]() |
e79747a600 | ||
![]() |
bd36ac2c0c | ||
![]() |
c6186f2c01 | ||
![]() |
d639f57470 | ||
![]() |
99a2d28592 | ||
![]() |
254ee80c16 | ||
![]() |
e43f57fe1a | ||
![]() |
f88c029a4c | ||
![]() |
93c3cbeaef | ||
![]() |
88c77b793f | ||
![]() |
11286524a5 | ||
![]() |
7c863c341e | ||
![]() |
3416cf984e | ||
![]() |
1784746e7e | ||
![]() |
6c6df1adaf | ||
![]() |
f91e1c17c0 | ||
![]() |
58201b95f2 | ||
![]() |
fcce8f6d51 | ||
![]() |
f7bdda8828 | ||
![]() |
df5a60fd5b | ||
![]() |
5782ab7ccc | ||
![]() |
72e3f98213 | ||
![]() |
1b1433a664 | ||
![]() |
568704ed22 | ||
![]() |
05a7e4eb64 | ||
![]() |
7a0acf2838 | ||
![]() |
27787505e0 | ||
![]() |
2c8048115d | ||
![]() |
7df1780853 | ||
![]() |
d5609f3207 | ||
![]() |
cd10fbc1fe | ||
![]() |
ca0b085d15 | ||
![]() |
9a034234d8 | ||
![]() |
66ef6c9e4c | ||
![]() |
7df60b259b | ||
![]() |
34b3bbc883 | ||
![]() |
e02d20dd74 | ||
![]() |
1a11608f1f | ||
![]() |
9e2c9d7812 | ||
![]() |
404a393315 | ||
![]() |
c69092e110 | ||
![]() |
ebc0eeac79 | ||
![]() |
2b72f35c32 | ||
![]() |
d8212ad620 | ||
![]() |
1066bb38a8 | ||
![]() |
2bf3f1856f | ||
![]() |
f145129f6e | ||
![]() |
8d365458d5 | ||
![]() |
55cfbf378e | ||
![]() |
d76093b148 | ||
![]() |
7873e41e00 | ||
![]() |
9817e9b18d | ||
![]() |
519716bbe4 | ||
![]() |
c2dd22ec10 | ||
![]() |
232aced926 | ||
![]() |
63b9a876b0 | ||
![]() |
5cf85a82d3 | ||
![]() |
b9f78821d4 | ||
![]() |
f4c5b15cc6 | ||
![]() |
4d33bd456c | ||
![]() |
3a5f7f53ff | ||
![]() |
1ed4236bcf | ||
![]() |
5ff2c6be74 | ||
![]() |
dd18402737 | ||
![]() |
686e8ca0f0 | ||
![]() |
5aa47d6677 | ||
![]() |
0d44348c7d | ||
![]() |
35929b46ae | ||
![]() |
ba3ba0367c | ||
![]() |
7ce866ad7c | ||
![]() |
0ae1965f6b | ||
![]() |
eb9e892491 | ||
![]() |
e39e1d4f60 | ||
![]() |
93a95725fc | ||
![]() |
4758d9f04b | ||
![]() |
d39c016e1d | ||
![]() |
5393a0df16 | ||
![]() |
68176e10f5 | ||
![]() |
c6a2569af8 | ||
![]() |
3424dc916c | ||
![]() |
c8ad32a39e | ||
![]() |
d0b76814b0 | ||
![]() |
bf3cb63d46 | ||
![]() |
8da7b692f6 | ||
![]() |
320c79db49 | ||
![]() |
ebf64d9892 | ||
![]() |
c12d5b8461 | ||
![]() |
7186edc45e | ||
![]() |
c94772104d | ||
![]() |
9374571056 | ||
![]() |
c232e91f83 | ||
![]() |
5b8777026a | ||
![]() |
51e435d46c | ||
![]() |
d3f9ab7dec | ||
![]() |
1ba330c473 | ||
![]() |
dba7f480ed | ||
![]() |
3a39accb0b | ||
![]() |
387eca6fbf | ||
![]() |
b2381d0513 | ||
![]() |
92952f6566 | ||
![]() |
a62a5d6c69 | ||
![]() |
0627324da6 | ||
![]() |
394331cd4e | ||
![]() |
0491768fb2 | ||
![]() |
a5705183d6 | ||
![]() |
95a6316cc7 | ||
![]() |
be32e3b1fb | ||
![]() |
b4cb5e23c0 | ||
![]() |
1375732c80 | ||
![]() |
7fbe845434 | ||
![]() |
3afa9f265e | ||
![]() |
ec8932d6a1 | ||
![]() |
f7a9805f7b | ||
![]() |
aaef612a05 | ||
![]() |
da9b75f553 | ||
![]() |
d3906bd1ab | ||
![]() |
4db90d23ac | ||
![]() |
bb455c1f71 | ||
![]() |
3275eee281 | ||
![]() |
0fe79a7752 | ||
![]() |
794adf9469 | ||
![]() |
718227bc2c | ||
![]() |
390c5ad8a0 | ||
![]() |
2da4b17d0b | ||
![]() |
d19c488929 | ||
![]() |
0db5e0439d | ||
![]() |
6083bad5ff | ||
![]() |
63a507a123 | ||
![]() |
294e3fe7ab | ||
![]() |
e5c49dae13 | ||
![]() |
900785e1aa | ||
![]() |
979efbb950 | ||
![]() |
7da1a9b3cf | ||
![]() |
661f273481 | ||
![]() |
cb5c878b77 | ||
![]() |
34ed3bc9e3 | ||
![]() |
ad7cf12128 | ||
![]() |
6fb6283463 | ||
![]() |
b45dc8db61 | ||
![]() |
3397d261d8 | ||
![]() |
eaa8be8ddd | ||
![]() |
0f9dcb8610 | ||
![]() |
3446c475d7 | ||
![]() |
ffef0a0b6f | ||
![]() |
580fbe77e9 | ||
![]() |
e92e99c4d1 | ||
![]() |
c3f793aa09 | ||
![]() |
3d9908c8e5 | ||
![]() |
7b198d5966 | ||
![]() |
601209c83c | ||
![]() |
78db826a75 | ||
![]() |
c2a63b2c54 | ||
![]() |
7c27624161 | ||
![]() |
d86b90e663 | ||
![]() |
d72bef9f9a | ||
![]() |
37972dfe3e | ||
![]() |
c6496ddf13 | ||
![]() |
a95e8c790c | ||
![]() |
03942a1b90 | ||
![]() |
d4317fdc85 | ||
![]() |
b5010c71a9 | ||
![]() |
9015bd4ecf | ||
![]() |
fe2421275d | ||
![]() |
257270c1eb | ||
![]() |
0b33a634a6 | ||
![]() |
3e396ef146 | ||
![]() |
1b07b61c04 | ||
![]() |
fa2efcdb5b | ||
![]() |
a345131aaa | ||
![]() |
ffc16736ba | ||
![]() |
3c3df3133c | ||
![]() |
16a208243b | ||
![]() |
dd407410d2 | ||
![]() |
8f52ed26c7 | ||
![]() |
479263989b | ||
![]() |
87e1adcb40 | ||
![]() |
8e166de1d1 | ||
![]() |
3aef3edbad | ||
![]() |
b2fdaac99e | ||
![]() |
9a342ab7f8 | ||
![]() |
8596d36d02 | ||
![]() |
423e5132a1 | ||
![]() |
1581acfd14 | ||
![]() |
5d4189306a | ||
![]() |
f61b282886 | ||
![]() |
3fd28d0792 | ||
![]() |
dd53b141ef | ||
![]() |
99d0a41ec6 | ||
![]() |
b8e5b918a3 | ||
![]() |
71af62c1df | ||
![]() |
7d5f04917e | ||
![]() |
46d7c65621 | ||
![]() |
87f5df1503 | ||
![]() |
9a77ab57f6 | ||
![]() |
20a7ff0be8 | ||
![]() |
075081a521 | ||
![]() |
f4387e9746 | ||
![]() |
0d14239c21 | ||
![]() |
2475187c7d | ||
![]() |
4d6e9ffaa2 | ||
![]() |
6184e17a42 | ||
![]() |
e814986b4e | ||
![]() |
3a9f74e79c | ||
![]() |
a1fb1507d4 | ||
![]() |
85ca594118 | ||
![]() |
9c9393bff9 | ||
![]() |
560bd901f8 | ||
![]() |
114ef92d42 | ||
![]() |
1840ef70ae | ||
![]() |
935db853f0 | ||
![]() |
17d2ca2d63 | ||
![]() |
c930f5367b | ||
![]() |
d8a3bc920c | ||
![]() |
711e4817a5 | ||
![]() |
7cd359c1fd | ||
![]() |
2598d98922 | ||
![]() |
8617213149 | ||
![]() |
3628ea22d4 | ||
![]() |
6a0729ea91 | ||
![]() |
b0062a7f6f | ||
![]() |
b140b27b9a | ||
![]() |
e0bd2a2911 | ||
![]() |
ea41db4cc7 | ||
![]() |
5a201be844 | ||
![]() |
28e113fd00 | ||
![]() |
5710b87b06 | ||
![]() |
8c62d93bca | ||
![]() |
b8cc8b72bd | ||
![]() |
cc7379d532 | ||
![]() |
163fc6f589 | ||
![]() |
c7f193e441 | ||
![]() |
09978e500a | ||
![]() |
2fad10ca3f | ||
![]() |
e707b7a600 | ||
![]() |
e7403013e5 | ||
![]() |
c3f9696268 | ||
![]() |
cb24a0c24f | ||
![]() |
0efb8160b9 | ||
![]() |
bf13ba72b5 | ||
![]() |
6fc38d1669 | ||
![]() |
879c70f93a | ||
![]() |
6fda01111e | ||
![]() |
4f4fa39cd5 | ||
![]() |
c60b6be548 | ||
![]() |
9b4b49a6a8 | ||
![]() |
c0baf9b873 | ||
![]() |
65ef9cab66 | ||
![]() |
6ffee9e54a | ||
![]() |
43360e3786 | ||
![]() |
4d708aa4da | ||
![]() |
5d51129e65 | ||
![]() |
a0b82e39e1 | ||
![]() |
9642368835 | ||
![]() |
cbf7afc1cc |
48
Makefile.am
48
Makefile.am
@@ -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
72
README
@@ -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
37
README.md
Normal 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
|
||||
|
||||

|
||||
|
||||
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)
|
||||
|
@@ -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
323
c/bench.c
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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 $@
|
||||
|
125
c/unpack.h
125
c/unpack.h
@@ -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 */
|
||||
|
135
c/vrefbuffer.c
135
c/vrefbuffer.c
@@ -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);
|
||||
}
|
||||
}
|
||||
|
44
configure.in
44
configure.in
@@ -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])
|
||||
|
@@ -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.
|
20
cpp/ChangeLog
Normal file
20
cpp/ChangeLog
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
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
1552
cpp/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
|
78
cpp/README.md
Normal file
78
cpp/README.md
Normal 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.
|
||||
|
188
cpp/bench.cpp
188
cpp/bench.cpp
@@ -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;
|
||||
}
|
||||
|
@@ -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 $@
|
||||
|
@@ -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"
|
72
cpp/configure.in
Normal file
72
cpp/configure.in
Normal file
@@ -0,0 +1,72 @@
|
||||
AC_INIT(src/object.cpp)
|
||||
AC_CONFIG_AUX_DIR(ac)
|
||||
AM_INIT_AUTOMAKE(msgpack, 0.5.1)
|
||||
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 test/Makefile])
|
||||
|
@@ -1 +0,0 @@
|
||||
.
|
44
cpp/msgpack_vc8.postbuild.bat
Normal file
44
cpp/msgpack_vc8.postbuild.bat
Normal 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
20
cpp/msgpack_vc8.sln
Normal 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
299
cpp/msgpack_vc8.vcproj
Normal 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
31
cpp/preprocess
Executable 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/
|
||||
|
107
cpp/src/Makefile.am
Normal file
107
cpp/src/Makefile.am
Normal file
@@ -0,0 +1,107 @@
|
||||
|
||||
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
|
||||
|
||||
|
||||
msgpack/version.h: msgpack/version.h.in Makefile.in
|
||||
sed -e s/VERSION_UNDEFINED/$(VERSION)/ \
|
||||
-e s/VERSION_MAJOR_UNDEFINED/$(VERSION_MAJOR)/ \
|
||||
-e s/VERSION_MINOR_UNDEFINED/$(VERSION_MINOR)/ \
|
||||
$< > $@
|
||||
|
||||
|
||||
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
|
||||
|
@@ -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"
|
||||
|
@@ -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
|
||||
}
|
@@ -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:
|
@@ -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
|
@@ -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>
|
@@ -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
|
||||
}
|
@@ -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
15
cpp/src/msgpack/type.hpp
Normal 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"
|
||||
|
@@ -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
|
||||
|
117
cpp/src/msgpack/type/define.hpp.erb
Normal file
117
cpp/src/msgpack/type/define.hpp.erb
Normal 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 */
|
||||
|
77
cpp/src/msgpack/type/deque.hpp
Normal file
77
cpp/src/msgpack/type/deque.hpp
Normal 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 */
|
||||
|
@@ -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 */
|
@@ -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 */
|
||||
|
@@ -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 */
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
61
cpp/src/msgpack/type/pair.hpp
Normal file
61
cpp/src/msgpack/type/pair.hpp
Normal 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 */
|
||||
|
@@ -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
|
||||
|
122
cpp/src/msgpack/type/set.hpp
Normal file
122
cpp/src/msgpack/type/set.hpp
Normal 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 */
|
||||
|
62
cpp/src/msgpack/type/string.hpp
Normal file
62
cpp/src/msgpack/type/string.hpp
Normal 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 */
|
||||
|
129
cpp/src/msgpack/type/tr1/unordered_map.hpp
Normal file
129
cpp/src/msgpack/type/tr1/unordered_map.hpp
Normal 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 */
|
||||
|
122
cpp/src/msgpack/type/tr1/unordered_set.hpp
Normal file
122
cpp/src/msgpack/type/tr1/unordered_set.hpp
Normal 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 */
|
||||
|
@@ -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 */
|
||||
|
81
cpp/src/msgpack/type/vector.hpp
Normal file
81
cpp/src/msgpack/type/vector.hpp
Normal 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
260
cpp/src/msgpack/unpack.h
Normal 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 */
|
||||
|
@@ -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)
|
||||
{
|
40
cpp/src/msgpack/version.h.in
Normal file
40
cpp/src/msgpack/version.h.in
Normal 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_UNDEFINED"
|
||||
#define MSGPACK_VERSION_MAJOR VERSION_MAJOR_UNDEFINED
|
||||
#define MSGPACK_VERSION_MINOR VERSION_MINOR_UNDEFINED
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* msgpack/version.h */
|
||||
|
@@ -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
|
@@ -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
207
cpp/src/msgpack/zbuffer.h
Normal 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
100
cpp/src/msgpack/zbuffer.hpp
Normal 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 */
|
||||
|
@@ -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;
|
||||
}
|
@@ -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|%>
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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
17
cpp/src/version.c
Normal 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
220
cpp/src/vrefbuffer.c
Normal 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;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
201
cpp/test.cpp
201
cpp/test.cpp
@@ -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;
|
||||
}
|
||||
|
@@ -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
48
cpp/test/Makefile.am
Normal 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
75
cpp/test/buffer.cc
Normal 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
36
cpp/test/cases.cc
Normal 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
74
cpp/test/convert.cc
Normal 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
982
cpp/test/msgpack_test.cpp
Normal 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
424
cpp/test/msgpackc_test.cpp
Normal 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
134
cpp/test/object.cc
Normal 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
123
cpp/test/pack_unpack.cc
Normal 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
70
cpp/test/pack_unpack_c.cc
Normal 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
220
cpp/test/streaming.cc
Normal 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
57
cpp/test/streaming_c.cc
Normal 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
13
cpp/test/version.cc
Normal 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
78
cpp/test/zone.cc
Normal 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);
|
||||
}
|
||||
|
@@ -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
4
erlang/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
MANIFEST
|
||||
*.beam
|
||||
.omakedb*
|
||||
*.omc
|
42
erlang/OMakefile
Normal file
42
erlang/OMakefile
Normal 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
45
erlang/OMakeroot
Normal 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
9
erlang/README.md
Normal 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
362
erlang/msgpack.erl
Normal 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.
|
65
erlang/testcase_generator.rb
Normal file
65
erlang/testcase_generator.rb
Normal 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
58
example/custom.cc
Normal 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;
|
||||
}
|
||||
}
|
||||
|
@@ -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
24
haskell/LICENSE
Normal 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
3
haskell/Setup.lhs
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env runhaskell
|
||||
> import Distribution.Simple
|
||||
> main = defaultMain
|
137
haskell/cbits/msgpack.c
Normal file
137
haskell/cbits/msgpack.c
Normal 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
32
haskell/msgpack.cabal
Normal 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
|
63
haskell/src/Data/MessagePack.hs
Normal file
63
haskell/src/Data/MessagePack.hs
Normal 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
|
584
haskell/src/Data/MessagePack/Base.hsc
Normal file
584
haskell/src/Data/MessagePack/Base.hsc
Normal 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
|
101
haskell/src/Data/MessagePack/Class.hs
Normal file
101
haskell/src/Data/MessagePack/Class.hs
Normal 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
Reference in New Issue
Block a user