diff options
-rw-r--r-- | msgpack.c | 146 | ||||
-rw-r--r-- | test.c | 23 |
2 files changed, 87 insertions, 82 deletions
@@ -2,36 +2,32 @@ #include <endian.h> // endianness #include <string.h> // memcpy -#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 EXPAND_CALL(c, ...) c(__VA_ARGS__) +#define CAR(a, b) a +#define CDR(a, b) b #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 _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 CONV_ALL(...) __VA_ARGS__ +#define CONV_TYPE(t, b) t##b##_t +#define CONV_BITS(t, b) b -#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) ((CONV_TYPE c)EXPAND_CALL(_ITOH, CONV_BITS c, i)) +#define HTOI(c, h) ((CONV_TYPE c)EXPAND_CALL(_HTOI, CONV_BITS c, i)) +#define PTOH(c, p) ((CONV_TYPE c)EXPAND_CALL(_ITOH, CONV_BITS c, (*(CONV_TYPE c*)(p)))) +#define HTOP2(c, h, p) (((*(CONV_TYPE c *)(p)) = EXPAND_CALL(_HTOI, CONV_BITS c, h))) -#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 +#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 PTOH_F(c, p) EXPAND_CALL(ITOF, CONV_ALL c, PTOH((UINT, CONV_ALL c), p)) // possibly remove +#define HTOP2_F(c, f, p) HTOP2((UINT, CONV_ALL c), EXPAND_CALL(FTOI, CONV_ALL c, f), p) // possibly remove // range low, range high #define RANGES(X) \ @@ -52,33 +48,33 @@ X(0xC2, FMT_BOOL_TRUE, MSGPACK_BOOL, true) \ X(0xC3, FMT_BOOL_FALSE, MSGPACK_BOOL, false) -// byte, format, type, subtype, offset, lengh, field, conv, range high, range low +// byte, format, type, subtype, offset, lengh, field, conv, range #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) + 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, (32)) \ X(0xCB, FMT_DOUBLE, MSGPACK_FLOAT, MSGPACK_FLOAT_64, 1, 8, d, (64)) -// byte, fmt, type, subtype, offset, conv +// byte, fmt, type, subtype, offset, conv, max #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)) + X(0xA0, FMT_FIX_STR, MSGPACK_RAW, MSGPACK_RAW_STRING, 1, (UINT, 8), 31) \ + X(0xC4, FMT_BIN8, MSGPACK_RAW, MSGPACK_RAW_BIN, 2, (UINT, 8), UINT8_MAX) \ + X(0xC5, FMT_BIN16, MSGPACK_RAW, MSGPACK_RAW_BIN, 3, (UINT, 16), UINT16_MAX) \ + X(0xC6, FMT_BIN32, MSGPACK_RAW, MSGPACK_RAW_BIN, 5, (UINT, 32), UINT32_MAX) \ + X(0xD9, FMT_STR8, MSGPACK_RAW, MSGPACK_RAW_STRING, 2, (UINT, 8), UINT8_MAX) \ + X(0xDA, FMT_STR16, MSGPACK_RAW, MSGPACK_RAW_STRING, 3, (UINT, 16), UINT16_MAX) \ + X(0xDB, FMT_STR32, MSGPACK_RAW, MSGPACK_RAW_STRING, 5, (UINT, 32), UINT32_MAX) // // byte, fmt, type, elements, offset, lenght // #define FORMAT_ARRAY(X) \ @@ -119,9 +115,6 @@ static const enum msgpack_fmt byte_to_fmt[] = { FORMATS(X_BYTE_FMT) }; -// static size_t elements_length(msgpack_t *pack, enum msgpack_fmt fmt); -// static size_t pack_size(msgpack_t *pack); - // --- helper macros --- // @@ -171,6 +164,8 @@ const enum msgpack_type subtype; } \ } +// TODO: refactor these things, they are hard to read + #define OP_BOOL_READ(x_byte, pack, m, x_data) \ *m = x_data #define OP_BOOL_WRITE(x_byte, pack, m, x_data) \ @@ -203,50 +198,47 @@ const enum msgpack_type subtype; 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 OP_RAW_LENGTH_READ(x_fmt, x_conv) \ + (x_fmt == FMT_FIX_STR) ? PTOH(x_conv, pack->bin) & 0x1F \ + : PTOH(x_conv, pack->bin + 1); + +#define OP_RAW_LENGTH_WRITE(x_fmt, x_conv) m->size + +#define OP_RAW_READ(x_byte, x_offset, x_conv) \ + m->size = length; \ + m->bin = pack->bin + (x_offset); + +#define OP_RAW_WRITE(x_byte, x_offset, x_conv) \ + pack->bin[0] = x_byte; \ + if (fmt == FMT_FIX_STR) pack->bin[0] |= (uint8_t)length; \ + else HTOP2(x_conv, length, pack->bin+1); \ + memcpy(pack->bin+(x_offset), m->bin, m->size); -#define X_RAW_WRITE(x_byte, x_fmt, x_type, x_subtype, x_offset, x_conv) \ +#define MAKE_X_RAW(op, 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; \ + size_t length = OP_RAW_LENGTH_##op(x_fmt, x_conv); \ + \ 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); \ - } \ + OP_RAW_##op(x_byte, x_offset, x_conv); \ \ 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_INTORFLOAT(INT, READ, __VA_ARGS__) #define X_FLOAT_READ(...) MAKE_X_INTORFLOAT(FLOAT, READ, __VA_ARGS__) +#define X_RAW_READ(...) MAKE_X_RAW(READ, __VA_ARGS__) #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__) +#define X_RAW_WRITE(...) MAKE_X_RAW(WRITE, __VA_ARGS__) // int msgpack_read_nil (msgpack_t *pack); int msgpack_read_bool (msgpack_t *pack, bool *m) COMPOSE_FUNCTION(READ, BOOL) @@ -269,7 +261,7 @@ int msgpack_write_bool (msgpack_t *pack, const bool *m) COMPOSE_FUN 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) COMPOSE_FUNCTION(WRITE, FLOAT) -// int msgpack_write_raw (msgpack_t *pack, const struct mp_bin *m, enum msgpack_type subtype); +int msgpack_write_raw (msgpack_t *pack, const struct mp_bin *m, enum msgpack_type subtype) COMPOSE_FUNCTION(WRITE, RAW) // int msgpack_write_ext (msgpack_t *pack, const struct mp_bin *m, enum msgpack_type subtype); // int msgpack_write_array (msgpack_t *pack, const size_t *m); @@ -298,10 +290,10 @@ static enum msgpack_fmt pack_fmt(msgpack_t *pack) #define WRAP_FMT_INT(e) \ case MSGPACK_INT: e; break; -#define X_FMT_INT(_byte, x_fmt, x_type, x_subtype, _offset, _length, x_field, _conv, x_range_low, x_range_high) \ +#define X_FMT_INT(_byte, x_fmt, x_type, x_subtype, _offset, _length, x_field, _conv, x_range) \ if((x_subtype == subtype) && \ - (((union mp_int *)m)->x_field >= x_range_low) && \ - (((union mp_int *)m)->x_field <= x_range_high)) \ + (((union mp_int *)m)->x_field >= CAR x_range) && \ + (((union mp_int *)m)->x_field <= CDR x_range)) \ return x_fmt; \ else @@ -310,7 +302,12 @@ static enum msgpack_fmt pack_fmt(msgpack_t *pack) #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 +#define WRAP_FMT_RAW(e) \ + case MSGPACK_RAW: e; break; +#define X_FMT_RAW(_byte, x_fmt, x_type, x_subtype, _offset, _conv, x_range_max) \ + if((x_subtype == subtype) && \ + ((struct mp_bin *)m)->size <= x_range_max) return x_fmt; \ + else static enum msgpack_fmt data_fmt(enum msgpack_type type, enum msgpack_type subtype, const void *m) { @@ -318,6 +315,7 @@ static enum msgpack_fmt data_fmt(enum msgpack_type type, enum msgpack_type subty WRAP_FMT_BOOL(FORMAT_BOOL(X_FMT_BOOL)) WRAP_FMT_INT(FORMAT_INT(X_FMT_INT)) WRAP_FMT_FLOAT(FORMAT_FLOAT(X_FMT_FLOAT)) + WRAP_FMT_RAW(FORMAT_RAW(X_FMT_RAW)) default: return FMT_UNKNOWN; } @@ -140,7 +140,7 @@ int main(void) logvar(e, msgpack_error_string[e], "%s"); \ if(e == MSGPACK_ERROR_WRONG_TYPE) \ logvar(a, msgpack_type_string[a], "%s"); \ - else logvar(a, "%hhx"); \ + else logvar(a, "0x%hhx"); \ return; \ } @@ -303,18 +303,25 @@ int test_float() return failed_asserts; } -void raw_1(uint8_t *bin, size_t size, struct mp_bin b) +void raw_1(uint8_t *bin, size_t size, struct mp_bin r) { - msgpack_t pack = msgpack_init(bin, size, NULL); + uint8_t b[64] = {0}; struct mp_bin v = {0}; - MSGPACK_CHECK2(msgpack_read_raw(&pack, &v), (t, e, a), + MSGPACK_CHECK2(msgpack_read_raw(&msgpack_init(bin, size, NULL), &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)); + assert(v.size == r.size, logvar(v.size, "%zu")); + assert(memcmp(v.bin, r.bin, v.size) == 0, logbytes(v.bin, v.size)); + MSGPACK_CHECK2(msgpack_write_raw(&msgpack_init(b, sizeof(b), NULL), &r, MSGPACK_RAW_STRING), + (t, e, a), + BODY_SUCCESS_2(t, a, MSGPACK_RAW, MSGPACK_RAW_STRING), + BODY_FAILED_1(t, e, a)); + + assert(memcmp(b, bin, size) == 0, logbytes(b, size)); } int test_raw() @@ -322,8 +329,8 @@ 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"}), ); + check_condition(raw_1("\xd9\x24hello_______________________________", 38, + (struct mp_bin){.size = 36, .bin = "hello_______________________________"}), ); return failed_asserts; } |