Added examples for the following updated functions:

msgpack_unpack_return msgpack_unpacker_next(msgpack_unpacker* mpac, msgpack_unpacked* result);

msgpack_unpack_return
msgpack_unpack_next(msgpack_unpacked* result,
        const char* data, size_t len, size_t* off);
This commit is contained in:
Takatoshi Kondo
2014-07-13 09:35:58 +09:00
parent 0e48f65a4b
commit 0380215982
5 changed files with 236 additions and 28 deletions

119
example/lib_buffer_unpack.c Normal file
View File

@@ -0,0 +1,119 @@
#include <msgpack.h>
#include <stdio.h>
#include <assert.h>
typedef struct receiver {
msgpack_sbuffer sbuf;
size_t rest;
} receiver;
receiver r;
size_t receiver_init(receiver *r) {
msgpack_packer pk;
msgpack_sbuffer_init(&r->sbuf);
msgpack_packer_init(&pk, &r->sbuf, msgpack_sbuffer_write);
/* 1st object */
msgpack_pack_array(&pk, 3);
msgpack_pack_int(&pk, 1);
msgpack_pack_true(&pk);
msgpack_pack_str(&pk, 7);
msgpack_pack_str_body(&pk, "example", 7);
/* 2nd object */
msgpack_pack_str(&pk, 6);
msgpack_pack_str_body(&pk, "second", 6);
/* 3rd object */
msgpack_pack_array(&pk, 2);
msgpack_pack_int(&pk, 42);
msgpack_pack_false(&pk);
r->rest = r->sbuf.size;
}
size_t receiver_recv(receiver *r, char* buf, size_t try_size) {
size_t off = r->sbuf.size - r->rest;
size_t actual_size = try_size;
if (actual_size > r->rest) actual_size = r->rest;
memcpy(buf, r->sbuf.data + off, actual_size);
r->rest -= actual_size;
return actual_size;
}
#define EACH_RECV_SIZE 4
void unpack(receiver* r) {
/* buf is allocated by unpacker. */
msgpack_unpacker* unp = msgpack_unpacker_new(100);
msgpack_unpacked result;
msgpack_unpack_return ret;
char* buf;
size_t recv_len;
msgpack_unpacked_init(&result);
if (msgpack_unpacker_buffer_capacity(unp) < EACH_RECV_SIZE) {
bool expanded = msgpack_unpacker_reserve_buffer(unp, 100);
assert(expanded);
}
buf = msgpack_unpacker_buffer(unp);
recv_len = receiver_recv(r, buf, EACH_RECV_SIZE);
msgpack_unpacker_buffer_consumed(unp, recv_len);
int recv_count = 0;
while (recv_len > 0) {
int i = 0;
printf("receive count: %d %d bytes received.:\n", recv_count++, recv_len);
ret = msgpack_unpacker_next(unp, &result);
while (ret == MSGPACK_UNPACK_SUCCESS) {
msgpack_object obj = result.data;
/* Use obj. */
printf("Object no %d:\n", i++);
msgpack_object_print(stdout, obj);
printf("\n");
/* If you want to allocate something on the zone, you can use zone. */
/* msgpack_zone* zone = result.zone; */
/* The lifetime of the obj and the zone, */
ret = msgpack_unpacker_next(unp, &result);
}
if (ret == MSGPACK_UNPACK_PARSE_ERROR) {
printf("The data in the buf is invalid format.\n");
msgpack_unpacked_destroy(&result);
return;
}
if (msgpack_unpacker_buffer_capacity(unp) < EACH_RECV_SIZE) {
bool expanded = msgpack_unpacker_reserve_buffer(unp, 100);
assert(expanded);
}
buf = msgpack_unpacker_buffer(unp);
recv_len = receiver_recv(r, buf, 4);
msgpack_unpacker_buffer_consumed(unp, recv_len);
}
msgpack_unpacked_destroy(&result);
}
int main(void) {
receiver r;
receiver_init(&r);
unpack(&r);
return 0;
}
/* Output */
/*
Object no 1:
[1, true, "example"]
Object no 2:
"second"
Object no 3:
[42, false]
*/

View File

@@ -0,0 +1,75 @@
#include <msgpack.h>
#include <stdio.h>
#include <assert.h>
void prepare(msgpack_sbuffer* sbuf) {
msgpack_packer pk;
msgpack_packer_init(&pk, sbuf, msgpack_sbuffer_write);
/* 1st object */
msgpack_pack_array(&pk, 3);
msgpack_pack_int(&pk, 1);
msgpack_pack_true(&pk);
msgpack_pack_str(&pk, 7);
msgpack_pack_str_body(&pk, "example", 7);
/* 2nd object */
msgpack_pack_str(&pk, 6);
msgpack_pack_str_body(&pk, "second", 6);
/* 3rd object */
msgpack_pack_array(&pk, 2);
msgpack_pack_int(&pk, 42);
msgpack_pack_false(&pk);
}
void unpack(char const* buf, size_t len) {
/* buf is allocated by client. */
msgpack_unpacked result;
size_t off = 0;
msgpack_unpack_return ret;
int i = 0;
msgpack_unpacked_init(&result);
ret = msgpack_unpack_next(&result, buf, len, &off);
while (ret == MSGPACK_UNPACK_SUCCESS) {
msgpack_object obj = result.data;
/* Use obj. */
printf("Object no %d:\n", i++);
msgpack_object_print(stdout, obj);
printf("\n");
/* If you want to allocate something on the zone, you can use zone. */
/* msgpack_zone* zone = result.zone; */
/* The lifetime of the obj and the zone, */
ret = msgpack_unpack_next(&result, buf, len, &off);
}
msgpack_unpacked_destroy(&result);
if (ret == MSGPACK_UNPACK_CONTINUE) {
printf("All msgpack_object in the buffer is consumed.\n");
}
else if (ret == MSGPACK_UNPACK_PARSE_ERROR) {
printf("The data in the buf is invalid format.\n");
}
}
int main(void) {
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
prepare(&sbuf);
unpack(sbuf.data, sbuf.size);
msgpack_sbuffer_destroy(&sbuf);
return 0;
}
/* Output */
/*
Object no 1:
[1, true, "example"]
Object no 2:
"second"
Object no 3:
[42, false]
*/

View File

@@ -38,7 +38,17 @@ typedef struct msgpack_unpacked {
msgpack_object data;
} msgpack_unpacked;
bool msgpack_unpack_next(msgpack_unpacked* result,
typedef enum {
MSGPACK_UNPACK_SUCCESS = 2,
MSGPACK_UNPACK_EXTRA_BYTES = 1,
MSGPACK_UNPACK_CONTINUE = 0,
MSGPACK_UNPACK_PARSE_ERROR = -1,
MSGPACK_UNPACK_NOMEM_ERROR = -2
} msgpack_unpack_return;
msgpack_unpack_return
msgpack_unpack_next(msgpack_unpacked* result,
const char* data, size_t len, size_t* off);
/** @} */
@@ -136,7 +146,7 @@ static inline void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, si
* Returns true if it successes. Otherwise false is returned.
* @param pac pointer to an initialized msgpack_unpacked object.
*/
bool msgpack_unpacker_next(msgpack_unpacker* mpac, msgpack_unpacked* pac);
msgpack_unpack_return msgpack_unpacker_next(msgpack_unpacker* mpac, msgpack_unpacked* pac);
/**
* Initializes a msgpack_unpacked object.
@@ -174,20 +184,14 @@ static inline size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac)
/** @} */
// obsolete
typedef enum {
MSGPACK_UNPACK_SUCCESS = 2,
MSGPACK_UNPACK_EXTRA_BYTES = 1,
MSGPACK_UNPACK_CONTINUE = 0,
MSGPACK_UNPACK_PARSE_ERROR = -1
} msgpack_unpack_return;
// obsolete
msgpack_unpack_return
msgpack_unpack(const char* data, size_t len, size_t* off,
msgpack_zone* result_zone, msgpack_object* result);
static inline size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac);
bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac);

View File

@@ -390,25 +390,24 @@ void msgpack_unpacker_reset(msgpack_unpacker* mpac)
mpac->parsed = 0;
}
bool msgpack_unpacker_next(msgpack_unpacker* mpac, msgpack_unpacked* result)
msgpack_unpack_return msgpack_unpacker_next(msgpack_unpacker* mpac, msgpack_unpacked* result)
{
if(result->zone != NULL) {
msgpack_zone_free(result->zone);
}
int ret = msgpack_unpacker_execute(mpac);
if(ret <= 0) {
if(ret < 0) {
result->zone = NULL;
memset(&result->data, 0, sizeof(msgpack_object));
return false;
return MSGPACK_UNPACK_PARSE_ERROR;
}
if(ret == 0) {
return MSGPACK_UNPACK_CONTINUE;
}
result->zone = msgpack_unpacker_release_zone(mpac);
result->data = msgpack_unpacker_data(mpac);
msgpack_unpacker_reset(mpac);
return true;
return MSGPACK_UNPACK_SUCCESS;
}
@@ -450,7 +449,8 @@ msgpack_unpack(const char* data, size_t len, size_t* off,
return MSGPACK_UNPACK_SUCCESS;
}
bool msgpack_unpack_next(msgpack_unpacked* result,
msgpack_unpack_return
msgpack_unpack_next(msgpack_unpacked* result,
const char* data, size_t len, size_t* off)
{
msgpack_unpacked_destroy(result);
@@ -459,29 +459,39 @@ bool msgpack_unpack_next(msgpack_unpacked* result,
if(off != NULL) { noff = *off; }
if(len <= noff) {
return false;
return MSGPACK_UNPACK_CONTINUE;
}
msgpack_zone* z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
if (!result->zone) {
result->zone = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
}
if (!result->zone) {
return MSGPACK_UNPACK_NOMEM_ERROR;
}
template_context ctx;
template_init(&ctx);
ctx.user.z = z;
ctx.user.z = result->zone;
ctx.user.referenced = false;
int e = template_execute(&ctx, data, len, &noff);
if(e <= 0) {
msgpack_zone_free(z);
return false;
if(e < 0) {
msgpack_zone_free(result->zone);
result->zone = NULL;
return MSGPACK_UNPACK_PARSE_ERROR;
}
if(off != NULL) { *off = noff; }
result->zone = z;
if(e == 0) {
return MSGPACK_UNPACK_CONTINUE;
}
result->data = template_data(&ctx);
return true;
return MSGPACK_UNPACK_SUCCESS;
}
#if defined(MSGPACK_OLD_COMPILER_BUS_ERROR_WORKAROUND)

View File

@@ -54,7 +54,7 @@ TEST(streaming, basic)
msgpack_unpacker_buffer_consumed(&pac, 1);
while(msgpack_unpacker_next(&pac, &result)) {
while(msgpack_unpacker_next(&pac, &result) == MSGPACK_UNPACK_SUCCESS) {
unpacked = 1;
msgpack_object obj = result.data;
msgpack_object e;