mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-18 19:48:46 +02:00
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:
119
example/lib_buffer_unpack.c
Normal file
119
example/lib_buffer_unpack.c
Normal 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]
|
||||||
|
*/
|
75
example/user_buffer_unpack.c
Normal file
75
example/user_buffer_unpack.c
Normal 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]
|
||||||
|
*/
|
@@ -38,7 +38,17 @@ typedef struct msgpack_unpacked {
|
|||||||
msgpack_object data;
|
msgpack_object data;
|
||||||
} msgpack_unpacked;
|
} 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);
|
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.
|
* Returns true if it successes. Otherwise false is returned.
|
||||||
* @param pac pointer to an initialized msgpack_unpacked object.
|
* @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.
|
* 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
|
// obsolete
|
||||||
msgpack_unpack_return
|
msgpack_unpack_return
|
||||||
msgpack_unpack(const char* data, size_t len, size_t* off,
|
msgpack_unpack(const char* data, size_t len, size_t* off,
|
||||||
msgpack_zone* result_zone, msgpack_object* result);
|
msgpack_zone* result_zone, msgpack_object* result);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac);
|
static inline size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac);
|
||||||
|
|
||||||
bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac);
|
bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac);
|
||||||
|
44
src/unpack.c
44
src/unpack.c
@@ -390,25 +390,24 @@ void msgpack_unpacker_reset(msgpack_unpacker* mpac)
|
|||||||
mpac->parsed = 0;
|
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);
|
int ret = msgpack_unpacker_execute(mpac);
|
||||||
|
|
||||||
if(ret <= 0) {
|
if(ret < 0) {
|
||||||
result->zone = NULL;
|
result->zone = NULL;
|
||||||
memset(&result->data, 0, sizeof(msgpack_object));
|
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->zone = msgpack_unpacker_release_zone(mpac);
|
||||||
result->data = msgpack_unpacker_data(mpac);
|
result->data = msgpack_unpacker_data(mpac);
|
||||||
msgpack_unpacker_reset(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;
|
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)
|
const char* data, size_t len, size_t* off)
|
||||||
{
|
{
|
||||||
msgpack_unpacked_destroy(result);
|
msgpack_unpacked_destroy(result);
|
||||||
@@ -459,29 +459,39 @@ bool msgpack_unpack_next(msgpack_unpacked* result,
|
|||||||
if(off != NULL) { noff = *off; }
|
if(off != NULL) { noff = *off; }
|
||||||
|
|
||||||
if(len <= noff) {
|
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_context ctx;
|
||||||
template_init(&ctx);
|
template_init(&ctx);
|
||||||
|
|
||||||
ctx.user.z = z;
|
ctx.user.z = result->zone;
|
||||||
ctx.user.referenced = false;
|
ctx.user.referenced = false;
|
||||||
|
|
||||||
int e = template_execute(&ctx, data, len, &noff);
|
int e = template_execute(&ctx, data, len, &noff);
|
||||||
if(e <= 0) {
|
if(e < 0) {
|
||||||
msgpack_zone_free(z);
|
msgpack_zone_free(result->zone);
|
||||||
return false;
|
result->zone = NULL;
|
||||||
|
return MSGPACK_UNPACK_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(off != NULL) { *off = noff; }
|
if(off != NULL) { *off = noff; }
|
||||||
|
|
||||||
result->zone = z;
|
if(e == 0) {
|
||||||
|
return MSGPACK_UNPACK_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
result->data = template_data(&ctx);
|
result->data = template_data(&ctx);
|
||||||
|
|
||||||
return true;
|
return MSGPACK_UNPACK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MSGPACK_OLD_COMPILER_BUS_ERROR_WORKAROUND)
|
#if defined(MSGPACK_OLD_COMPILER_BUS_ERROR_WORKAROUND)
|
||||||
|
@@ -54,7 +54,7 @@ TEST(streaming, basic)
|
|||||||
|
|
||||||
msgpack_unpacker_buffer_consumed(&pac, 1);
|
msgpack_unpacker_buffer_consumed(&pac, 1);
|
||||||
|
|
||||||
while(msgpack_unpacker_next(&pac, &result)) {
|
while(msgpack_unpacker_next(&pac, &result) == MSGPACK_UNPACK_SUCCESS) {
|
||||||
unpacked = 1;
|
unpacked = 1;
|
||||||
msgpack_object obj = result.data;
|
msgpack_object obj = result.data;
|
||||||
msgpack_object e;
|
msgpack_object e;
|
||||||
|
Reference in New Issue
Block a user