aboutsummaryrefslogtreecommitdiff
path: root/msgpack.old.c
diff options
context:
space:
mode:
Diffstat (limited to 'msgpack.old.c')
-rw-r--r--msgpack.old.c244
1 files changed, 244 insertions, 0 deletions
diff --git a/msgpack.old.c b/msgpack.old.c
new file mode 100644
index 0000000..9a7be3c
--- /dev/null
+++ b/msgpack.old.c
@@ -0,0 +1,244 @@
+#include "msgpack.h"
+
+// read big endian ints
+#define M_I16(b) (b[0] << 8) | (b[1])
+#define M_I32(b) (b[0] << 24) | (b[1] << 16) \
+ | (b[2] << 8) | (b[3])
+#define M_I64(b) (b[0] << 56) | (b[1] << 48) \
+ | (b[2] << 40) | (b[3] << 32) \
+ | (b[4] << 24) | (b[5] << 16) \
+ | (b[6] << 8) | (b[7])
+
+// Todo: add memtable for the lengths, the index is the current index from the array,
+// the msgpack_t struct has a pointer to such a table
+// macro making sure there are enough bytes before reading them
+#define ENOUGH_BYTES(pack, n, on_fail) if((pack)->size < (n)) { on_fail; }
+#define EB(pack, n) ENOUGH_BYTES(pack, (n)+1, return 0)
+
+// byte, type, format, length expr, condition
+#define BYTE_FORMATS(X, pack) \
+ X(0xc0, MSGPACK_NIL, FMT_NIL, 0, ;) \
+ X(0xc1, MSGPACK_UNKNOWN, FMT_UNUSED, 0, ;) \
+ X(0xc2, MSGPACK_BOOL, FMT_FALSE, 0, ;) \
+ X(0xc3, MSGPACK_BOOL, FMT_TRUE, 0, ;) \
+ \
+ X(0xc4, MSGPACK_RAW, FMT_BIN8, 1+ pack->bin[1], EB(pack, 1)) \
+ X(0xc5, MSGPACK_RAW, FMT_BIN16, 2+ M_I16(pack->bin+1), EB(pack, 2)) \
+ X(0xc6, MSGPACK_RAW, FMT_BIN32, 4+ M_I32(pack->bin+1), EB(pack, 4)) \
+ X(0xc7, MSGPACK_EXT, FMT_EXT8, 1+ pack->bin[1], EB(pack, 1)) \
+ X(0xc8, MSGPACK_EXT, FMT_EXT16, 2+ M_I16(pack->bin+1), EB(pack, 2)) \
+ X(0xc9, MSGPACK_EXT, FMT_EXT32, 4+ M_I32(pack->bin+1), EB(pack, 4)) \
+ \
+ X(0xca, MSGPACK_FLOAT, FMT_F32, 4, ;) \
+ X(0xcb, MSGPACK_FLOAT, FMT_F64, 8, ;) \
+ X(0xcc, MSGPACK_INT, FMT_U8, 1, ;) \
+ X(0xcd, MSGPACK_INT, FMT_U16, 2, ;) \
+ X(0xce, MSGPACK_INT, FMT_U32, 4, ;) \
+ X(0xcf, MSGPACK_INT, FMT_U64, 8, ;) \
+ X(0xd0, MSGPACK_INT, FMT_I8, 1, ;) \
+ X(0xd1, MSGPACK_INT, FMT_I16, 2, ;) \
+ X(0xd2, MSGPACK_INT, FMT_I32, 4, ;) \
+ X(0xd3, MSGPACK_INT, FMT_I64, 8, ;) \
+ X(0xd4, MSGPACK_EXT, FMT_FIX_EXT1, 1+ 1, ;) \
+ X(0xd5, MSGPACK_EXT, FMT_FIX_EXT2, 1+ 2, ;) \
+ X(0xd6, MSGPACK_EXT, FMT_FIX_EXT4, 1+ 4, ;) \
+ X(0xd7, MSGPACK_EXT, FMT_FIX_EXT8, 1+ 8, ;) \
+ X(0xd8, MSGPACK_EXT, FMT_FIX_EXT16, 1+ 16, ;) \
+ \
+ X(0xd9, MSGPACK_RAW, FMT_STR8, 1+ pack->bin[1], EB(pack, 1)) \
+ X(0xda, MSGPACK_RAW, FMT_STR16, 2+ M_I16(pack->bin+1), EB(pack, 2)) \
+ X(0xdb, MSGPACK_RAW, FMT_STR32, 4+ M_I32(pack->bin+1), EB(pack, 4)) \
+ \
+ X(0xdc, MSGPACK_ARRAY, FMT_ARRAY16, 2+ complex_length(pack, FMT_ARRAY16), EB(pack, 2)) \
+ X(0xdd, MSGPACK_ARRAY, FMT_ARRAY32, 4+ complex_length(pack, FMT_ARRAY32), EB(pack, 4)) \
+ X(0xde, MSGPACK_MAP, FMT_MAP16, 2+ complex_length(pack, FMT_MAP16), EB(pack, 2)) \
+ X(0xdf, MSGPACK_MAP, FMT_MAP32, 4+ complex_length(pack, FMT_MAP32), EB(pack, 4))
+
+// just mask these ranges, don't check them
+// use the logaical and of the ranges as a mask
+
+// range low, range high, type, format, length expr
+#define RANGE_FORMATS(X, pack) \
+ X(0x00, 0x7f, MSGPACK_INT, FMT_FIX_U, 0) \
+ X(0x80, 0x8f, MSGPACK_MAP, FMT_FIX_MAP, complex_length(pack, FMT_FIX_MAP)) \
+ X(0x90, 0x9f, MSGPACK_ARRAY, FMT_FIX_ARRAY, complex_length(pack, FMT_FIX_ARRAY)) \
+ X(0xa0, 0xbf, MSGPACK_STRING, FMT_FIX_STR, pack[0] & 01F) \
+ X(0xe0, 0xff, MSGPACK_INT, FMT_FIX_I, 0)
+
+#define X_TO_ENUM2(_1, _2, fmt, ...) fmt,
+#define X_TO_ENUM3(_1, _2, _3, fmt, ...) fmt,
+
+enum msgpack_fmt {
+ BYTE_FORMATS(X_TO_ENUM2,;)
+ RANGE_FORMATS(X_TO_ENUM3,;)
+};
+
+#define X_TO_FMT_TYPE1(_1, type, fmt, ...) [fmt] = type,
+#define X_TO_FMT_TYPE2(_1, _2, type, fmt, ...) [fmt] = type,
+
+static const enum msgpack_type fmt_to_type[] = {
+ BYTE_FORMATS(X_TO_FMT_TYPE1,;)
+ RANGE_FORMATS(X_TO_FMT_TYPE2,;)
+};
+
+
+static size_t complex_length(msgpack_t *pack, enum msgpack_fmt fmt);
+static size_t pack_lenght(msgpack_t pack);
+static enum msgpack_fmt pack_fmt(msgpack_t pack);
+
+#define SUCCESS(type) (type)
+#define ERROR(type, err, rest) ((rest << 6) | (err << 3) | (type))
+
+#define CHECK_ARGS(type, pack, m) \
+ do { \
+ if(!(pack) || !(pack)->bin || (pack)->size == 0) \
+ return ERROR((type), MSGPACK_ERROR_INVALID_PACK, 0); \
+ if((pack)->bin[0] == 0xc) \
+ return ERROR((type), MSGPACK_ERROR_WRONG_TYPE, MSGPACK_NIL);\
+ if(!(m)) \
+ return ERROR((type), MSGPACK_ERROR_INVALID_ARGUMENT, 0); \
+ } while(0)
+
+int msgpack_read(msgpack_t *pack, msgpack_allocator_t alloc, void **m_ptr);
+
+int msgpack_read_int(msgpack_t *pack, msgpack_int_t *m)
+{
+ CHECK_ARGS(MSGPACK_INT, pack, m);
+
+ enum msgpack_fmt fmt = pack_fmt(pack);
+ switch(fmt) {
+ default:
+ return ERROR(MSGPACK_INT, MSGPACK_ERROR_WRONG_TYPE, fmt_to_type[fmt]);
+ }
+
+ return SUCCESS(MSGPACK_INT);
+}
+
+int msgpack_read_bool(msgpack_t *pack, msgpack_bool_t *m);
+int msgpack_read_float(msgpack_t *pack, msgpack_int_t *m);
+int msgpack_read_string(msgpack_t *pack, msgpack_string_t *m);
+int msgpack_read_bin(msgpack_t *pack, msgpack_bin_t *m);
+
+int msgpack_read_array(msgpack_t *pack, msgpack_array_t *m)
+{
+ CHECK_ARGS(MSGPACK_ARRAY, pack, m);
+
+ enum msgpack_fmt fmt = pack_fmt(pack);
+ size_t offset = 0;
+ size_t elements = 0;
+
+ switch(fmt) {
+ case FMT_FIX_ARRAY:
+ offset = 1;
+ elements = pack->bin[0] & 0x0F;
+ break;
+ case FMT_ARRAY16:
+ offset = 3;
+ ENOUGH_BYTES(pack, offset, return 0);
+ elements = M_I16(pack->bin+1);
+ break;
+ case FMT_ARRAY32:
+ offset = 5;
+ ENOUGH_BYTES(pack, offset, return 0);
+ elements = M_I32(pack->bin+1);
+ break;
+ default:
+ return ERROR(MSGPACK_ARRAY, MSGPACK_ERROR_WRONG_TYPE, fmt_to_type[fmt]);
+ }
+
+ if(m->length < elements) {
+ m->length = elements;
+ return ERROR(MSGPACK_ARRAY, MSGPACK_ERROR_UNSUFFICIENT_CAPACITY, 0);
+ }
+
+ for(size_t i = 0; i < elements; i++) {
+ msgpack_t new_pack = {pack->bin+offset, size-offset};
+ size_t len = pack_lenght(&new_pack) + 1;
+
+ ENOUGH_BYTES(pack, offset + len,
+ return ERROR(MSGPACK_ARRAY, MSGPACK_ERROR_UNEXPECTED_END, 0));
+
+ m->members[i].bin = pack->bin + offset;
+ m->members[i].size = len;
+
+ offset += len;
+ }
+
+ return SUCCESS(MSGPACK_ARRAY);
+}
+
+int msgpack_read_map(msgpack_t *pack, msgpack_map_t *m);
+
+static size_t complex_length(msgpack_t *pack, enum msgpack_fmt fmt)
+{
+ ENOUGH_BYTES(pack, 1, return 0);
+
+ size_t offset = 0;
+ size_t elements = 0;
+
+ switch(fmt) {
+ case FMT_FIX_MAP:
+ case FMT_FIX_ARRAY:
+ offset = 1;
+ elements = pack->bin[0] & 0x0F;
+ break;
+ case FMT_MAP16:
+ case FMT_ARRAY16:
+ offset = 3;
+ ENOUGH_BYTES(pack, offset, return 0);
+ elements = M_I16(pack->bin+1);
+ break;
+ case FMT_MAP32:
+ case FMT_ARRAY32:
+ offset = 5;
+ ENOUGH_BYTES(pack, offset, return 0);
+ elements = M_I32(pack->bin+1);
+ break;
+ }
+
+ if(fmt_to_type[fmt] == MSGPACK_MAP) elements *= 2;
+
+ for(size_t i = 0; i < elements; i++) {
+ msgpack_t new_pack = {pack->bin+offset, size-offset};
+ size_t len = pack_lenght(new_pack) + 1;
+ if(len == 0) return 0;
+
+ offset += len;
+ ENOUGH_BYTES(pack, offset, return 0);
+ }
+
+ return offset - 1;
+}
+
+#define WRAP_BYTE_FORMATS(X, pack) \
+ switch(pack->bin[0]) { BYTE_FORMATS(X, pack) }
+#define WRAP_RANGE_FORMATS(X, pack) \
+ char byte = pack->bin[0]; RANGE_FORMATS(X, pack) {}
+
+#define BYTE_TO_LENGHT(byte, _type, _fmt, length_expr, cond) \
+ case byte: cond; return (length_expr) +1; break;
+#define BYTE_TO_TYPE(byte, type, _fmt _length_expr, _cond) \
+ case byte: return type; break;
+
+#define RANGE_TO_LENGHT(bytel, byteh, _type, _fmt, length_expr) \
+ if(bytel <= byte && byteh >= pack->bin[0]) { return (length_expr) + 1; } else
+#define RANGE_TO_TYPE(bytel, byteh, type, _fmt, _length) \
+ if(bytel <= byte && byteh >= pack->bin[0]) { return type; } else
+
+static size_t pack_lenght(msgpack_t pack)
+{
+ ENOUGH_BYTES(pack, 1, return 0);
+ WRAP_BYTE_FORMATS(BYTE_TO_LENGTH, pack);
+ WRAP_RANGE_FORMATS(RANGE_TO_LENGTH, pack);
+
+ return 0;
+}
+
+static enum msgpack_fmt pack_fmt(msgpack_t pack)
+{
+ ENOUGH_BYTES(pack, 1, return 0);
+ WRAP_BYTE_FORMATS(BYTE_TO_TYPE, pack);
+ WRAP_RANGE_FORMATS(RANGE_TO_TYPE, pack);
+
+ return FMT_UNUSED;
+}