MessagePack メモ
Python
help(msgpack) するとファイルライクオブジェクトに対して入出力する pack, unpack と、 Python 文字列を対象とする packb (= packs), unpackb (= unpacks) の説明あり。
import sys import msgpack msgpack.pack([1, True, 'example'], sys.stdout)
import sys import msgpack print msgpack.unpack(sys.stdin)
$ python write.py | python read.py [1, True, 'example']
しかしコードを斜め読みすると Packer, Unpacker というのもあった。こちらのほうが本命で pack, unpack はショートカット用かな。
import sys import msgpack packer = msgpack.Packer() sys.stdout.write(packer.pack([1, True, 'example'])) sys.stdout.write(packer.pack('spam')) sys.stdout.write(packer.pack(range(5))) sys.stdout.write(packer.pack({'a': 'b', 'c': 'd'}))
import sys import msgpack unpacker = msgpack.Unpacker() while True: buf = sys.stdin.read() if not buf: break unpacker.feed(buf) for obj in unpacker: print obj
$ python write2.py | python read2.py [1, True, 'example'] spam [0, 1, 2, 3, 4] {'a': 'b', 'c': 'd'}
Ruby
http://msgpack.sourceforge.net/ruby:snippets 。明日試してみる。 http://d.hatena.ne.jp/viver/20100324/p1 も読む。 Copy-on-Write によるゼロ・コピーデシリアライズ対応。
C
シリアライズ。 http://msgpack.sourceforge.net/c:snippets のまま。
#include <msgpack.h> #include <stdio.h> int main(void) { msgpack_sbuffer sbuf; msgpack_packer pk; msgpack_sbuffer_init(&sbuf); msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); msgpack_pack_array(&pk, 3); msgpack_pack_int(&pk, 1); msgpack_pack_true(&pk); msgpack_pack_raw(&pk, 7); msgpack_pack_raw_body(&pk, "example", 7); fwrite(sbuf.data, sbuf.size, 1, stdout); msgpack_sbuffer_destroy(&sbuf); return 0; }
デシリアライズ。 http://msgpack.sourceforge.net/c:snippets の改悪。 Advanced streaming deserialization も読む必要がありそうだがこれは明日に。
#include <msgpack.h> #include <stdio.h> int main(void) { msgpack_zone *mempool; msgpack_object obj; msgpack_unpack_return ret; size_t offset = 0; char buf[8192]; size_t size; size = fread(buf, 1, 8192, stdin); while (1) { mempool = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE); ret = msgpack_unpack(buf, size, &offset, mempool, &obj); switch(ret) { case MSGPACK_UNPACK_SUCCESS: printf("a object is unpacked and no buffer remain: "); msgpack_object_print(stdout, obj); printf("\n"); msgpack_zone_free(mempool); return 0; case MSGPACK_UNPACK_EXTRA_BYTES: printf("a object is unpacked: "); msgpack_object_print(stdout, obj); printf("\n"); msgpack_zone_free(mempool); break; case MSGPACK_UNPACK_CONTINUE: printf("buffer is to insufficient to unpack a object\n"); return 1; case MSGPACK_UNPACK_PARSE_ERROR: printf("parse error\n"); return 1; } } }
$ ./write | ./read a object is unpacked and no buffer remain: [1, true, "example"]
えっと、 msgpack_unpack の戻り値 MSGPACK_UNPACK_SUCCESS はぴったり読みきったことを示し MSGPACK_UNPACK_EXTRA_BYTES はまだデータが余っていることを示すのか。これは Python 版の Unpacker 同様、複数オブジェクトを詰め込んだファイルを綺麗に処理できる予感。 試してみる。
$ python write2.py | ./read a object is unpacked: [1, true, "example"] a object is unpacked: "spam" a object is unpacked: [0, 1, 2, 3, 4] a object is unpacked and no buffer remain: {"a"=>"b", "c"=>"d"}
うん、読めた。