diff options
author | kartofen <mladenovnasko0@gmail.com> | 2025-04-19 18:23:06 +0300 |
---|---|---|
committer | kartofen <mladenovnasko0@gmail.com> | 2025-04-19 18:23:06 +0300 |
commit | cb71851d51bf4af8e13c3917b361b2aac81d6733 (patch) | |
tree | 441a8c60490e8a48a87b2f4eb86eb4047315f52e | |
parent | 81b8e14fd785141193c62bcd0023815b2a6cb810 (diff) |
arrays and maps added
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | builtfiles.dd.m4 | 4 | ||||
-rw-r--r-- | msgpack.c | 232 | ||||
-rw-r--r-- | msgpack.h | 2 | ||||
-rw-r--r-- | test.c | 69 |
5 files changed, 199 insertions, 110 deletions
@@ -2,6 +2,8 @@ This is a simple implementation of the MessagePack specification (`spec.md` in the tree). +Heard C is dangerous, so the library is just macros + This library uses NO dynamic allocations. ### Usage diff --git a/builtfiles.dd.m4 b/builtfiles.dd.m4 index 70d747a..0919275 100644 --- a/builtfiles.dd.m4 +++ b/builtfiles.dd.m4 @@ -12,12 +12,12 @@ define(substitue, [esyscmd([ ifdef([LIBDIR], [ define([LIBS]) - define([LIBS_SOURCE], [match_extension([build], [so]) match_extension([build], [a])]) + define([LIBS_SOURCE], [match_extension(BIN, [so]) match_extension([build], [a])]) define([LIBS_TARGET], [substitue(LIBS_SOURCE, BIN, LIBDIR)])]) ifdef([INCLUDEDIR], [ define([HEADERS]) - define([HEADERS_SOURCE], [match_extension([build], [h])]) + define([HEADERS_SOURCE], [match_extension(BIN, [h])]) define([HEADERS_TARGET], [substitue(HEADERS_SOURCE, BIN, INCLUDEDIR)])]) divert(0) @@ -2,10 +2,16 @@ #include <endian.h> // endianness #include <string.h> // 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; } @@ -136,8 +136,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); 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); /* -- MessagePack Types -- * @@ -1,7 +1,6 @@ #include <stdio.h> #include <string.h> #include <inttypes.h> -#include <unistd.h> #include <sys/sendfile.h> #include "msgpack.h" @@ -46,9 +45,9 @@ static FILE *logfp; #define logbuf(...) OVERLOAD_MACRO_4(__VA_ARGS__, _logbuf4, _logbuf3, _, _) (__VA_ARGS__) #define logbytes(...) logbuf(__VA_ARGS__, "0x%hhx") -// copy source fp from its file position indicator -// to dest fp using sendfile (logfprintf is for that) -static int fsendfile(FILE *dest, FILE *source) +// sendfile for file pointers +// when count is -1, copy to the end +static ssize_t fsendfile(FILE *dest, FILE *source, long *offset, ssize_t count) { fflush(dest); fflush(source); @@ -56,12 +55,15 @@ static int fsendfile(FILE *dest, FILE *source) long cur = ftell(source); fseek(source, 0, SEEK_END); long end = ftell(source); + + if(!offset) offset = &cur; + if(count < 0) + count = end - *offset; - int fd = fileno(source); - return sendfile(fileno(dest), fd, &cur, end - cur); + fseek(source, count + *offset, SEEK_SET); + return sendfile(fileno(dest), fileno(source), offset, count); } - static int passed_test_counter; static int failed_test_counter; static int failed_asserts; @@ -72,7 +74,7 @@ static int failed_asserts; call; \ assert("Failed Test Condition", \ prev_failed_asserts == failed_asserts, \ - body); \ + body; logprintf("\n")); \ } while(0) #define TEST(test) \ @@ -86,7 +88,7 @@ static int failed_asserts; printf("[PASSED] "#test"\n"); \ passed_test_counter++; \ } \ - fsendfile(stdout, logfp) \ + fsendfile(stdout, logfp, NULL, -1) \ ? printf("\n") : 0; \ } while(0) @@ -95,6 +97,8 @@ int test_bool(); int test_int(); int test_float(); int test_raw(); +int test_array(); +int test_map(); int test_compound(); int main(void) @@ -106,6 +110,8 @@ int main(void) TEST(test_int()); TEST(test_float()); TEST(test_raw()); + TEST(test_array()); + TEST(test_map()); TEST(test_compound()); printf("------------------------------\n"); @@ -334,6 +340,51 @@ int test_raw() return failed_asserts; } +#define make_arrayormap_1(stype, btype) \ + void stype##_1(uint8_t *bin, size_t size, size_t value) \ + { \ + uint8_t b[64] = {0}; \ + size_t v = {0}; \ + \ + MSGPACK_CHECK2(msgpack_read_##stype(&msgpack_init(bin, size, NULL), &v), \ + (t, e, a), \ + BODY_SUCCESS_1(t, btype), \ + BODY_FAILED_1(t, e, a)); \ + \ + assert(value == v, logvar(v, "%zu")); \ + \ + MSGPACK_CHECK2(msgpack_write_##stype(&msgpack_init(b, sizeof(b), NULL), &value), \ + (t, e, a), \ + BODY_SUCCESS_1(t, btype), \ + BODY_FAILED_1(t, e, a)); \ + \ + assert(memcmp(b, bin, size) == 0, logbytes(b, size)); \ + } + +make_arrayormap_1(array, MSGPACK_ARRAY) + +int test_array() +{ + failed_asserts = 0; + + check_condition(array_1("\x95", 1, 5),); + check_condition(array_1("\xdc\x00\x11", 3, 17),); + + return failed_asserts; +} + +make_arrayormap_1(map, MSGPACK_MAP) + +int test_map() +{ + failed_asserts = 0; + + check_condition(map_1("\x85", 1, 5),); + check_condition(map_1("\xde\x00\x11", 3, 17),); + + return failed_asserts; +} + void compound_1() { uint8_t bin[] = {0x0A, 0xCF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01}; |