aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkartofen <mladenovnasko0@gmail.com>2025-04-19 18:23:06 +0300
committerkartofen <mladenovnasko0@gmail.com>2025-04-19 18:23:06 +0300
commitcb71851d51bf4af8e13c3917b361b2aac81d6733 (patch)
tree441a8c60490e8a48a87b2f4eb86eb4047315f52e
parent81b8e14fd785141193c62bcd0023815b2a6cb810 (diff)
arrays and maps added
-rw-r--r--README.md2
-rw-r--r--builtfiles.dd.m44
-rw-r--r--msgpack.c232
-rw-r--r--msgpack.h2
-rw-r--r--test.c69
5 files changed, 199 insertions, 110 deletions
diff --git a/README.md b/README.md
index dc59126..f72d5bf 100644
--- a/README.md
+++ b/README.md
@@ -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)
diff --git a/msgpack.c b/msgpack.c
index c125a2d..07433b1 100644
--- a/msgpack.c
+++ b/msgpack.c
@@ -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;
}
diff --git a/msgpack.h b/msgpack.h
index 6171664..98ff5cc 100644
--- a/msgpack.h
+++ b/msgpack.h
@@ -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 --
*
diff --git a/test.c b/test.c
index 6b405dd..8ed77a5 100644
--- a/test.c
+++ b/test.c
@@ -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};