aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--msgpack.c284
-rw-r--r--test.c264
3 files changed, 343 insertions, 207 deletions
diff --git a/.gitignore b/.gitignore
index ea35e10..8855af4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-bin
+build
.ninja_*
diff --git a/msgpack.c b/msgpack.c
index 70cd463..e30501c 100644
--- a/msgpack.c
+++ b/msgpack.c
@@ -2,36 +2,36 @@
#include <endian.h> // endianness
#include <string.h> // memcpy
-#define PINT8_H(p) (*(int8_t*)(p))
-#define PINT16_H(p) ((int16_t)be16toh(*(uint16_t *)(p)))
-#define PINT32_H(p) ((int32_t)be32toh(*(uint32_t *)(p)))
-#define PINT64_H(p) ((int64_t)be64toh(*(uint64_t *)(p)))
-
-#define PUINT8_H(p) (*(uint8_t*)(p))
-#define PUINT16_H(p) (be16toh(*(uint16_t *)(p)))
-#define PUINT32_H(p) (be32toh(*(uint32_t *)(p)))
-#define PUINT64_H(p) (be64toh(*(uint64_t *)(p)))
-
-#define H_UINT8(b) ((uint8_t)b)
-#define H_UINT16(b) ((uint16_t)htobe16((uint16_t)(b)))
-#define H_UINT32(b) ((uint32_t)htobe32((uint32_t)(b)))
-#define H_UINT64(b) ((uint64_t)htobe64((uint64_t)(b)))
-
-#define H_UINT8_CPY(b, p) (((uint8_t*)(p))[0] = H_UINT8(b));
-#define H_UINT16_CPY(b, p) (((uint16_t*)(p))[0] = H_UINT16(b))
-#define H_UINT32_CPY(b, p) (((uint32_t*)(p))[0] = H_UINT32(b))
-#define H_UINT64_CPY(b, p) (((uint64_t*)(p))[0] = H_UINT64(b))
-
-#define H_INT8_CPY(b, p) H_UINT8_CPY(b, p)
-#define H_INT16_CPY(b, p) H_UINT16_CPY(b, p)
-#define H_INT32_CPY(b, p) H_UINT32_CPY(b, p)
-#define H_INT64_CPY(b, p) H_UINT64_CPY(b, p)
-
-// fix these
-// #define F32_H(b) (*(float *) &be32toh(*(uint32_t *)(b)))
-// #define F64_H(b) (*(double *)&be64toh(*(uint64_t *)(b)))
-// #define H_F32(b) (*(float *) &htobe32(*(uint32_t *)(b)))
-// #define H_F64(b) (*(double *)&htobe64(*(uint64_t *)(b)))
+#define ITOF(bits, v) (((union {uint32_t u32; float f32; uint64_t u64; double f64;}){.u##bits = v}).f##bits)
+#define FTOI(bits, v) (((union {uint32_t u32; float f32; uint64_t u64; double f64;}){.f##bits = v}).u##bits)
+
+#define INT int
+#define UINT uint
+#define F32 float // possibly remove
+#define F64 double // possibly remove
+
+#define htobe8(i) (i)
+#define be8toh(i) (i)
+#define __HTOI(bits, i) htobe##bits(i)
+#define __ITOH(bits, i) be##bits##toh(i)
+
+#define _ITOH(type, bits, i) ((type)__ITOH(bits, i))
+#define _HTOI(type, bits, h) ((type)__HTOI(bits, h))
+#define _PTOH(type, bits, p) ((type)__ITOH(bits, (*(type *)(p))))
+#define _HTOP2(type, bits, h, p) ((*(type *)(p)) = __HTOI(bits, h))
+#define _PTOH_F(type, bits, p) ITOF(bits, _PTOH(uint##bits##_t, bits, p)) // possibly remove
+#define _HTOP2_F(type, bits, f, p) _HTOP2(uint##bits##_t, bits, FTOI(bits, f), p) // possibly remove
+
+#define EXPAND_CALL(c, ...) c(__VA_ARGS__)
+#define EXPAND_CONV1(t, b) t##b##_t, b
+#define EXPAND_CONV2(b) F##b, b
+
+#define ITOH(c, i) EXPAND_CALL(_TTOH, EXPAND_CONV1 c, i)
+#define HTOI(c, h) EXPAND_CALL(_HTOH, EXPAND_CONV1 c, h)
+#define PTOH(c, p) EXPAND_CALL(_PTOH, EXPAND_CONV1 c, p)
+#define HTOP2(c, h, p) EXPAND_CALL(_HTOP2, EXPAND_CONV1 c, h, p)
+#define PTOH_F(c, p) EXPAND_CALL(_PTOH_F, EXPAND_CONV2 c, p) // possibly remove
+#define HTOP2_F(c, f, p) EXPAND_CALL(_HTOP2_F, EXPAND_CONV2 c, f, p) // possibly remove
// range low, range high
#define RANGES(X) \
@@ -53,32 +53,32 @@
X(0xC3, FMT_BOOL_FALSE, MSGPACK_BOOL, false)
// byte, format, type, subtype, offset, lengh, field, conv, range high, range low
-#define FORMAT_INT(X) \
- X(0x00, FMT_FIX_UINT, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 0, 1, u, UINT8, 0, 127) \
- X(0XE0, FMT_FIX_INT, MSGPACK_INT, MSGPACK_INT_SIGNED, 0, 1, i, INT8, -32, -1) \
- X(0xCC, FMT_U8, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 1, u, UINT8, 0, UINT8_MAX) \
- X(0xCD, FMT_U16, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 2, u, UINT16, 0, UINT16_MAX) \
- X(0xCE, FMT_U32, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 4, u, UINT32, 0, UINT32_MAX) \
- X(0xCF, FMT_U64, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 8, u, UINT64, 0, UINT64_MAX) \
- X(0xD0, FMT_I8, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 1, i, INT8, INT8_MIN, INT8_MAX) \
- X(0xD1, FMT_I16, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 2, i, INT16, INT16_MIN, INT16_MAX) \
- X(0xD2, FMT_I32, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 4, i, INT32, INT32_MIN, INT32_MAX) \
- X(0xD3, FMT_I64, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 8, i, INT64, INT64_MIN, INT64_MAX)
+#define FORMAT_INT(X) \
+ X(0x00, FMT_FIX_UINT, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 0, 1, u, (UINT, 8), 0, 127) \
+ X(0XE0, FMT_FIX_INT, MSGPACK_INT, MSGPACK_INT_SIGNED, 0, 1, i, (INT, 8), -32, -1) \
+ X(0xCC, FMT_U8, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 1, u, (UINT, 8), 0, UINT8_MAX) \
+ X(0xCD, FMT_U16, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 2, u, (UINT, 16), 0, UINT16_MAX) \
+ X(0xCE, FMT_U32, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 4, u, (UINT, 32), 0, UINT32_MAX) \
+ X(0xCF, FMT_U64, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 8, u, (UINT, 64), 0, UINT64_MAX) \
+ X(0xD0, FMT_I8, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 1, i, (INT, 8), INT8_MIN, INT8_MAX) \
+ X(0xD1, FMT_I16, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 2, i, (INT, 16), INT16_MIN, INT16_MAX) \
+ X(0xD2, FMT_I32, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 4, i, (INT, 32), INT32_MIN, INT32_MAX) \
+ X(0xD3, FMT_I64, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 8, i, (INT, 64), INT64_MIN, INT64_MAX)
// byte, format, type, subtype, offset, length, field, conv
#define FORMAT_FLOAT(X) \
- X(0xCA, FMT_FLOAT, MSGPACK_FLOAT, MSGPACK_FLOAT_32, 1, 4, f, F32) \
- X(0xCB, FMT_DOUBLE, MSGPACK_FLOAT, MSGPACK_FLOAT_64, 1, 8, d, F64)
-
-// // byte, fmt, type, subtype, offset, length, data
-// #define FORMAT_RAW(X) \
-// X(0xA0, FMT_FIX_STR, MSGPACK_RAW, MSGPACK_RAW_STRING, 1, pack->bin[0] & 0x0F) \
-// X(0xC4, FMT_BIN8, MSGPACK_RAW, MSGPACK_RAW_BIN, 1, pack->bin[1]) \
-// X(0xC5, FMT_BIN16, MSGPACK_RAW, MSGPACK_RAW_BIN, 3, UINT16_H(pack->bin+1)) \
-// X(0xC6, FMT_BIN32, MSGPACK_RAW, MSGPACK_RAW_BIN, 5, UINT32_H(pack->bin+1)) \
-// X(0xD9, FMT_STR8, MSGPACK_RAW, MSGPACK_RAW_STRING, 1, pack->bin[1]) \
-// X(0xDA, FMT_STR16, MSGPACK_RAW, MSGPACK_RAW_STRING, 3, UINT16_H(pack->bin+1)) \
-// X(0xDB, FMT_STR32, MSGPACK_RAW, MSGPACK_RAW_STRING, 5, UINT32_H(pack->bin+1))
+ X(0xCA, FMT_FLOAT, MSGPACK_FLOAT, MSGPACK_FLOAT_32, 1, 4, f, (32)) \
+ X(0xCB, FMT_DOUBLE, MSGPACK_FLOAT, MSGPACK_FLOAT_64, 1, 8, d, (64))
+
+// byte, fmt, type, subtype, offset, conv
+#define FORMAT_RAW(X) \
+ X(0xA0, FMT_FIX_STR, MSGPACK_RAW, MSGPACK_RAW_STRING, 1, (UINT, 8)) \
+ X(0xC4, FMT_BIN8, MSGPACK_RAW, MSGPACK_RAW_BIN, 2, (UINT, 8)) \
+ X(0xC5, FMT_BIN16, MSGPACK_RAW, MSGPACK_RAW_BIN, 3, (UINT, 16)) \
+ X(0xC6, FMT_BIN32, MSGPACK_RAW, MSGPACK_RAW_BIN, 5, (UINT, 32)) \
+ X(0xD9, FMT_STR8, MSGPACK_RAW, MSGPACK_RAW_STRING, 2, (UINT, 8)) \
+ X(0xDA, FMT_STR16, MSGPACK_RAW, MSGPACK_RAW_STRING, 3, (UINT, 16)) \
+ X(0xDB, FMT_STR32, MSGPACK_RAW, MSGPACK_RAW_STRING, 5, (UINT, 32))
// // byte, fmt, type, elements, offset, lenght
// #define FORMAT_ARRAY(X) \
@@ -98,7 +98,7 @@
FORMAT_BOOL (X) \
FORMAT_INT (X) \
FORMAT_FLOAT (X) \
- // FORMAT_RAW (X) \
+ FORMAT_RAW (X) \
// FORMAT_ARRAY (X) \
// FORMAT_MAP (X) \
// FORMAT_EXT (X)
@@ -142,7 +142,7 @@ static const enum msgpack_fmt byte_to_fmt[] = {
} while(0)
static enum msgpack_fmt pack_fmt(msgpack_t *pack);
-static enum msgpack_fmt data_fmt(enum msgpack_type type, enum msgpack_type subtype, void *m);
+static enum msgpack_fmt data_fmt(enum msgpack_type type, enum msgpack_type subtype, const void *m);
#define FMT_FOR_READ(pack, type, subtype, m) pack_fmt(pack)
#define FMT_FOR_WRITE(pack, type, subtype, m) data_fmt(type, subtype, m)
@@ -160,7 +160,7 @@ const enum msgpack_type subtype;
if(!m) \
return ERROR(MSGPACK_##type, MSGPACK_ERROR_INVALID_ARGUMENT); \
\
- enum msgpack_fmt fmt = \
+ const enum msgpack_fmt fmt = \
FMT_FOR_##op(pack, MSGPACK_##type, subtype, m); \
\
switch(fmt) { \
@@ -183,32 +183,77 @@ const enum msgpack_type subtype;
return SUCCESS(x_type);
#define OP_INT_READ(_byte, ptr, value, x_conv) \
- value = P##x_conv##_H(ptr)
+ value = PTOH(x_conv, ptr)
#define OP_INT_WRITE(x_byte, ptr, value, x_conv) \
(ptr-1)[0] = x_byte; /* temp fix*/ \
- H_##x_conv##_CPY((value), (ptr))
+ HTOP2(x_conv, value, ptr)
-#define MAKE_X_INT(op, x_byte, x_fmt, x_type, x_subtype, x_offset, x_length, x_field, x_conv, ...) \
+#define OP_FLOAT_READ(_byte, ptr, value, x_conv) \
+ value = PTOH_F(x_conv, ptr)
+#define OP_FLOAT_WRITE(x_byte, ptr, value, x_conv) \
+ (ptr-1)[0] = x_byte; /* temp fix*/ \
+ HTOP2_F(x_conv, value, ptr)
+
+#define MAKE_X_INTORFLOAT(type, op, x_byte, x_fmt, x_type, x_subtype, x_offset, x_length, x_field, x_conv, ...) \
case x_fmt: \
ENOUGH_BYTES(pack, (x_offset) + (x_length), \
return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \
- OP_INT_##op(x_byte, pack->bin + (x_offset), m->x_field, x_conv); \
+ OP_##type##_##op(x_byte, pack->bin + (x_offset), m->x_field, x_conv); \
\
MOVE_PACK(pack, (x_offset) + (x_length)); \
return SUCCESS2(x_type, x_subtype);
+#define X_RAW_READ(_byte, x_fmt, x_type, x_subtype, x_offset, x_conv) \
+ case x_fmt: { \
+ ENOUGH_BYTES(pack, (x_offset), \
+ return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \
+ size_t length = (x_fmt == FMT_FIX_STR) ? PTOH(x_conv, pack->bin) & 0x0F \
+ : PTOH(x_conv, pack->bin + 1); \
+ ENOUGH_BYTES(pack, (x_offset) + length, \
+ return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \
+ \
+ m->size = length; \
+ m->bin = pack->bin + (x_offset); \
+ \
+ MOVE_PACK(pack, (x_offset) + length); \
+ return SUCCESS2(x_type, x_subtype); \
+ }
+
+#define X_RAW_WRITE(x_byte, x_fmt, x_type, x_subtype, x_offset, x_conv) \
+ case x_fmt: { \
+ ENOUGH_BYTES(pack, (x_offset), \
+ return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \
+ size_t length = *m; \
+ ENOUGH_BYTES(pack, (x_offset) + length, \
+ return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \
+ \
+ pack->bin[0] = x_byte; \
+ if (fmt == FMT_FIX_STR) { \
+ pack->bin[0] |= (uint8_t)length; \
+ } else { \
+ HTOP2(x_conv, length, pack->bin+1); \
+ } \
+ \
+ MOVE_PACK(pack, (x_offset) + length); \
+ return SUCCESS2(x_type, x_subtype); \
+ }
// --- api implemention --- //
#define X_BOOL_READ(...) MAKE_X_BOOL(READ, __VA_ARGS__)
-#define X_INT_READ(...) MAKE_X_INT(READ, __VA_ARGS__)
+#define X_INT_READ(...) MAKE_X_INTORFLOAT(INT, READ, __VA_ARGS__)
+#define X_FLOAT_READ(...) MAKE_X_INTORFLOAT(FLOAT, READ, __VA_ARGS__)
-int msgpack_read_nil (msgpack_t *pack);// COMPOSE_FUNCTION(READ, NIL)
+#define X_BOOL_WRITE(...) MAKE_X_BOOL(WRITE, __VA_ARGS__)
+#define X_INT_WRITE(...) MAKE_X_INTORFLOAT(INT, WRITE, __VA_ARGS__)
+#define X_FLOAT_WRITE(...) MAKE_X_INTORFLOAT(FLOAT, WRITE, __VA_ARGS__)
+
+// int msgpack_read_nil (msgpack_t *pack);
int msgpack_read_bool (msgpack_t *pack, bool *m) COMPOSE_FUNCTION(READ, BOOL)
int msgpack_read_int (msgpack_t *pack, union mp_int *m) COMPOSE_FUNCTION(READ, INT)
-// int msgpack_read_float (msgpack_t *pack, union mp_float *m); COMPOSE_FUNCTION(READ, FLOAT)
+int msgpack_read_float (msgpack_t *pack, union mp_float *m) COMPOSE_FUNCTION(READ, FLOAT)
-// int msgpack_read_raw (msgpack_t *pack, struct mp_bin *m) COMPOSE_FUNCTION(READ, RAW)
+int msgpack_read_raw (msgpack_t *pack, struct mp_bin *m) COMPOSE_FUNCTION(READ, RAW)
// int msgpack_read_raw_cpy (msgpack_t *pack, struct mp_bin *m);
// int msgpack_read_ext (msgpack_t *pack, struct mp_bin *m) COMPOSE_FUNCTION(READ, EXT)
// int msgpack_read_ext_cpy (msgpack_t *pack, struct mp_bin *m);
@@ -218,13 +263,11 @@ int msgpack_read_int (msgpack_t *pack, union mp_int *m) COMPOSE_FUNCTION(RE
// int msgpack_read_array2 (const msgpack_t *pack, struct mp_array *m);
// int msgpack_read_map2 (const msgpack_t *pack, struct mp_map *m);
-#define X_BOOL_WRITE(...) MAKE_X_BOOL(WRITE, __VA_ARGS__)
-#define X_INT_WRITE(...) MAKE_X_INT(WRITE, __VA_ARGS__)
-
-int msgpack_write_nil (msgpack_t *pack);
+
+// int msgpack_write_nil (msgpack_t *pack);
int msgpack_write_bool (msgpack_t *pack, const bool *m) COMPOSE_FUNCTION(WRITE, BOOL)
int msgpack_write_int (msgpack_t *pack, const union mp_int *m, enum msgpack_type subtype) COMPOSE_FUNCTION(WRITE, INT)
-int msgpack_write_float (msgpack_t *pack, const union mp_float *m, enum msgpack_type subtype);
+int msgpack_write_float (msgpack_t *pack, const union mp_float *m, enum msgpack_type subtype) COMPOSE_FUNCTION(WRITE, FLOAT)
// int msgpack_write_raw (msgpack_t *pack, const struct mp_bin *m, enum msgpack_type subtype);
// int msgpack_write_ext (msgpack_t *pack, const struct mp_bin *m, enum msgpack_type subtype);
@@ -249,7 +292,7 @@ static enum msgpack_fmt pack_fmt(msgpack_t *pack)
}
#define WRAP_FMT_BOOL(e) \
- case MSGPACK_BOOL: switch(*(bool *)m) {e; default: break; } break;
+ case MSGPACK_BOOL: switch((int)*(bool *)m) {e; default: break; } break;
#define X_FMT_BOOL(_byte, x_fmt, x_type, x_data) \
case x_data: return x_fmt;
@@ -262,104 +305,21 @@ static enum msgpack_fmt pack_fmt(msgpack_t *pack)
return x_fmt; \
else
-static enum msgpack_fmt data_fmt(enum msgpack_type type, enum msgpack_type subtype, void *m)
+#define WRAP_FMT_FLOAT(e) \
+ case MSGPACK_FLOAT: switch(subtype) {e; default: break; } break;
+#define X_FMT_FLOAT(_byte, x_fmt, _type, x_subtype, _offset, _length, _field, _conv) \
+ case x_subtype: return x_fmt;
+
+// TODO: add X_FMT_RAW
+
+static enum msgpack_fmt data_fmt(enum msgpack_type type, enum msgpack_type subtype, const void *m)
{
switch(type) {
WRAP_FMT_BOOL(FORMAT_BOOL(X_FMT_BOOL))
WRAP_FMT_INT(FORMAT_INT(X_FMT_INT))
+ WRAP_FMT_FLOAT(FORMAT_FLOAT(X_FMT_FLOAT))
default: return FMT_UNKNOWN;
}
return FMT_UNKNOWN;
}
-
-
-
-// #define X_FLOAT(...) X_INT(__VA_ARGS__)
-
-// #define OP_RAW_READ(x_byte, pack, m, x_offset, x_length) \
-// m->bin = pack->bin + (x_offset); \
-// m->size = (x_length); \
-
-// #define X_READ_RAW(op, x_byte, x_fmt, x_type, x_subtype, x_offset, x_length_expr) \
-// case x_fmt: \
-// ENOUGH_BYTES(pack, (x_offset), \
-// return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \
-// size_t length = x_length_expr; \
-// ENOUGH_BYTES(pack, (size_t)(x_offset) + (x_length), \
-// return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \
-// OP_RAW_##op(x_byte, pack, m, (x_offset), (x_length)); \
-// \
-// MOVE_PACK(pack, (x_offset) + (x_length)); \
-// return SUCCESS2(x_type, x_subtype);
-
-// #define X_READ_EXT(...) //X_READ_RAW(__VA_ARGS__)
-
-// #define X_READ_ARRAY(_byte, x_fmt, x_type, x_elements, x_offset, _length) \
-// case x_fmt: \
-// ENOUGH_BYTES(pack, (x_offset), \
-// return ERROR(x_type, MSGPACK_ERROR_UNEXPECTED_END)); \
-// *m = x_elements; \
-// \
-// MOVE_PACK(pack, (x_offset)); \
-// return SUCCESS(x_type);
-
-// #define X_READ_MAP(...) X_READ_ARRAY(__VA_ARGS__)
-
-
-
-// #define X_COMPLEX_LENGTH(_byte, x_fmt, _type, x_elements, x_offset, x_length) \
-// case x_fmt: { \
-// ENOUGH_BYTES(pack, (x_offset), return 0); \
-// offset = (x_offset); \
-// elements = (x_elements); \
-// } break;
-
-// static size_t elements_length(msgpack_t *pack, enum msgpack_fmt fmt)
-// {
-// size_t offset = 0;
-// size_t elements = 0;
-
-// switch(fmt) {
-// FORMAT_ARRAY(X_COMPLEX_LENGTH)
-// FORMAT_MAP(X_COMPLEX_LENGTH)
-// default: return 0;
-// }
-
-// for(size_t i = 0; i < elements; i++) {
-// msgpack_t new_pack = {pack->bin + offset,
-// pack->size - offset};//, pack->membuf};
-// size_t len = pack_size(&new_pack);
-// if(len == 0) return 0;
-
-// offset += len;
-// ENOUGH_BYTES(pack, offset, return 0);
-// }
-
-// return offset;
-// }
-
-// #define X_PACK_SIZE(_byte, x_fmt, _type, _, x_offset, x_length, ...) \
-// case x_fmt: { \
-// ENOUGH_BYTES(pack, (x_offset), return 0); \
-// offset = (x_offset); \
-// length = (x_length); \
-// } break;
-
-// static size_t pack_size(msgpack_t *pack)
-// {
-// enum msgpack_fmt fmt = pack_fmt(pack);
-
-// size_t offset = 0;
-// size_t length = 0;
-
-// switch(fmt) {
-// FORMATS(X_PACK_SIZE)
-// default: return 0;
-// }
-
-// if(fmt_to_type[fmt] == MSGPACK_ARRAY || fmt_to_type[fmt] == MSGPACK_MAP)
-// if(length == 0) return 0;
-
-// return offset + length;
-// }
diff --git a/test.c b/test.c
index f7e821a..4ee5298 100644
--- a/test.c
+++ b/test.c
@@ -1,39 +1,72 @@
#include <stdio.h>
#include <string.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <sys/sendfile.h>
#include "msgpack.h"
-#define _IN " "
+// fprintf to logfp, but doesn't
+// move the file position indicator
+static FILE *logfp;
+#define logprintf(...) \
+ do { \
+ long pos = ftell(logfp); \
+ fseek(logfp, 0, SEEK_END); \
+ fprintf(logfp, __VA_ARGS__); \
+ fseek(logfp, pos, SEEK_SET); \
+ } while(0)
+#define _IN " "
#define _assert1(c) _assert2(c, ;)
#define _assert2(c, b) _assert3(#c, c, b)
#define _assert3(n, c, b) \
do { \
if(!(c)) { \
- printf("Assertion error '%s' in %s:%d\n", n, __FILE__, __LINE__); \
+ logprintf("Assertion error '%s' in %s:%d\n", n, __FILE__, __LINE__); \
b; \
failed_asserts++; \
} \
} while (0);
#define _logvar2(v, fmt) _logvar3(v, v, fmt)
-#define _logvar3(n, v, fmt) printf(_IN #n" = "fmt"\n", v)
+#define _logvar3(n, v, fmt) logprintf(_IN #n" = "fmt"\n", v)
#define _logbuf3(b, l, fmt) _logbuf4(b, b, l, fmt)
-#define _logbuf4(n, b, l, fmt) \
- do { \
- printf(_IN #n" = { "fmt, b[0]); \
- for(size_t i = 1; i < l; i++) printf(", "fmt, b[i]); \
- printf(" }\n"); \
+#define _logbuf4(n, b, l, fmt) \
+ do { \
+ logprintf(_IN #n" = { "fmt, b[0]); \
+ for(size_t i = 1; i < l; i++) \
+ logprintf(", "fmt, b[i]); \
+ logprintf(" }\n"); \
} while(0)
-
#define OVERLOAD_MACRO_4(_1, _2, _3, _4, NAME, ...) NAME
#define assert(...) OVERLOAD_MACRO_4(__VA_ARGS__, _, _assert3, _assert2, _assert1) (__VA_ARGS__)
#define logvar(...) OVERLOAD_MACRO_4(__VA_ARGS__, _, _logvar3, _logvar2, _) (__VA_ARGS__)
#define logbuf(...) OVERLOAD_MACRO_4(__VA_ARGS__, _logbuf4, _logbuf3, _, _) (__VA_ARGS__)
#define logbytes(...) logbuf(__VA_ARGS__, "0x%hhx")
-#define make_template(call, body) \
+// copy source fp from its file position indicator
+// to dest fp using sendfile (logfprintf is for that)
+static int fsendfile(FILE *dest, FILE *source)
+{
+ fflush(dest);
+ fflush(source);
+
+ long cur = ftell(source);
+ fseek(source, 0, SEEK_END);
+ long end = ftell(source);
+
+ int fd = fileno(source);
+ return sendfile(fileno(dest), fd, &cur, end - cur);
+}
+
+
+static int passed_test_counter;
+static int failed_test_counter;
+static int failed_asserts;
+
+#define check_condition(call, body) \
do { \
int prev_failed_asserts = failed_asserts; \
call; \
@@ -42,42 +75,48 @@
body); \
} while(0)
-static int passed_test_counter;
-static int failed_test_counter;
-static int failed_asserts;
-
-int test_internal();
-int test_bool();
-int test_int();
-
#define TEST(test) \
do { \
- if(test) { \
- printf("[FAILED] "#test"\n"); \
+ int r = 0; \
+ if((r = test)) { \
+ printf("[FAILED] "#test \
+ " with %d errors\n", r); \
failed_test_counter++; \
} else { \
printf("[PASSED] "#test"\n"); \
passed_test_counter++; \
} \
+ fsendfile(stdout, logfp) \
+ ? printf("\n") : 0; \
} while(0)
+int test_internal();
+int test_bool();
+int test_int();
+int test_float();
+int test_raw();
+int test_compound();
+
int main(void)
{
+ logfp = tmpfile();
+
TEST(test_internal());
TEST(test_bool());
TEST(test_int());
+ TEST(test_float());
+ TEST(test_raw());
+ TEST(test_compound());
- printf("\n------------------------------\n");
+ printf("------------------------------\n");
printf("PASSED %d/%d tests, (%.1f%%)\n",
passed_test_counter,
failed_test_counter + passed_test_counter,
100.0f * passed_test_counter /
(failed_test_counter + passed_test_counter));
- return 0;
-}
-int test_internal()
-{
+
+ fclose(logfp);
return 0;
}
@@ -90,10 +129,10 @@ int test_internal()
#define BODY_SUCCESS_2(t, a, type, subtype) \
{ \
BODY_SUCCESS_1(t, type); \
- assert(a == subtype, \
+ assert((int)a == (int)subtype, \
logvar(a, msgpack_type_string[a], "%s")); \
}
-
+
#define BODY_FAILED_1(t, e, a) \
{ \
assert("Failed Call", 0, ;); \
@@ -105,23 +144,30 @@ int test_internal()
return; \
}
+int test_internal()
+{
+ failed_asserts = 0;
+
+ return failed_asserts;
+}
void bool_1(uint8_t *buf, size_t size, bool value)
{
uint8_t b[1] = {0};
bool v;
-
+
MSGPACK_CHECK2(msgpack_read_bool(&msgpack_init(buf, size, NULL), &v),
(t, e, a), BODY_SUCCESS_1(t, MSGPACK_BOOL), BODY_FAILED_1(t, e, a));
assert(v == value, logvar(v, "%d"));
-
+
MSGPACK_CHECK2(msgpack_write_bool(&msgpack_init(b, size, NULL), &value),
(t, e, a), BODY_SUCCESS_1(t, MSGPACK_BOOL), BODY_FAILED_1(t, e, a));
assert(memcmp(buf, b, size) == 0, logbytes(b, size));
}
-
+
#define bool_template(n, _buf, _value) \
- make_template(bool_##n((_buf), sizeof(_buf), (_value)), { \
+ check_condition(bool_##n((_buf), sizeof(_buf), (_value)), \
+ { \
logbytes(buf, (_buf), sizeof(_buf)); \
logvar(value, (_value), "%d"); \
printf("\n"); \
@@ -141,36 +187,166 @@ void int_1(uint8_t *buf, size_t size, union mp_int value, enum msgpack_type subt
{
uint8_t b[9] = {0};
union mp_int v;
-
+
MSGPACK_CHECK2(msgpack_read_int(&msgpack_init(buf, size, NULL), &v),
(t, e, a), BODY_SUCCESS_2(t, a, MSGPACK_INT, subtype),
BODY_FAILED_1(t, e, a));
- assert(v.i == value.i, logvar(v.u, "%lld"));
-
+ assert(v.u == value.u, logvar(v.u, "%"PRIu64));
+
MSGPACK_CHECK2(msgpack_write_int(&msgpack_init(b, size, NULL), &value, subtype),
(t, e, a), BODY_SUCCESS_2(t, a, MSGPACK_INT, subtype),
BODY_FAILED_1(t, e, a));
assert(memcmp(buf, b, size) == 0, logbytes(b, size));
}
-#define int_template(n, _buf, _value, _subtype) \
- make_template(int_##n((_buf), sizeof(_buf), (_value), (_subtype)), { \
- logbytes(buf, (_buf), sizeof(_buf)); \
- if((_subtype) == MSGPACK_INT_SIGNED) \
- logvar(value.i, (_value).i, "%lld"); \
- else logvar(value.u, (_value).u, "%lld"); \
- logvar(subtype, msgpack_type_string[(_subtype)], "%s"); \
- printf("\n"); \
- }); \
+#define int_template(n, _buf, _value, _subtype) \
+ check_condition(int_##n((_buf), sizeof(_buf), (_value), (_subtype)), \
+ { \
+ logbytes(buf, (_buf), sizeof(_buf)); \
+ if((_subtype) == MSGPACK_INT_SIGNED) \
+ logvar(value.i, (_value).i, "%"PRIi64); \
+ else logvar(value.u, (_value).u, "%"PRIu64); \
+ logvar(subtype, msgpack_type_string[(_subtype)], "%s"); \
+ printf("\n"); \
+ }); \
int test_int()
{
failed_asserts = 0;
-
+
int_template(1, ((uint8_t []){0xD3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01}),
((union mp_int){.i=0x0100000000000201}), MSGPACK_INT_SIGNED);
+ int_template(1, ((uint8_t []){0xCF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01}),
+ ((union mp_int){.u=0x0100000000000201}), MSGPACK_INT_UNSIGNED);
int_template(1, ((uint8_t []){0xFF}),
((union mp_int){.i=-1}), MSGPACK_INT_SIGNED);
return failed_asserts;
}
+
+// void float_1(uint8_t *buf, size_t size, union mp_float value, enum msgpack_type subtype)
+// {
+// uint8_t b[9] = {0};
+// union mp_float v;
+
+// MSGPACK_CHECK2(msgpack_read_float(&msgpack_init(buf, size, NULL), &v),
+// (t, e, a), BODY_SUCCESS_2(t, a, MSGPACK_FLOAT, subtype),
+// BODY_FAILED_1(t, e, a));
+
+// if(subtype == MSGPACK_FLOAT_32) {
+// assert(v.f == value.f, logvar(v.f, "%f"));
+// } else {
+// assert(v.d == value.d, logvar(v.d, "%f"));
+// }
+
+// MSGPACK_CHECK2(msgpack_write_float(&msgpack_init(b, size, NULL), &value, subtype),
+// (t, e, a), BODY_SUCCESS_2(t, a, MSGPACK_FLOAT, subtype),
+// BODY_FAILED_1(t, e, a));
+// assert(memcmp(buf, b, size) == 0, logbytes(b, size));
+// }
+
+// #define float_template(n, _buf, _value, _subtype) \
+// check_condition(float_##n((_buf), sizeof(_buf), (_value), (_subtype)), \
+// { \
+// logbytes(buf, (_buf), sizeof(_buf)); \
+// if((_subtype) == MSGPACK_FLOAT_32) \
+// logvar(value.f, (_value).f, "%f"); \
+// else logvar(value.d, (_value).d, "%f"); \
+// logvar(subtype, msgpack_type_string[(_subtype)], "%s"); \
+// printf("\n"); \
+// });
+
+void float_2(union mp_float value, enum msgpack_type subtype)
+{
+ uint8_t b[9] = {0};
+ size_t size = 9;
+ union mp_float v;
+
+ MSGPACK_CHECK2(msgpack_write_float(&msgpack_init(b, size, NULL), &value, subtype),
+ (t, e, a), BODY_SUCCESS_2(t, a, MSGPACK_FLOAT, subtype),
+ BODY_FAILED_1(t, e, a));
+
+ MSGPACK_CHECK2(msgpack_read_float(&msgpack_init(b, size, NULL), &v),
+ (t, e, a), BODY_SUCCESS_2(t, a, MSGPACK_FLOAT, subtype),
+ BODY_FAILED_1(t, e, a));
+
+ if(subtype == MSGPACK_FLOAT_32) {
+ assert(v.f == value.f, logvar(v.f, "%f"));
+ logbytes(b, 5);
+ } else {
+ assert(v.d == value.d, logvar(v.d, "%f"));
+ logbytes(b, 9);
+ }
+}
+
+#define float_template(n, _value, _subtype) \
+ check_condition(float_##n((_value), (_subtype)), \
+ { \
+ if((_subtype) == MSGPACK_FLOAT_32) \
+ logvar(value.f, (_value).f, "%f"); \
+ else logvar(value.d, (_value).d, "%f"); \
+ logvar(subtype, \
+ msgpack_type_string[(_subtype)], "%s"); \
+ })
+
+#include <float.h>
+int test_float()
+{
+ failed_asserts = 0;
+
+ float_template(2, ((union mp_float){.f=-1.7}), MSGPACK_FLOAT_32);
+ float_template(2, ((union mp_float){.f=FLT_MAX}), MSGPACK_FLOAT_32);
+ float_template(2, ((union mp_float){.f=FLT_MIN}), MSGPACK_FLOAT_32);
+ float_template(2, ((union mp_float){.d=DBL_MAX}), MSGPACK_FLOAT_64);
+ float_template(2, ((union mp_float){.d=DBL_MIN}), MSGPACK_FLOAT_64);
+
+ return failed_asserts;
+}
+
+void raw_1(uint8_t *bin, size_t size, struct mp_bin b)
+{
+ msgpack_t pack = msgpack_init(bin, size, NULL);
+ struct mp_bin v = {0};
+
+ MSGPACK_CHECK2(msgpack_read_raw(&pack, &v), (t, e, a),
+ BODY_SUCCESS_2(t, a, MSGPACK_RAW, MSGPACK_RAW_STRING),
+ BODY_FAILED_1(t, e, a));
+
+ assert(v.size == b.size, logvar(v.size, "%z"));
+ assert(memcmp(v.bin, b.bin, v.size) == 0, logbytes(v.bin, v.size));
+
+}
+
+int test_raw()
+{
+ failed_asserts = 0;
+ check_condition(raw_1("\xa5hello", 6,
+ (struct mp_bin){.size = 5, .bin = "hello"}), );
+ check_condition(raw_1("\xd9\x05hello", 7,
+ (struct mp_bin){.size = 5, .bin = "hello"}), );
+ return failed_asserts;
+}
+
+void compound_1()
+{
+ uint8_t bin[] = {0x0A, 0xCF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01};
+ msgpack_t pack = msgpack_init(bin, sizeof(bin), NULL);
+ union mp_int v = {0};
+
+ MSGPACK_CHECK2(msgpack_read_int(&pack, &v),
+ (t, e, a), BODY_SUCCESS_2(t, a, MSGPACK_INT, MSGPACK_INT_UNSIGNED),
+ BODY_FAILED_1(t, e, a));
+ assert(v.i == 10, logvar(v.u, "%"PRIi64));
+
+ MSGPACK_CHECK2(msgpack_read_int(&pack, &v),
+ (t, e, a), BODY_SUCCESS_2(t, a, MSGPACK_INT, MSGPACK_INT_UNSIGNED),
+ BODY_FAILED_1(t, e, a));
+ assert(v.i == 0x0100000000000201, logvar(v.u, "%"PRIi64));
+}
+
+int test_compound()
+{
+ failed_asserts = 0;
+ compound_1();
+ return failed_asserts;
+}