File: socket_stream_example.cpp

package info (click to toggle)
msgpack-cxx 7.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 8,520 kB
  • sloc: cpp: 87,413; ansic: 3,571; sh: 56; makefile: 39
file content (157 lines) | stat: -rw-r--r-- 4,078 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <iostream>
#include <sstream>
#include <msgpack.hpp>

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"<<std::endl;
    }
    void insufficient_bytes(size_t /*parsed_offset*/, size_t /*error_offset*/) {
        std::cout << "insufficient bytes"<<std::endl;
    }
    std::string& m_s;

    // These two functions are required by parser.
    void set_referenced(bool ref) { m_ref = ref; }
    bool referenced() const { return m_ref; }
    bool m_ref;
};

struct do_nothing {
    void operator()(char* /*buffer*/) {
    }
};

class json_like_printer : public msgpack::parser<json_like_printer, do_nothing>,
                          public json_like_visitor {
    typedef parser<json_like_printer, do_nothing> 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 <typename T>
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 = static_cast<std::size_t>(ss.gcount());
    return (size > 0);
}

//shows how you can treat data 
void consume( const char* buff, const std::size_t size, 
    ref_buffer<json_like_printer> & 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<std::vector<int>> vvi1 { { 1,2,3,4,5}, { 6,7,8,9,10} }; 
    std::vector<std::vector<int>> 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<json_like_printer> rb(jp);

    while( produce(ss,buffer,size) )
    {
        consume(buffer, size, rb, jp);
    }

}