From 9c6e78990e76367e683a429cd5a9637b1ac94542 Mon Sep 17 00:00:00 2001 From: kartofen Date: Sun, 30 Mar 2025 01:48:04 +0200 Subject: some more formats and a build system --- .gitignore | 2 + build.ninja | 6 + build.sh | 6 - main | Bin 29120 -> 0 bytes main.c | 105 ------------------ msgpack.c | 358 ++++++++++++++++++++++++++++++------------------------------ msgpack.h | 71 ++++++------ ninja.m4 | 44 ++++++++ test.c | 110 +++++++++++++++++++ 9 files changed, 375 insertions(+), 327 deletions(-) create mode 100644 .gitignore create mode 100644 build.ninja delete mode 100755 build.sh delete mode 100755 main delete mode 100644 main.c create mode 100644 ninja.m4 create mode 100644 test.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea35e10 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +bin +.ninja_* diff --git a/build.ninja b/build.ninja new file mode 100644 index 0000000..2f1d0b0 --- /dev/null +++ b/build.ninja @@ -0,0 +1,6 @@ +rule gen + command = m4 ninja.m4 > build.ninja + generator = 1 + +build bootstrap: gen +default bootstrap diff --git a/build.sh b/build.sh deleted file mode 100755 index 504f926..0000000 --- a/build.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -set -xe - -gcc -g -Wall -Wextra main.c msgpack.c -o main -valgrind ./main diff --git a/main b/main deleted file mode 100755 index 2dcf90b..0000000 Binary files a/main and /dev/null differ diff --git a/main.c b/main.c deleted file mode 100644 index 3468c01..0000000 --- a/main.c +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include "msgpack.h" - -#define _IN " " - -#define assert(c) assert2(c, ;) -#define assert2(c, b) \ - do { \ - if(!(c)) { \ - fprintf(stderr, "Assertion error '%s' in %s:%d\n", #c, __FILE__, __LINE__); \ - b; \ - failed_asserts++; \ - } \ - } while (0); - -#define logvar(v, fmt) logvar2(v, v, fmt) -#define logvar2(n, v, fmt) printf(_IN #n" = "fmt"\n", v) - -#define logbuf(b, l, fmt) logbuf(b, b, l, fmt) -#define logbuf2(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"); \ - } while(0) - - -#define logbytes(b, l) logbytes(b, b, l) -#define logbytes2(n, b, l) logbuf2(n, b, l, "0x%hhx") - -#define make_template(call, body) \ - do { \ - int prev_failed_asserts = failed_asserts; \ - call; \ - assert2(prev_failed_asserts == failed_asserts, body); \ - } while(0) - -static int passed_test_counter; -static int failed_test_counter; -static int failed_asserts; - -int test_bool(); -int test_int(); - -#define CHECK(test) \ - do { \ - if(test) { \ - printf("[FAILED] "#test"\n"); \ - failed_test_counter++; \ - } else { \ - printf("[PASSED] "#test"\n"); \ - passed_test_counter++; \ - } \ - } while(0) - -int main(void) -{ - CHECK(test_bool()); - // CHECK(test_int()); - - printf("\n------------------------------\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; -} - -void bool_1(char *buf, size_t size, int value) -{ - int b; - MSGPACK_CHECK2(msgpack_read_bool(&msgpack_init(buf, size, NULL), &b), (t, e, a), - { - assert2(t == MSGPACK_BOOL, logvar2(t, msgpack_type_string[t], "%s")); - }, { - assert(0); - // log variables - return; - }); - - assert2(b == value, logvar(b, "%d")); -} - -#define bool_template(n, _buf, _value) \ - make_template(bool_##n(_buf, sizeof(_buf), _value), { \ - logbytes2(buf, _buf, sizeof(_buf)); \ - logvar2(value, _value, "%d"); \ - }); \ - -int test_bool() -{ - failed_asserts = 0; - - bool_template(1, (char []){0xC2}, 1); - bool_template(1, (char []){0xC3}, 0); - - return failed_asserts; -} - -// void test_int() -// { -// char buf[] = {0xD3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01}; -// char buf[] = {0xCC, 0xFF}; -// } diff --git a/msgpack.c b/msgpack.c index bd4efdf..f20a54d 100644 --- a/msgpack.c +++ b/msgpack.c @@ -1,15 +1,15 @@ #include "msgpack.h" #include -#define I8(b) (*(int8_t*)(b)) -#define I16(b) ((int16_t)be16toh(*(uint16_t *)(b))) -#define I32(b) ((int32_t)be32toh(*(uint32_t *)(b))) -#define I64(b) ((int64_t)be64toh(*(uint64_t *)(b))) +#define TO_I8(b) (*(int8_t*)(b)) +#define TO_I16(b) ((int16_t)be16toh(*(uint16_t *)(b))) +#define TO_I32(b) ((int32_t)be32toh(*(uint32_t *)(b))) +#define TO_I64(b) ((int64_t)be64toh(*(uint64_t *)(b))) -#define U8(b) (*(uint8_t*)(b)) -#define U16(b) ((uint16_t)be16toh(*(uint16_t *)(b))) -#define U32(b) ((uint32_t)be32toh(*(uint32_t *)(b))) -#define U64(b) ((uint64_t)be64toh(*(uint64_t *)(b))) +#define TO_U8(b) (*(uint8_t*)(b)) +#define TO_U16(b) ((uint16_t)be16toh(*(uint16_t *)(b))) +#define TO_U32(b) ((uint32_t)be32toh(*(uint32_t *)(b))) +#define TO_U64(b) ((uint64_t)be64toh(*(uint64_t *)(b))) #define ENOUGH_BYTES(pack, n, on_fail) if((pack)->size < (n)) { on_fail; } @@ -26,47 +26,47 @@ X(0xC0, FMT_NIL, MSGPACK_NIL, ;, 1, 0) // byte, fmt, type, _, offset, length, data -#define FORMAT_BOOL(X) \ - X(0xC2, FMT_BOOL_TRUE, MSGPACK_BOOL, ;, 1, 0, 1) \ - X(0xC3, FMT_BOOL_FALSE, MSGPACK_BOOL, ;, 1, 0, 0) +#define FORMAT_BOOL(X) \ + X(0xC2, FMT_BOOL_TRUE, MSGPACK_BOOL, ;, 1, 0, true) \ + X(0xC3, FMT_BOOL_FALSE, MSGPACK_BOOL, ;, 1, 0, false) // byte, fmt, type, subtype, offset, length, data -#define FORMAT_INT(X) \ - X(0x00, FMT_FIX_UINT, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 0, m->u = U8(pack->bin)) \ - X(0XE0, FMT_FIX_INT, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 0, m->i = I8(pack->bin)) \ - X(0xCC, FMT_U8, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 1, m->u = U8(pack->bin+1)) \ - X(0xCD, FMT_U16, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 2, m->u = U16(pack->bin+1)) \ - X(0xCE, FMT_U32, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 4, m->u = U32(pack->bin+1)) \ - X(0xCF, FMT_U64, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 8, m->u = U64(pack->bin+1)) \ - X(0xD0, FMT_I8, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 1, m->i = I8(pack->bin+1)) \ - X(0xD1, FMT_I16, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 2, m->i = I16(pack->bin+1)) \ - X(0xD2, FMT_I32, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 4, m->i = I32(pack->bin+1)) \ - X(0xD3, FMT_I64, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 8, m->i = I64(pack->bin+1)) \ +#define FORMAT_INT(X) \ + X(0x00, FMT_FIX_UINT, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 0, TO_U8(pack->bin)) \ + X(0XE0, FMT_FIX_INT, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 0, TO_I8(pack->bin)) \ + X(0xCC, FMT_U8, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 1, TO_U8(pack->bin+1)) \ + X(0xCD, FMT_U16, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 2, TO_U16(pack->bin+1)) \ + X(0xCE, FMT_U32, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 4, TO_U32(pack->bin+1)) \ + X(0xCF, FMT_U64, MSGPACK_INT, MSGPACK_INT_UNSIGNED, 1, 8, TO_U64(pack->bin+1)) \ + X(0xD0, FMT_I8, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 1, TO_I8(pack->bin+1)) \ + X(0xD1, FMT_I16, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 2, TO_I16(pack->bin+1)) \ + X(0xD2, FMT_I32, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 4, TO_I32(pack->bin+1)) \ + X(0xD3, FMT_I64, MSGPACK_INT, MSGPACK_INT_SIGNED, 1, 8, TO_I64(pack->bin+1)) // byte, fmt, type, subtype, offset, length, data #define FORMAT_FLOAT(X) \ - X(0xCA, FMT_FLOAT, MSGPACK_FLOAT, MSGPACK_FLOAT_32, 1, 4, m->_u = U32(pack->bin+1)) \ - X(0xCB, FMT_DOUBLE, MSGPACK_FLOAT, MSGPACK_FLOAT_64, 1, 8, m->_u = U64(pack->bin+1)) \ - -// byte, fmt, type, subtype, offset, length -#define FORMAT_RAW(X) \ - X(0xA0, FMT_FIX_STR, MSGPACK_RAW, MSGPACK_RAW_STRING, 1, pack->bin[0] & 1) \ - X(0xC4, FMT_BIN8, MSGPACK_RAW, MSGPACK_RAW_BIN, 1, pack->bin[1]) \ - X(0xC5, FMT_BIN16, MSGPACK_RAW, MSGPACK_RAW_BIN, 3, U16(pack->bin+1)) \ - X(0xC6, FMT_BIN32, MSGPACK_RAW, MSGPACK_RAW_BIN, 5, U32(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, U16(pack->bin+1)) \ - X(0xDB, FMT_STR32, MSGPACK_RAW, MSGPACK_RAW_STRING, 5, U32(pack->bin+1)) + X(0xCA, FMT_FLOAT, MSGPACK_FLOAT, MSGPACK_FLOAT_32, 1, 4, TO_U32(pack->bin+1)) \ + X(0xCB, FMT_DOUBLE, MSGPACK_FLOAT, MSGPACK_FLOAT_64, 1, 8, TO_U64(pack->bin+1)) + +// 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] & 0x1F) \ + X(0xC4, FMT_BIN8, MSGPACK_RAW, MSGPACK_RAW_BIN, 1, pack->bin[1]) \ + X(0xC5, FMT_BIN16, MSGPACK_RAW, MSGPACK_RAW_BIN, 3, TO_U16(pack->bin+1)) \ + X(0xC6, FMT_BIN32, MSGPACK_RAW, MSGPACK_RAW_BIN, 5, TO_U32(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, TO_U16(pack->bin+1)) \ + X(0xDB, FMT_STR32, MSGPACK_RAW, MSGPACK_RAW_STRING, 5, TO_U32(pack->bin+1)) // 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, U16(pack->bin+1), 3, elements_length(pack, fmt)) \ - X(0xDD, FMT_ARRAY32, MSGPACK_ARRAY, U32(pack->bin+1), 5, elements_length(pack, fmt)) + X(0xDC, FMT_ARRAY16, MSGPACK_ARRAY, TO_U16(pack->bin+1), 3, elements_length(pack, fmt)) \ + X(0xDD, FMT_ARRAY32, MSGPACK_ARRAY, TO_U32(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 * (U16(pack->bin+1)), 3, elements_length(pack, fmt)) \ - X(0xDF, FMT_MAP32, MSGPACK_MAP, 2 * (U16(pack->bin+1)), 5, elements_length(pack, fmt)) + X(0xDE, FMT_MAP16, MSGPACK_MAP, 2 * (TO_U16(pack->bin+1)), 3, elements_length(pack, fmt)) \ + X(0xDF, FMT_MAP32, MSGPACK_MAP, 2 * (TO_U32(pack->bin+1)), 5, elements_length(pack, fmt)) #define FORMAT_EXT(X) @@ -78,7 +78,7 @@ FORMAT_RAW (X) \ FORMAT_ARRAY(X) \ FORMAT_MAP (X) \ - FORMAT_EXT (X) + FORMAT_EXT (X) #define EXPAND(X) X #define X_FMT_ENUM(_byte, fmt, ...) fmt, @@ -97,173 +97,111 @@ static const enum msgpack_fmt byte_to_fmt[] = { }; static enum msgpack_fmt pack_fmt(const msgpack_t *pack); -static size_t elements_length(msgpack_t *pack, enum msgpack_fmt fmt); -static size_t pack_size(msgpack_t *pack); - +// static size_t elements_length(msgpack_t *pack, enum msgpack_fmt fmt); +// static size_t pack_size(msgpack_t *pack); #define SUCCESS(type) SUCCESS2(type, 0) #define ERROR(type, err) ERROR2(type, err, 0) #define SUCCESS2(type, rest) \ - ((rest << 6) | (type)) + (((rest) << 6) | (type)) #define ERROR2(type, err, rest) \ - ((1 << (sizeof(int)*8-1))| (rest << 6) | (err << 3) | (type)) - -#define CHECK_READ_ARGS(type, pack, m) \ - do { \ - if(!(pack) || !(pack)->bin || (pack)->size == 0) \ - return ERROR((type), MSGPACK_ERROR_INVALID_PACK); \ - if((pack)->bin[0] == 0xc) \ - return ERROR2((type), MSGPACK_ERROR_WRONG_TYPE, MSGPACK_NIL); \ - if(!(m)) \ - return ERROR((type), MSGPACK_ERROR_INVALID_ARGUMENT); \ - } while(0) - - + ((1 << (sizeof(int)*8-1))| ((rest) << 6) | ((err) << 3) | (type)) -#define X_READ_INT(_byte, x_fmt, x_type, x_subtype, x_offset, x_length, x_data) \ - case x_fmt: { \ - ENOUGH_BYTES(pack, (x_offset) + (x_length), \ - return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \ - x_data; \ - return SUCCESS2(x_type, x_subtype); \ - } - -int msgpack_read_int(const msgpack_t *pack, union mp_int *m) -{ - CHECK_READ_ARGS(MSGPACK_INT, pack, m); +#define CHECK_PACK(type, pack) \ + if(!(pack) || !(pack)->bin || (pack)->size == 0) \ + return ERROR((type), MSGPACK_ERROR_INVALID_PACK) - enum msgpack_fmt fmt = pack_fmt(pack); +#define CHECK_ARG(type, m) \ + if(!(m)) \ + return ERROR((type), MSGPACK_ERROR_INVALID_ARGUMENT) - switch(fmt) { - FORMAT_INT(X_READ_INT) - default: - return ERROR2(MSGPACK_INT, MSGPACK_ERROR_WRONG_TYPE, fmt_to_type[fmt]); - } -} +#define MOVE_PACK(pack, sz) \ + do { \ + pack->bin += (sz); \ + pack->size -= (sz); \ + } while(0) -#define X_READ_BOOL(_byte, x_fmt, x_type, _, _offset, _length, x_data) \ - case x_fmt: { \ - *m = x_data; \ - return SUCCESS(x_type); \ +#define READ_FUNCTION(type) \ + { \ + CHECK_PACK(MSGPACK_##type, pack); \ + CHECK_ARG (MSGPACK_##type, m); \ + \ + enum msgpack_fmt fmt = pack_fmt(pack); \ + \ + switch(fmt) { \ + FORMAT_##type(X_READ_##type) \ + default: \ + return ERROR2(MSGPACK_##type, MSGPACK_ERROR_WRONG_TYPE, \ + fmt_to_type[fmt]); \ + } \ } -int msgpack_read_bool(const msgpack_t *pack, int *m) -{ - CHECK_READ_ARGS(MSGPACK_BOOL, pack, m); - enum msgpack_fmt fmt = pack_fmt(pack); +#define X_READ_BOOL(_byte, x_fmt, x_type, _, x_offset, x_length, x_data) \ + case x_fmt: \ + MOVE_PACK(pack, (x_offset)); \ + *m = x_data; \ + return SUCCESS(x_type); - switch(fmt) { - FORMAT_BOOL(X_READ_BOOL) - default: - return ERROR2(MSGPACK_BOOL, MSGPACK_ERROR_WRONG_TYPE, fmt_to_type[fmt]); - } -} +#define X_READ_INT(_byte, x_fmt, x_type, x_subtype, x_offset, x_length, x_data) \ + case x_fmt: \ + ENOUGH_BYTES(pack, (x_offset) + (x_length), \ + return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \ + MOVE_PACK(pack, (x_offset) + (x_length)); \ + \ + m->u = x_data; \ + return SUCCESS2(x_type, x_subtype); #define X_READ_FLOAT(...) X_READ_INT(__VA_ARGS__) -int msgpack_read_float(const msgpack_t *pack, union mp_float *m) -{ - CHECK_READ_ARGS(MSGPACK_FLOAT, pack, m); - - enum msgpack_fmt fmt = pack_fmt(pack); +#define X_READ_RAW(_byte, x_fmt, x_type, x_subtype, x_offset, x_length) \ + case x_fmt: \ + ENOUGH_BYTES(pack, (x_offset), \ + return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \ + ENOUGH_BYTES(pack, (size_t)(x_offset) + (x_length), \ + return ERROR2(x_type, MSGPACK_ERROR_UNEXPECTED_END, x_subtype)); \ + MOVE_PACK(pack, (x_offset) + (x_length)); \ + \ + m->bin = pack->bin + (x_offset); \ + m->size = (x_length); \ + return SUCCESS2(x_type, x_subtype); - switch(fmt) { - FORMAT_FLOAT(X_READ_FLOAT) - default: - return ERROR2(MSGPACK_FLOAT, MSGPACK_ERROR_WRONG_TYPE, fmt_to_type[fmt]); - } -} +#define X_READ_EXT(...) X_READ_RAW(__VA_ARGS__) -int msgpack_read_raw (const msgpack_t *pack, struct mp_bin *m); -int msgpack_read_raw_cpy (const msgpack_t *pack, struct mp_bin *m); -int msgpack_read_ext (const msgpack_t *pack, struct mp_bin *m); -int msgpack_read_ext_cpy (const msgpack_t *pack, struct mp_bin *m); - -int msgpack_read_array (msgpack_t *pack, size_t *length); -int msgpack_read_map (msgpack_t *pack, size_t *length); -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 CHECK_WRITE_ARGS(type, pack, m) \ - do { \ - if(!(pack) || !(pack)->bin || (pack)->size == 0) \ - return ERROR((type), MSGPACK_ERROR_INVALID_PACK); \ - if((pack)->bin[0] == 0xc) \ - return ERROR2((type), MSGPACK_ERROR_WRONG_TYPE, MSGPACK_NIL); \ - if(!(m)) \ - return ERROR((type), MSGPACK_ERROR_INVALID_ARGUMENT); \ - } while(0) +#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)); \ + MOVE_PACK(pack, (x_offset)); \ + \ + *m = x_elements; \ + return SUCCESS(x_type); -int msgpack_write_int (msgpack_t *pack, const union mp_int *m, int subtype) - ;// { - -// } +#define X_READ_MAP(...) X_READ_ARRAY(__VA_ARGS__) -int msgpack_write_bool (msgpack_t *pack, const int *m); -int msgpack_write_float (msgpack_t *pack, const union mp_float *m, int subtype); +int msgpack_read_bool (msgpack_t *pack, bool *m) READ_FUNCTION(BOOL) +int msgpack_read_int (msgpack_t *pack, union mp_int *m) READ_FUNCTION(INT) +int msgpack_read_float (msgpack_t *pack, union mp_float *m) READ_FUNCTION(FLOAT) -int msgpack_write_raw (msgpack_t *pack, const struct mp_bin *m, int subtype); -int msgpack_write_ext (msgpack_t *pack, const struct mp_bin *m, int subtype); +int msgpack_read_raw (msgpack_t *pack, struct mp_bin *m) READ_FUNCTION(RAW) +// int msgpack_read_raw_cpy (msgpack_t *pack, struct mp_bin *m); +int msgpack_read_ext (msgpack_t *pack, struct mp_bin *m) READ_FUNCTION(EXT) +// int msgpack_read_ext_cpy (msgpack_t *pack, struct mp_bin *m); -int msgpack_write_array (msgpack_t *pack, const size_t *length); -int msgpack_write_map (msgpack_t *pack, const size_t *length); +int msgpack_read_array (msgpack_t *pack, size_t *m) READ_FUNCTION(ARRAY) +int msgpack_read_map (msgpack_t *pack, size_t *m) READ_FUNCTION(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); +int msgpack_write_int (msgpack_t *pack, const union mp_int *m, enum msgpack_type subtype); +int msgpack_write_bool (msgpack_t *pack, const bool *m); +int msgpack_write_float (msgpack_t *pack, const union mp_float *m, enum msgpack_type subtype); -#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; +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); -static size_t elements_length(msgpack_t *pack, enum msgpack_fmt fmt) -{ - size_t offset = 0; - size_t elements = 0; +int msgpack_write_array (msgpack_t *pack, const size_t *m); +int msgpack_write_map (msgpack_t *pack, const size_t *m); - 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; -} #define X_MASK_RANGE(range_low, range_high) \ if(byte >= range_low && byte <= range_high) \ @@ -273,8 +211,64 @@ static size_t pack_size(msgpack_t *pack) static enum msgpack_fmt pack_fmt(const msgpack_t *pack) { ENOUGH_BYTES(pack, 1, return 0); - unsigned char byte = pack->bin[0]; + uint8_t byte = pack->bin[0]; RANGES(X_MASK_RANGE){}; return byte_to_fmt[byte]; } + +// #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/msgpack.h b/msgpack.h index fc3ab9a..7eff711 100644 --- a/msgpack.h +++ b/msgpack.h @@ -3,6 +3,7 @@ #include #include +#include /* -- Data structures -- * @@ -40,19 +41,18 @@ */ typedef struct mp_msgpack { - char *bin; + uint8_t *bin; size_t size; - struct mp_membuf { - uintptr_t offset; - size_t *buf; - } *membuf; + // struct mp_membuf { + // uintptr_t offset; + // size_t *buf; + // } *membuf; } msgpack_t; #define msgpack_init(bin, size, membuf) \ - ((msgpack_t){(bin), (size), (membuf)}) -#define membuf_init(uintptr_bin, size_t_buf) \ - ((struct mp_membuf){(offset), (buf)}) + ((msgpack_t){(bin), (size)}) +// ((msgpack_t){(bin), (size), (membuf)}) union mp_int { int64_t i; @@ -62,7 +62,12 @@ union mp_int { union mp_float { float f; double d; - uint64_t _u; + uint64_t u; +}; + +struct mp_bin { + uint8_t* bin; + size_t size; }; struct mp_array { @@ -76,11 +81,6 @@ struct mp_map { size_t length; }; -struct mp_bin { - char* bin; - size_t size; -}; - struct mp_timestamp { // ... }; @@ -111,30 +111,33 @@ struct mp_timestamp { * */ -int msgpack_read_int (const msgpack_t *pack, union mp_int *m); -int msgpack_read_bool (const msgpack_t *pack, int *m); -int msgpack_read_float (const msgpack_t *pack, union mp_float *m); +enum msgpack_type; -int msgpack_read_raw (const msgpack_t *pack, struct mp_bin *m); -int msgpack_read_raw_cpy (const msgpack_t *pack, struct mp_bin *m); -int msgpack_read_ext (const msgpack_t *pack, struct mp_bin *m); -int msgpack_read_ext_cpy (const msgpack_t *pack, struct mp_bin *m); +int msgpack_read_nil (msgpack_t *pack); +int msgpack_read_int (msgpack_t *pack, union mp_int *m); +int msgpack_read_bool (msgpack_t *pack, bool *m); +int msgpack_read_float (msgpack_t *pack, union mp_float *m); + +int msgpack_read_raw (msgpack_t *pack, struct mp_bin *m); +// int msgpack_read_raw_cpy (msgpack_t *pack, struct mp_bin *m); +int msgpack_read_ext (msgpack_t *pack, struct mp_bin *m); +// int msgpack_read_ext_cpy (msgpack_t *pack, struct mp_bin *m); int msgpack_read_array (msgpack_t *pack, size_t *length); int msgpack_read_map (msgpack_t *pack, size_t *length); -int msgpack_read_array2 (const msgpack_t *pack, struct mp_array *m); -int msgpack_read_map2 (const msgpack_t *pack, struct mp_map *m); +// int msgpack_read_array2 (const msgpack_t *pack, struct mp_array *m); +// int msgpack_read_map2 (const msgpack_t *pack, struct mp_map *m); -int msgpack_write_int (msgpack_t *pack, const union mp_int *m, int subtype); -int msgpack_write_bool (msgpack_t *pack, const int *m); -int msgpack_write_float (msgpack_t *pack, const union mp_float *m, int subtype); +int msgpack_write_int (msgpack_t *pack, const union mp_int *m, enum msgpack_type subtype); +int msgpack_write_bool (msgpack_t *pack, const bool *m); +int msgpack_write_float (msgpack_t *pack, const union mp_float *m, enum msgpack_type subtype); -int msgpack_write_raw (msgpack_t *pack, const struct mp_bin *m, int subtype); -int msgpack_write_ext (msgpack_t *pack, const struct mp_bin *m, int subtype); +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 *length); -int msgpack_write_map (msgpack_t *pack, const size_t *length); +int msgpack_write_array (msgpack_t *pack, const size_t *m); +int msgpack_write_map (msgpack_t *pack, const size_t *m); /* -- MessagePack Types -- * @@ -157,9 +160,9 @@ int msgpack_write_map (msgpack_t *pack, const size_t *length); X(MSGPACK_ARRAY) \ X(MSGPACK_MAP) \ X(MSGPACK_EXT) \ - X(MSGPACK_UNKNOWN) \ #define MSGPACK_SUBTYPES(X) \ + X(MSGPACK_UNKNOWN) \ X(MSGPACK_INT_SIGNED) \ X(MSGPACK_INT_UNSIGNED) \ X(MSGPACK_FLOAT_32) \ @@ -170,11 +173,11 @@ int msgpack_write_map (msgpack_t *pack, const size_t *length); #define MSGPACK_ERRORS(X) \ X(MSGPACK_ERROR_UNKNOWN) \ + X(MSGPACK_ERROR_INVALID_PACK) \ + X(MSGPACK_ERROR_INVALID_ARGUMENT) \ X(MSGPACK_ERROR_WRONG_TYPE) \ X(MSGPACK_ERROR_UNSUFFICIENT_CAPACITY) \ - X(MSGPACK_ERROR_UNEXPECTED_END) \ - X(MSGPACK_ERROR_INVALID_PACK) \ - X(MSGPACK_ERROR_INVALID_ARGUMENT) + X(MSGPACK_ERROR_UNEXPECTED_END) #define X_TO_ENUM(e) e, #define X_TO_STRING(e) [e] = #e, diff --git a/ninja.m4 b/ninja.m4 new file mode 100644 index 0000000..98824ff --- /dev/null +++ b/ninja.m4 @@ -0,0 +1,44 @@ +changequote([,]) + +cflags = ifdef([PROD], [], [-std=c99 -Wall -Wextra -g -D_DEFAULT_SOURCE]) +bin = bin +m4flags = + +rule cc + command = gcc -MD -MF $out.d $cflags -c $in -o $out + depfile = $out.d +rule ar + command = ar rcs $out $in + +build $bin/msgpack.o: cc msgpack.c +build $bin/msgpack.a: ar $bin/msgpack.o +build $bin/msgpack.so: cc msgpack.c + cflags = $cflags -fPIC -shared + +rule elf + command = gcc $cflags $in -o $out +rule run + command = valgrind -s --leak-check=full --show-leak-kinds=all $in + +build $bin/test.o: cc test.c +build $bin/test: elf $bin/msgpack.o $bin/test.o + +build static: phony $bin/msgpack.a +build shared: phony $bin/msgpack.so +build header: phony # TODO write it +build test: run $bin/test + +ifdef([PROD], [default test], [default header]) + +rule gen + command = m4 $m4flags ninja.m4 > build.ninja + generator = 1 + +build build.ninja: gen | ninja.m4 + +ifdef([PROD], [dnl +build dev: gen +], [dnl +build prod: gen + m4flags = -D [PROD] +]) diff --git a/test.c b/test.c new file mode 100644 index 0000000..b8fd68b --- /dev/null +++ b/test.c @@ -0,0 +1,110 @@ +#include +#include "msgpack.h" + +#define _IN " " + +#define assert(c) assert2(c, ;) +#define assert2(c, b) \ + do { \ + if(!(c)) { \ + fprintf(stderr, "Assertion error '%s' in %s:%d\n", #c, __FILE__, __LINE__); \ + b; \ + failed_asserts++; \ + } \ + } while (0); + +#define logvar(v, fmt) logvar2(v, v, fmt) +#define logvar2(n, v, fmt) printf(_IN #n" = "fmt"\n", v) + +#define logbuf(b, l, fmt) logbuf(b, b, l, fmt) +#define logbuf2(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"); \ + } while(0) + + +#define logbytes(b, l) logbytes(b, b, l) +#define logbytes2(n, b, l) logbuf2(n, b, l, "0x%hhx") + +#define make_template(call, body) \ + do { \ + int prev_failed_asserts = failed_asserts; \ + call; \ + assert2(prev_failed_asserts == failed_asserts, body); \ + } while(0) + +static int passed_test_counter; +static int failed_test_counter; +static int failed_asserts; + +int test_bool(); +int test_int(); + +#define CHECK(test) \ + do { \ + if(test) { \ + printf("[FAILED] "#test"\n"); \ + failed_test_counter++; \ + } else { \ + printf("[PASSED] "#test"\n"); \ + passed_test_counter++; \ + } \ + } while(0) + +// the functions in main form a test suite + +int main(void) +{ + CHECK(test_bool()); + // CHECK(test_int()); + + printf("\n------------------------------\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; +} + +void bool_1(uint8_t *buf, size_t size, bool value) +{ + bool b; + MSGPACK_CHECK2(msgpack_read_bool(&msgpack_init(buf, size, NULL), &b), (t, e, a), + { + assert2(t == MSGPACK_BOOL, logvar2(t, msgpack_type_string[t], "%s")); + }, { + (void)e; + (void)a; + assert(0); + // log variables + return; + }); + + assert2(b == value, logvar(b, "%d")); +} + +#define bool_template(n, _buf, _value) \ + make_template(bool_##n(_buf, sizeof(_buf), _value), { \ + logbytes2(buf, _buf, sizeof(_buf)); \ + logvar2(value, _value, "%d"); \ + }); \ + +int test_bool() +{ + failed_asserts = 0; + + bool_template(1, (uint8_t []){0xC2}, true); + bool_template(1, (uint8_t []){0xC3}, false); + bool_template(1, (uint8_t []){0xC1}, false); + + return failed_asserts; +} + +// void test_int() +// { +// char buf[] = {0xD3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01}; +// char buf[] = {0xCC, 0xFF}; +// } -- cgit v1.2.3