From 9c77a0f24a14acc83b3e590e36578c4565f7121f Mon Sep 17 00:00:00 2001 From: pmalhaire Date: Wed, 30 Nov 2016 10:28:57 +0100 Subject: [PATCH] Adding an example of sax like parser using buffered content (could be a socket) --- example/cpp11/CMakeLists.txt | 1 + example/cpp11/socket_stream_example.cpp | 157 ++++++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 example/cpp11/socket_stream_example.cpp diff --git a/example/cpp11/CMakeLists.txt b/example/cpp11/CMakeLists.txt index 994f114d..43816cbc 100644 --- a/example/cpp11/CMakeLists.txt +++ b/example/cpp11/CMakeLists.txt @@ -6,6 +6,7 @@ IF (MSGPACK_CXX11) LIST (APPEND exec_PROGRAMS container.cpp non_def_con_class.cpp + socket_stream_example.cpp ) FOREACH (source_file ${exec_PROGRAMS}) diff --git a/example/cpp11/socket_stream_example.cpp b/example/cpp11/socket_stream_example.cpp new file mode 100644 index 00000000..b81c43f0 --- /dev/null +++ b/example/cpp11/socket_stream_example.cpp @@ -0,0 +1,157 @@ +#include +#include +#include + +struct json_like_visitor : msgpack::v2::null_visitor { + json_like_visitor(std::string& s):m_s(s), m_ref(false) {} // m_ref is false by default + + bool visit_nil() { + m_s += "null"; + return true; + } + bool visit_boolean(bool v) { + if (v) m_s += "true"; + else m_s += "false"; + return true; + } + bool visit_positive_integer(uint64_t v) { + std::stringstream ss; + ss << v; + m_s += ss.str(); + return true; + } + bool visit_negative_integer(int64_t v) { + std::stringstream ss; + ss << v; + m_s += ss.str(); + return true; + } + bool visit_str(const char* v, uint32_t size) { + // I omit escape process. + m_s += '"' + std::string(v, size) + '"'; + return true; + } + bool start_array(uint32_t /*num_elements*/) { + m_s += "["; + return true; + } + bool end_array_item() { + m_s += ","; + return true; + } + bool end_array() { + m_s.erase(m_s.size() - 1, 1); // remove the last ',' + m_s += "]"; + return true; + } + bool start_map(uint32_t /*num_kv_pairs*/) { + m_s += "{"; + return true; + } + bool end_map_key() { + m_s += ":"; + return true; + } + bool end_map_value() { + m_s += ","; + return true; + } + bool end_map() { + m_s.erase(m_s.size() - 1, 1); // remove the last ',' + m_s += "}"; + return true; + } + void parse_error(size_t /*parsed_offset*/, size_t /*error_offset*/) { + std::cerr << "parse error"<, + public json_like_visitor { + typedef parser parser_t; +public: + json_like_printer(std::size_t initial_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE) + :parser_t(do_nothing_, initial_buffer_size), + json_like_visitor(json_str_) { + } + + json_like_visitor& visitor() { return *this; } + void print() { std::cout << json_str_ << std::endl; json_str_.clear();} +private: + do_nothing do_nothing_; + std::string json_str_; +}; + +template +struct ref_buffer { + ref_buffer(T& t):t(t) {} + void write(char const* ptr, std::size_t len) { + if (len > t.buffer_capacity()) { + t.reserve_buffer(len - t.buffer_capacity()); + } + std::memcpy(t.buffer(), ptr, len); + t.buffer_consumed(len); + } + T& t; +}; + +#define BUFFERING_SIZE_MAX 100 + +//simulates streamed content (a socket for example) +bool produce( std::stringstream & ss, char* buff, std::size_t& size) +{ + ss.read(buff, BUFFERING_SIZE_MAX); + size = ss.gcount(); + return (size > 0); +} + +//shows how you can treat data +void consume( const char* buff, const std::size_t size, + ref_buffer & rb, + json_like_printer & jp + ) +{ + rb.write(buff,size); + while( jp.next() ) + { + //here we print the data, you could do any wanted processing + jp.print(); + } +} + +int main() { + + std::vector> vvi1 { { 1,2,3,4,5}, { 6,7,8,9,10} }; + std::vector> vvi2 { { 11,12,13,14,15}, { 16,17,18,19,20} }; + + std::stringstream ss; + + msgpack::pack(ss, vvi1); + msgpack::pack(ss, vvi2); + + char buffer[BUFFERING_SIZE_MAX]; + std::size_t size = 0; + + json_like_printer jp(1); // set initial buffer size explicitly + ref_buffer rb(jp); + + while( produce(ss,buffer,size) ) + { + consume(buffer, size, rb, jp); + } + +} \ No newline at end of file