Skip to content

Instantly share code, notes, and snippets.

@redboltz
Created June 28, 2014 16:14
Show Gist options
  • Save redboltz/672c5af16b2907488977 to your computer and use it in GitHub Desktop.
Save redboltz/672c5af16b2907488977 to your computer and use it in GitHub Desktop.
msgpack-c boost::variant example
#include <boost/variant.hpp>
#include <msgpack.hpp>
// Definition of the variant type.
// The types appear the following example are supported.
// {'metadata': {'date': '2014-06-25', 'user_id': 501},
// 'values': [3.1, 4.1, 5.1],
// 'version': 1}
typedef boost::make_recursive_variant<
std::string,
std::map<boost::recursive_variant_, boost::recursive_variant_>,
std::vector<boost::recursive_variant_>,
int,
double
>::type variant_t;
// An example of the application using variant_t.
void print(variant_t const& v) {
struct printer:boost::static_visitor<void> {
void operator()(int value) const {
std::cout << value;
}
void operator()(double value) const {
std::cout << value;
}
void operator()(std::string const& value) const {
std::cout << "'" << value << "'";
}
void operator()(std::vector<variant_t> const& value) const {
bool first(true);
std::cout << '[';
for (auto const& v : value) {
if (first) first = false;
else std::cout << ',';
boost::apply_visitor(*this, v);
}
std::cout << ']';
}
void operator()(std::map<variant_t, variant_t> const& value) const {
bool first(true);
std::cout << '{';
for (auto const& v : value) {
if (first) first = false;
else std::cout << ',';
boost::apply_visitor(*this, v.first);
std::cout << ':';
boost::apply_visitor(*this, v.second);
}
std::cout << '}';
}
};
boost::apply_visitor(printer(), v);
std::cout << std::endl;
}
// Custom converter for variant_t
namespace msgpack {
// Convert from msgpacl::object to variant_t.
inline variant_t& operator>>(object const& o, variant_t& v) {
switch(o.type) {
case type::MAP:
v = std::map<variant_t, variant_t>();
o.convert(boost::get<std::map<variant_t, variant_t> >(&v));
break;
case type::ARRAY:
v = std::vector<variant_t>();
o.convert(boost::get<std::vector<variant_t> >(&v));
break;
case type::POSITIVE_INTEGER:
v = int();
o.convert(boost::get<int>(&v));
break;
case type::DOUBLE:
v = double();
o.convert(boost::get<double>(&v));
break;
case type::RAW:
v = std::string();
o.convert(boost::get<std::string>(&v));
break;
default:
break;
}
return v;
}
// Convert from variant_t to msgpacl::object.
template <typename Stream>
struct packer_imp:boost::static_visitor<void> {
template <typename T>
void operator()(T const& value) const {
o_.pack(value);
}
packer_imp(packer<Stream>& o):o_(o) {}
packer<Stream>& o_;
};
template <typename Stream>
inline packer<Stream>& operator<< (packer<Stream>& o, const variant_t& v)
{
boost::apply_visitor(packer_imp<Stream>(o), v);
return o;
}
} // namespace msgpack
void test() {
// Pack from variant type.
variant_t v =
std::map<variant_t, variant_t>({
{
"metadata",
std::map<variant_t, variant_t>({
{ "date", "2014-06-25" },
{ "user_id", 501 }
})
},
{
"values", std::vector<variant_t>({ 3.1, 4.1, 5.1 })
},
{
"version", 1
}
});
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, v);
// Unpack to variant type.
msgpack::unpacker unp;
unp.reserve_buffer(sbuf.size());
memcpy(unp.buffer(), sbuf.data(), sbuf.size());
unp.buffer_consumed(sbuf.size());
msgpack::unpacked result;
while(bool ret = unp.next(&result)) {
std::cout << "ret:" << std::boolalpha << ret << std::endl;
msgpack::object const& obj = result.get();
std::cout << obj << std::endl;
variant_t v;
obj.convert(&v);
print(v);
}
}
int main() {
test();
}
@brainstormot
Copy link

Thanks for your helpful code.
But I have some error when I compile your code.
It seem like most of them is due to my low compiler version.
(I cannot avoid using g++ 4.1.2 and boost 1.5.3)

What I wonder is line 56 "boost::apply_visitor(*this, v);".

It also invoked error but I cannot figure out if it is caused by version difference or not.

With my compiler, 'apply_visitor' didn't allow 'variant_t' type. (make error)
but it allowed every other types like int, string, etc...

In your codes, 'v' is 'variant_t' or 'variant_t&' , isn't it?

I am sorry for poor English.
Thanks for any advise.

@brainstormot
Copy link

I solved it , never mind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment