From cb71851d51bf4af8e13c3917b361b2aac81d6733 Mon Sep 17 00:00:00 2001 From: kartofen Date: Sat, 19 Apr 2025 18:23:06 +0300 Subject: arrays and maps added --- msgpack.c | 232 ++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 134 insertions(+), 98 deletions(-) (limited to 'msgpack.c') diff --git a/msgpack.c b/msgpack.c index c125a2d..07433b1 100644 --- a/msgpack.c +++ b/msgpack.c @@ -2,10 +2,16 @@ #include // endianness #include // memcpy -#define EXPAND_CALL(c, ...) c(__VA_ARGS__) +// TODO: it works pretty good, but some parts +// are needlessly complicated, not good + +// handy macros for extra expansion +#define _(...) __VA_ARGS__ +#define _CALL(f, ...) f(__VA_ARGS__) #define CAR(a, b) a #define CDR(a, b) b +// converions to and from big endian, including for floats #define INT int #define UINT uint @@ -18,16 +24,16 @@ #define CONV_TYPE(t, b) t##b##_t #define CONV_BITS(t, 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) ((CONV_TYPE c)_CALL(_ITOH, CONV_BITS c, i)) +#define HTOI(c, h) ((CONV_TYPE c)_CALL(_HTOI, CONV_BITS c, i)) +#define PTOH(c, p) ((CONV_TYPE c)_CALL(_ITOH, CONV_BITS c, (*(CONV_TYPE c*)(p)))) +#define HTOP2(c, h, p) (((*(CONV_TYPE c *)(p)) = _CALL(_HTOI, CONV_BITS c, h))) #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 +#define PTOH_F(c, p) _CALL(ITOF, CONV_ALL c, PTOH((UINT, CONV_ALL c), p)) // possibly remove +#define HTOP2_F(c, f, p) HTOP2((UINT, CONV_ALL c), _CALL(FTOI, CONV_ALL c, f), p) // possibly remove // range low, range high #define RANGES(X) \ @@ -50,8 +56,8 @@ // 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(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)) \ @@ -62,29 +68,29 @@ 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) \ +#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, max -#define FORMAT_RAW(X) \ - 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) \ +#define FORMAT_RAW(X) \ + 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(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) \ -// X(0x90, FMT_FIX_ARRAY, MSGPACK_ARRAY, pack->bin[0] & 0x0F, 1, elements_length(pack, fmt)) \ -// X(0xDC, FMT_ARRAY16, MSGPACK_ARRAY, UINT16_H(pack->bin+1), 3, elements_length(pack, fmt)) \ -// X(0xDD, FMT_ARRAY32, MSGPACK_ARRAY, UINT32_H(pack->bin+1), 5, elements_length(pack, fmt)) -// #define FORMAT_MAP(X) \ -// X(0x80, FMT_FIX_MAP, MSGPACK_MAP, 2 * (pack->bin[0] & 0x0F), 1, elements_length(pack, fmt)) \ -// X(0xDE, FMT_MAP16, MSGPACK_MAP, 2 * (UINT16_H(pack->bin+1)), 3, elements_length(pack, fmt)) \ -// X(0xDF, FMT_MAP32, MSGPACK_MAP, 2 * (UINT32_H(pack->bin+1)), 5, elements_length(pack, fmt)) +// byte, fmt, type, offset, conv, lenght +#define FORMAT_ARRAY(X) \ + X(0x90, FMT_FIX_ARRAY, MSGPACK_ARRAY, 1, (UINT, 8), 15) \ + X(0xDC, FMT_ARRAY16, MSGPACK_ARRAY, 3, (UINT, 16), UINT16_MAX) \ + X(0xDD, FMT_ARRAY32, MSGPACK_ARRAY, 5, (UINT, 32), UINT32_MAX) +#define FORMAT_MAP(X) \ + X(0x80, FMT_FIX_MAP, MSGPACK_MAP, 1, (UINT, 8), 15) \ + X(0xDE, FMT_MAP16, MSGPACK_MAP, 3, (UINT, 16), UINT16_MAX) \ + X(0xDF, FMT_MAP32, MSGPACK_MAP, 5, (UINT, 32), UINT32_MAX) // #define FORMAT_EXT(X) @@ -95,8 +101,8 @@ FORMAT_INT (X) \ FORMAT_FLOAT (X) \ FORMAT_RAW (X) \ - // FORMAT_ARRAY (X) \ - // FORMAT_MAP (X) \ + FORMAT_ARRAY (X) \ + FORMAT_MAP (X) \ // FORMAT_EXT (X) #define X_FMT_ENUM(_byte, fmt, ...) fmt, @@ -115,7 +121,6 @@ static const enum msgpack_fmt byte_to_fmt[] = { FORMATS(X_BYTE_FMT) }; - // --- helper macros --- // #define SUCCESS(type) SUCCESS2(type, 0) @@ -143,40 +148,42 @@ static enum msgpack_fmt data_fmt(enum msgpack_type type, enum msgpack_type subty // --- function composition --- // // these will be shadowed unless missing in parameters -const void * const m = (void *)1; -const enum msgpack_type subtype; - -#define COMPOSE_FUNCTION(op, type) \ - { \ - if(!pack || !pack->bin || pack->size == 0) \ - return ERROR(MSGPACK_##type, MSGPACK_ERROR_INVALID_PACK); \ - if(!m) \ +static const void * const m = (void *)1; +static const enum msgpack_type subtype; + +#define COMPOSE_FUNCTION(op, type) \ + { \ + if(!pack || !pack->bin || pack->size == 0) \ + return ERROR(MSGPACK_##type, MSGPACK_ERROR_INVALID_PACK); \ + if(!m) \ return ERROR(MSGPACK_##type, MSGPACK_ERROR_INVALID_ARGUMENT); \ - \ - const enum msgpack_fmt fmt = \ - FMT_FOR_##op(pack, MSGPACK_##type, subtype, m); \ - \ - switch(fmt) { \ - FORMAT_##type(X_##type##_##op) \ - default: \ - return ERROR2(MSGPACK_##type, MSGPACK_ERROR_WRONG_TYPE, \ - fmt_to_type[fmt]); \ - } \ + \ + const enum msgpack_fmt fmt = \ + FMT_FOR_##op(pack, MSGPACK_##type, subtype, m); \ + \ + switch(fmt) { \ + FORMAT_##type(X_##type##_##op) \ + default: \ + return ERROR2(MSGPACK_##type, MSGPACK_ERROR_WRONG_TYPE, \ + fmt_to_type[fmt]); \ + } \ } -// TODO: refactor these things, they are hard to read +// TODO: refactor these, 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) \ pack->bin[0] = x_byte -#define MAKE_X_BOOL(op, x_byte, x_fmt, x_type, x_data) \ - case x_fmt: \ - OP_BOOL_##op(x_byte, pack, m, x_data); \ - MOVE_PACK(pack, 1); \ +#define MAKE_X_BOOL(op, x_byte, x_fmt, \ + x_type, x_data) \ + case x_fmt: \ + OP_BOOL_##op(x_byte, pack, m, x_data); \ + MOVE_PACK(pack, 1); \ return SUCCESS(x_type); + #define OP_INT_READ(_byte, ptr, value, x_conv) \ value = PTOH(x_conv, ptr) #define OP_INT_WRITE(x_byte, ptr, value, x_conv) \ @@ -189,56 +196,80 @@ const enum msgpack_type subtype; (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_##type##_##op(x_byte, pack->bin + (x_offset), m->x_field, x_conv); \ - \ - MOVE_PACK(pack, (x_offset) + (x_length)); \ +#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_##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 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_LENGTH_READ(x_byte, x_offset, x_conv) \ + (x_offset == 1) \ + ? PTOH(x_conv, pack->bin) & ~(uint8_t)x_byte \ + : PTOH(x_conv, pack->bin + 1); +#define OP_RAW_LENGTH_WRITE(x_byte, x_offset, 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); + 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((x_offset) == 1) pack->bin[0] |= (uint8_t)length; \ + else HTOP2(x_conv, length, pack->bin+1); \ + memcpy(pack->bin+(x_offset), m->bin, m->size); #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 = OP_RAW_LENGTH_##op(x_fmt, x_conv); \ - \ - ENOUGH_BYTES(pack, (x_offset) + length, \ - return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \ - OP_RAW_##op(x_byte, x_offset, x_conv); \ - \ - MOVE_PACK(pack, (x_offset) + length); \ - return SUCCESS2(x_type, x_subtype); \ + case x_fmt: { \ + ENOUGH_BYTES(pack, (x_offset), \ + return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \ + size_t length = OP_RAW_LENGTH_##op(x_byte, x_offset, x_conv); \ + \ + ENOUGH_BYTES(pack, (x_offset) + length, \ + return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \ + OP_RAW_##op(x_byte, x_offset, x_conv); \ + \ + MOVE_PACK(pack, (x_offset) + length); \ + return SUCCESS2(x_type, x_subtype); \ } - + + +#define OP_ARRAYORMAP_READ(x_byte, x_offset, x_conv) \ + *m = OP_RAW_LENGTH_READ(x_byte, x_offset, x_conv) +#define OP_ARRAYORMAP_WRITE(x_byte, x_offset, x_conv) \ + pack->bin[0] = x_byte; \ + if((x_offset) == 1) pack->bin[0] |= (uint8_t)*m; \ + else HTOP2(x_conv, *m, pack->bin+1); \ + +#define MAKE_X_ARRAYORMAP(op, x_byte, x_fmt, x_type, \ + x_offset, x_conv, ...) \ + case x_fmt: \ + ENOUGH_BYTES(pack, (x_offset), \ + return ERROR(x_type, MSGPACK_ERROR_UNEXPECTED_END)); \ + OP_ARRAYORMAP_##op(x_byte, x_offset, x_conv); \ + \ + MOVE_PACK(pack, (x_offset)); \ + return SUCCESS(x_type); + // --- 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_ARRAY_READ(...) MAKE_X_ARRAYORMAP(READ, __VA_ARGS__) +#define X_MAP_READ(...) MAKE_X_ARRAYORMAP(READ, __VA_ARGS__) -#define X_BOOL_WRITE(...) MAKE_X_BOOL(WRITE, __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__) +#define X_ARRAY_WRITE(...) MAKE_X_ARRAYORMAP(WRITE, __VA_ARGS__) +#define X_MAP_WRITE(...) MAKE_X_ARRAYORMAP(WRITE, __VA_ARGS__) // int msgpack_read_nil (msgpack_t *pack); int msgpack_read_bool (msgpack_t *pack, bool *m) COMPOSE_FUNCTION(READ, BOOL) @@ -250,8 +281,8 @@ int msgpack_read_raw (msgpack_t *pack, struct mp_bin *m) COMPOSE_FUNCTION(RE // 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); -// int msgpack_read_array (msgpack_t *pack, size_t *m) COMPOSE_FUNCTION(READ, ARRAY) -// int msgpack_read_map (msgpack_t *pack, size_t *m) COMPOSE_FUNCTION(READ, MAP) +int msgpack_read_array (msgpack_t *pack, size_t *m) COMPOSE_FUNCTION(READ, ARRAY) +int msgpack_read_map (msgpack_t *pack, size_t *m) COMPOSE_FUNCTION(READ, MAP) // int msgpack_read_array2 (const msgpack_t *pack, struct mp_array *m); // int msgpack_read_map2 (const msgpack_t *pack, struct mp_map *m); @@ -264,9 +295,8 @@ int msgpack_write_float (msgpack_t *pack, const union mp_float *m, enum msgpac 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); -// int msgpack_write_map (msgpack_t *pack, const size_t *m); - +int msgpack_write_array (msgpack_t *pack, const size_t *m) COMPOSE_FUNCTION(WRITE, ARRAY) +int msgpack_write_map (msgpack_t *pack, const size_t *m) COMPOSE_FUNCTION(WRITE, MAP) // --- helpers --- // @@ -283,13 +313,14 @@ static enum msgpack_fmt pack_fmt(msgpack_t *pack) return byte_to_fmt[byte]; } -#define WRAP_FMT_BOOL(e) \ - case MSGPACK_BOOL: switch((int)*(bool *)m) {e; default: break; } break; +#define WRAP_SWTICH(type, cond, e) case type: switch(cond) { e; default: break; } break; +#define WRAP_IFELSE(type, e) case type: e; break; + +#define WRAP_FMT_BOOL(e) WRAP_SWTICH(MSGPACK_BOOL, (int)*(bool *)m, e); #define X_FMT_BOOL(_byte, x_fmt, x_type, x_data) \ case x_data: return x_fmt; -#define WRAP_FMT_INT(e) \ - case MSGPACK_INT: e; break; +#define WRAP_FMT_INT(e) WRAP_IFELSE(MSGPACK_INT, e) #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 >= CAR x_range) && \ @@ -297,25 +328,30 @@ static enum msgpack_fmt pack_fmt(msgpack_t *pack) return x_fmt; \ else -#define WRAP_FMT_FLOAT(e) \ - case MSGPACK_FLOAT: switch(subtype) {e; default: break; } break; +#define WRAP_FMT_FLOAT(e) WRAP_SWTICH(MSGPACK_FLOAT, subtype, e) #define X_FMT_FLOAT(_byte, x_fmt, _type, x_subtype, _offset, _length, _field, _conv) \ case x_subtype: return x_fmt; -#define WRAP_FMT_RAW(e) \ - case MSGPACK_RAW: e; break; +#define WRAP_FMT_RAW(e) WRAP_IFELSE(MSGPACK_RAW, e) #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 +#define WRAP_FMT_ARRAY(e) WRAP_IFELSE(MSGPACK_ARRAY, e) +#define X_FMT_ARRAY(_byte, x_fmt, _type, _offset, _conv, x_range_max) \ + if(*(size_t *)m <= x_range_max) return x_fmt; else + +#define WRAP_FMT_MAP(e) WRAP_IFELSE(MSGPACK_MAP, e) +#define X_FMT_MAP(...) X_FMT_ARRAY(__VA_ARGS__) + +#define MAIN_TYPES(X) X(BOOL) X(INT) X(FLOAT) X(RAW) X(ARRAY) X(MAP) +#define X_MAIN_TYPES(type) WRAP_FMT_##type(FORMAT_##type(X_FMT_##type)) + 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)) - WRAP_FMT_RAW(FORMAT_RAW(X_FMT_RAW)) + MAIN_TYPES(X_MAIN_TYPES) default: return FMT_UNKNOWN; } -- cgit v1.2.3