问题
I am trying to use msgpack (in c version, not c++) to replace our own serialization method, which is in primary xml based. It is quite straight forward to pack some ordinary data. However, we have a lot of k-v based structures like
struct Table {
struct Key {
// Multi-keys
int key1;
int key2;
};
struct Attr {
// Attributes
int attr1;
bool attr2;
char[8] attr3;
};
}
How to pack multi-key table with msg_pack_map in msgpack-c? (unfortunately, our system is exception disabled, so I cannot use the c++ version "msgpack.hpp")
my code snippet:
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
msgpack_packer pk;
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
msgpack_packer_map(&pk, 10) // 10 pairs
for(int i= 0; i<10; ++i) {
// key
msgpack_pack_array(&pk, 2);
msgpack_pack_int(&pk, i);
msgpack_pack_int(&pk, 100+i);
// attr
msgpack_pack_array(&pk, 3);
msgpack_pack_int(&pk, 1);
msgpack_pack_true(&pk);
msgpack_pack_str(&pk, 7);
msgpack_pack_str_body(&pk, "example");
}
I assume in msgpack, we have to use msgpack_pack_array to pack struct.
Is my code right, or is there any better way to do that?
回答1:
Yes, you are right. There are two subtle mistake in your code snippet. msgpack_packer_map should be msgpack_pack_map. msgpack_pack_str_body requires a length of the string as the third argument.
I updated your code snippet, and added test codes.
See:
http://melpon.org/wandbox/permlink/RuZKLmzwStHej5TP
#include <msgpack.h>
#include <msgpack.hpp>
#include <map>
#include <iostream>
struct Key {
// Multi-keys
int key1;
int key2;
MSGPACK_DEFINE(key1, key2);
};
inline bool operator<(Key const& lhs, Key const& rhs) {
if (lhs.key1 < rhs.key1) return true;
if (lhs.key1 > rhs.key1) return false;
if (lhs.key2 < rhs.key2) return true;
return false;
}
struct Attr {
// Attributes
int attr1;
bool attr2;
std::string attr3;
MSGPACK_DEFINE(attr1, attr2, attr3);
};
int main() {
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
msgpack_packer pk;
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
msgpack_pack_map(&pk, 10); // 10 pairs
for(int i= 0; i<10; ++i) {
// key
msgpack_pack_array(&pk, 2);
msgpack_pack_int(&pk, i);
msgpack_pack_int(&pk, 100+i);
// attr
msgpack_pack_array(&pk, 3);
msgpack_pack_int(&pk, 1);
msgpack_pack_true(&pk);
msgpack_pack_str(&pk, 7);
msgpack_pack_str_body(&pk, "example", 7);
}
{
auto upd = msgpack::unpack(sbuf.data, sbuf.size);
std::cout << upd.get() << std::endl;
auto tbl = upd.get().as<std::map<Key, Attr>>();
}
msgpack_sbuffer_destroy(&sbuf);
}
That is a c++ code but I use C API in the packing part. You can check the unpacked msgpack object. It is also converted as C++ map successfully.
Here is C API documentation: https://github.com/msgpack/msgpack-c/wiki/v1_1_c_overview
来源:https://stackoverflow.com/questions/33737992/how-to-pack-multi-key-map-with-msgpack-c