diff --git a/example/c/user_buffer_unpack.c b/example/c/user_buffer_unpack.c index a26cdebc..646a9f67 100644 --- a/example/c/user_buffer_unpack.c +++ b/example/c/user_buffer_unpack.c @@ -2,6 +2,8 @@ #include #include +#define UNPACKED_BUFFER_SIZE 2048 + void prepare(msgpack_sbuffer* sbuf) { msgpack_packer pk; @@ -27,6 +29,7 @@ void unpack(char const* buf, size_t len) { size_t off = 0; msgpack_unpack_return ret; int i = 0; + char unpacked_buffer[UNPACKED_BUFFER_SIZE]; msgpack_unpacked_init(&result); ret = msgpack_unpack_next(&result, buf, len, &off); while (ret == MSGPACK_UNPACK_SUCCESS) { @@ -36,6 +39,8 @@ void unpack(char const* buf, size_t len) { printf("Object no %d:\n", ++i); msgpack_object_print(stdout, obj); printf("\n"); + msgpack_object_print_buffer(unpacked_buffer, UNPACKED_BUFFER_SIZE, obj); + printf("%s\n", unpacked_buffer); /* 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, */ diff --git a/include/msgpack/object.h b/include/msgpack/object.h index 666f8285..cb137290 100644 --- a/include/msgpack/object.h +++ b/include/msgpack/object.h @@ -98,6 +98,9 @@ typedef struct msgpack_object_kv { MSGPACK_DLLEXPORT void msgpack_object_print(FILE* out, msgpack_object o); +MSGPACK_DLLEXPORT +int msgpack_object_print_buffer(char *buffer, uint32_t buffer_size, msgpack_object o); + MSGPACK_DLLEXPORT bool msgpack_object_equal(const msgpack_object x, const msgpack_object y); diff --git a/include/msgpack/sysdep.h b/include/msgpack/sysdep.h index 84bf1f48..b1ee1488 100644 --- a/include/msgpack/sysdep.h +++ b/include/msgpack/sysdep.h @@ -14,6 +14,11 @@ #include #include + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +# define snprintf(buf, len, format,...) _snprintf_s(buf, len, len, format, __VA_ARGS__) +#endif + #if defined(_MSC_VER) && _MSC_VER < 1600 typedef signed __int8 int8_t; typedef unsigned __int8 uint8_t; diff --git a/src/objectc.c b/src/objectc.c index 72f2ffee..60b22dff 100644 --- a/src/objectc.c +++ b/src/objectc.c @@ -222,6 +222,205 @@ void msgpack_object_print(FILE* out, msgpack_object o) } } +int msgpack_object_print_buffer(char *buffer, uint32_t buffer_size, msgpack_object o) +{ + char *aux_buffer = buffer; + uint32_t aux_buffer_size = buffer_size; + int ret; + switch(o.type) { + case MSGPACK_OBJECT_NIL: + ret = snprintf(aux_buffer, aux_buffer_size, "nil"); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + break; + + case MSGPACK_OBJECT_BOOLEAN: + ret = snprintf(aux_buffer, aux_buffer_size, (o.via.boolean ? "true" : "false")); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + break; + + case MSGPACK_OBJECT_POSITIVE_INTEGER: +#if defined(PRIu64) + ret = snprintf(aux_buffer, aux_buffer_size, "%" PRIu64, o.via.u64); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; +#else + if (o.via.u64 > ULONG_MAX) { + ret = snprintf(aux_buffer, aux_buffer_size, "over 4294967295"); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + } else { + ret = snprintf(aux_buffer, aux_buffer_size, "%lu", (unsigned long)o.via.u64); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + } +#endif + break; + + case MSGPACK_OBJECT_NEGATIVE_INTEGER: +#if defined(PRIi64) + ret = snprintf(aux_buffer, aux_buffer_size, "%" PRIi64, o.via.i64); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; +#else + if (o.via.i64 > LONG_MAX) { + ret = snprintf(aux_buffer, aux_buffer_size, "over +2147483647"); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + } else if (o.via.i64 < LONG_MIN) { + ret = snprintf(aux_buffer, aux_buffer_size, "under -2147483648"); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + } else { + ret = snprintf(aux_buffer, aux_buffer_size, "%ld", (signed long)o.via.i64); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + } +#endif + break; + + case MSGPACK_OBJECT_FLOAT: + ret = snprintf(aux_buffer, aux_buffer_size, "%f", o.via.f64); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + break; + + case MSGPACK_OBJECT_STR: + ret = snprintf(aux_buffer, aux_buffer_size, "\""); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + ret = snprintf(aux_buffer, aux_buffer_size, "%.*s", o.via.str.size, o.via.str.ptr); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + ret = snprintf(aux_buffer, aux_buffer_size, "\""); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + break; + + case MSGPACK_OBJECT_BIN: + ret = snprintf(aux_buffer, aux_buffer_size, "\""); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + if (o.via.bin.size < aux_buffer_size) { + memcpy(aux_buffer, o.via.bin.ptr, o.via.bin.size); + aux_buffer = aux_buffer + o.via.bin.size; + aux_buffer_size = aux_buffer_size - o.via.bin.size; + } else { + memcpy(aux_buffer, o.via.bin.ptr, aux_buffer_size); + aux_buffer_size = 0; + } + ret = snprintf(aux_buffer, aux_buffer_size, "\""); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + break; + + case MSGPACK_OBJECT_EXT: +#if defined(PRIi8) + ret = snprintf(aux_buffer, aux_buffer_size, "(ext: %" PRIi8 ")", o.via.ext.type); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; +#else + ret = snprintf(aux_buffer, aux_buffer_size, "(ext: %d)", (int)o.via.ext.type); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; +#endif + ret = snprintf(aux_buffer, aux_buffer_size, "\""); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + ret = snprintf(aux_buffer, aux_buffer_size, "%.*s", o.via.ext.size, o.via.ext.ptr); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + ret = snprintf(aux_buffer, aux_buffer_size, "\""); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + break; + + case MSGPACK_OBJECT_ARRAY: + ret = snprintf(aux_buffer, aux_buffer_size, "["); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + if(o.via.array.size != 0) { + msgpack_object* p = o.via.array.ptr; + msgpack_object* const pend = o.via.array.ptr + o.via.array.size; + ret = msgpack_object_print_buffer(aux_buffer, aux_buffer_size, *p); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + ++p; + for(; p < pend; ++p) { + ret = snprintf(aux_buffer, aux_buffer_size, ", "); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + ret = msgpack_object_print_buffer(aux_buffer, aux_buffer_size, *p); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + } + } + ret = snprintf(aux_buffer, aux_buffer_size, "]"); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + break; + + case MSGPACK_OBJECT_MAP: + ret = snprintf(aux_buffer, aux_buffer_size, "{"); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + if(o.via.map.size != 0) { + msgpack_object_kv* p = o.via.map.ptr; + msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size; + ret = msgpack_object_print_buffer(aux_buffer, aux_buffer_size, p->key); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + ret = snprintf(aux_buffer, aux_buffer_size, "=>"); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + ret = msgpack_object_print_buffer(aux_buffer, aux_buffer_size, p->val); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + ++p; + for(; p < pend; ++p) { + ret = snprintf(aux_buffer, aux_buffer_size, ", "); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + ret = msgpack_object_print_buffer(aux_buffer, aux_buffer_size, p->key); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + ret = snprintf(aux_buffer, aux_buffer_size, "=>"); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + ret = msgpack_object_print_buffer(aux_buffer, aux_buffer_size, p->val); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + } + } + ret = snprintf(aux_buffer, aux_buffer_size, "}"); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + break; + + default: + // FIXME +#if defined(PRIu64) + ret = snprintf(aux_buffer, aux_buffer_size, "#", o.type, o.via.u64); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; +#else + if (o.via.u64 > ULONG_MAX) { + ret = snprintf(aux_buffer, aux_buffer_size, "#", o.type); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + } else { + ret = snprintf(aux_buffer, aux_buffer_size, "#", o.type, (unsigned long)o.via.u64); + aux_buffer = aux_buffer + ret; + aux_buffer_size = aux_buffer_size - ret; + } +#endif + } + + return buffer_size - aux_buffer_size; +} + + bool msgpack_object_equal(const msgpack_object x, const msgpack_object y) { if(x.type != y.type) { return false; }