aboutsummaryrefslogtreecommitdiff
path: root/msgpack.c
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 /msgpack.c
parent81b8e14fd785141193c62bcd0023815b2a6cb810 (diff)
arrays and maps added
Diffstat (limited to 'msgpack.c')
-rw-r--r--msgpack.c232
1 files changed, 134 insertions, 98 deletions
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;
}