1#include <msgpack.h>
2#include <stdio.h>
3#include <assert.h>
4
5
6typedef struct receiver {
7    msgpack_sbuffer sbuf;
8    size_t rest;
9} receiver;
10
11void receiver_init(receiver *r) {
12    msgpack_packer pk;
13
14    msgpack_sbuffer_init(&r->sbuf);
15    msgpack_packer_init(&pk, &r->sbuf, msgpack_sbuffer_write);
16    /* 1st object */
17    msgpack_pack_array(&pk, 3);
18    msgpack_pack_int(&pk, 1);
19    msgpack_pack_true(&pk);
20    msgpack_pack_str(&pk, 7);
21    msgpack_pack_str_body(&pk, "example", 7);
22    /* 2nd object */
23    msgpack_pack_str(&pk, 6);
24    msgpack_pack_str_body(&pk, "second", 6);
25    /* 3rd object */
26    msgpack_pack_array(&pk, 2);
27    msgpack_pack_int(&pk, 42);
28    msgpack_pack_false(&pk);
29    r->rest = r->sbuf.size;
30}
31
32size_t receiver_recv(receiver *r, char* buf, size_t try_size) {
33    size_t off = r->sbuf.size - r->rest;
34
35    size_t actual_size = try_size;
36    if (actual_size > r->rest) actual_size = r->rest;
37
38    memcpy(buf, r->sbuf.data + off, actual_size);
39    r->rest -= actual_size;
40
41    return actual_size;
42}
43
44size_t receiver_to_unpacker(receiver* r, size_t request_size,
45        msgpack_unpacker *unpacker)
46{
47    // make sure there's enough room, or expand the unpacker accordingly
48    if (msgpack_unpacker_buffer_capacity(unpacker) < request_size) {
49        msgpack_unpacker_reserve_buffer(unpacker, request_size);
50        assert(msgpack_unpacker_buffer_capacity(unpacker) >= request_size);
51    }
52    size_t recv_len = receiver_recv(r, msgpack_unpacker_buffer(unpacker),
53                                    request_size);
54    msgpack_unpacker_buffer_consumed(unpacker, recv_len);
55    return recv_len;
56}
57
58#define EACH_RECV_SIZE 4
59
60void unpack(receiver* r) {
61    /* buf is allocated by unpacker. */
62    msgpack_unpacker* unp = msgpack_unpacker_new(100);
63    msgpack_unpacked result;
64    msgpack_unpack_return ret;
65    size_t recv_len;
66    int recv_count = 0;
67    int i = 0;
68
69    msgpack_unpacked_init(&result);
70    while (true) {
71        recv_len = receiver_to_unpacker(r, EACH_RECV_SIZE, unp);
72        if (recv_len == 0) break; // (reached end of input)
73        printf("receive count: %d %zd bytes received.\n", recv_count++, recv_len);
74        ret = msgpack_unpacker_next(unp, &result);
75        while (ret == MSGPACK_UNPACK_SUCCESS) {
76            msgpack_object obj = result.data;
77
78            /* Use obj. */
79            printf("Object no %d:\n", ++i);
80            msgpack_object_print(stdout, obj);
81            printf("\n");
82            /* If you want to allocate something on the zone, you can use zone. */
83            /* msgpack_zone* zone = result.zone; */
84            /* The lifetime of the obj and the zone,  */
85
86            ret = msgpack_unpacker_next(unp, &result);
87        }
88        if (ret == MSGPACK_UNPACK_PARSE_ERROR) {
89            printf("The data in the buf is invalid format.\n");
90            msgpack_unpacked_destroy(&result);
91            return;
92        }
93    }
94    msgpack_unpacked_destroy(&result);
95    msgpack_unpacker_free(unp);
96}
97
98int main(void) {
99    receiver r;
100    receiver_init(&r);
101
102    unpack(&r);
103
104    return 0;
105}
106
107/* Output */
108
109/*
110receive count: 0 4 bytes received.
111receive count: 1 4 bytes received.
112receive count: 2 4 bytes received.
113Object no 1:
114[1, true, "example"]
115receive count: 3 4 bytes received.
116receive count: 4 4 bytes received.
117Object no 2:
118"second"
119receive count: 5 1 bytes received.
120Object no 3:
121[42, false]
122*/
123