Created
June 28, 2014 16:14
-
-
Save redboltz/672c5af16b2907488977 to your computer and use it in GitHub Desktop.
msgpack-c boost::variant example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.