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?
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