Add in_serial / out_serial for variant
This commit is contained in:
1 parent
12ba563416
commit
dcf7a94728
1 file changed
+111
-45
+111
-45
@@ -83,6 +83,10 @@
|
||||
(VARIANTI_DEFINE_OUT_STR(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL2(IN_STR, INIT, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_IN_STR(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL(OUT_SERIAL, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_OUT_SERIAL(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL2(IN_SERIAL, INIT, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_IN_SERIAL(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL(INIT_MOVE, __VA_ARGS__) \
|
||||
(VARIANTI_DEFINE_INIT_MOVE(name, __VA_ARGS__),) \
|
||||
VARIANTI_IF_ALL(INIT_MOVE, __VA_ARGS__) \
|
||||
@@ -107,9 +111,11 @@
|
||||
#define VARIANTI_GET_HASH(f,t,o) M_GET_HASH o
|
||||
#define VARIANTI_GET_EQUAL(f,t,o) M_GET_EQUAL o
|
||||
#define VARIANTI_GET_STR(f,t,o) M_GET_GET_STR o
|
||||
#define VARIANTI_GET_PARSE_STR(f,t,o) M_GET_PARSE_STR o
|
||||
#define VARIANTI_GET_OUT_STR(f,t,o) M_GET_OUT_STR o
|
||||
#define VARIANTI_GET_IN_STR(f,t,o) M_GET_IN_STR o
|
||||
#define VARIANTI_GET_PARSE_STR(f,t,o) M_GET_PARSE_STR o
|
||||
#define VARIANTI_GET_OUT_SERIAL(f,t,o) M_GET_OUT_SERIAL o
|
||||
#define VARIANTI_GET_IN_SERIAL(f,t,o) M_GET_IN_SERIAL o
|
||||
#define VARIANTI_GET_SWAP(f,t,o) M_GET_SWAP o
|
||||
|
||||
#define VARIANTI_CALL_INIT(t, ...) M_APPLY_API(VARIANTI_GET_INIT t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
@@ -122,9 +128,11 @@
|
||||
#define VARIANTI_CALL_HASH(t, ...) M_APPLY_API(VARIANTI_GET_HASH t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_EQUAL(t, ...) M_APPLY_API(VARIANTI_GET_EQUAL t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_GET_STR(t, ...) M_APPLY_API(VARIANTI_GET_STR t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_PARSE_STR(t, ...) M_APPLY_API(VARIANTI_GET_PARSE_STR t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_OUT_STR(t, ...) M_APPLY_API(VARIANTI_GET_OUT_STR t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_IN_STR(t, ...) M_APPLY_API(VARIANTI_GET_IN_STR t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_PARSE_STR(t, ...) M_APPLY_API(VARIANTI_GET_PARSE_STR t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_OUT_SERIAL(t, ...) M_APPLY_API(VARIANTI_GET_OUT_SERIAL t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_IN_SERIAL(t, ...) M_APPLY_API(VARIANTI_GET_IN_SERIAL t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
#define VARIANTI_CALL_SWAP(t, ...) M_APPLY_API(VARIANTI_GET_SWAP t, VARIANTI_GET_OPLIST t, __VA_ARGS__)
|
||||
|
||||
#define VARIANTI_DEFINE_TYPE(name, ...) \
|
||||
@@ -402,6 +410,46 @@
|
||||
break;
|
||||
|
||||
|
||||
#define VARIANTI_DEFINE_PARSE_STR(name, ...) \
|
||||
static inline bool M_C(name, _parse_str)(M_C(name,_t) el, \
|
||||
const char str[], \
|
||||
const char **endp) { \
|
||||
assert (str != NULL && el != NULL); \
|
||||
bool success = false; \
|
||||
char variantTypeBuf[M_MAX_IDENTIFIER_LENGTH+1]; \
|
||||
int c = *str++; \
|
||||
unsigned int i = 0; \
|
||||
M_C(name, _clean)(el); \
|
||||
if (c != '@') goto exit; \
|
||||
/* First read the name of the type */ \
|
||||
c = *str++; \
|
||||
while (c != '@' && c != 0 && i < sizeof(variantTypeBuf) - 1) { \
|
||||
variantTypeBuf[i++] = c; \
|
||||
c = *str++; \
|
||||
} \
|
||||
if (c != '@') goto exit; \
|
||||
variantTypeBuf[i++] = 0; \
|
||||
assert(i < sizeof(variantTypeBuf)); \
|
||||
/* In function of the type */ \
|
||||
if (strcmp(variantTypeBuf, "EMPTY") == 0) { \
|
||||
el->type = M_C(name, _EMPTY); \
|
||||
} \
|
||||
M_MAP2(VARIANTI_DEFINE_PARSE_STR_FUNC , name, __VA_ARGS__) \
|
||||
else goto exit; \
|
||||
success = (*str++ == '@'); \
|
||||
exit: \
|
||||
if (endp) *endp = str; \
|
||||
return success; \
|
||||
}
|
||||
#define VARIANTI_DEFINE_PARSE_STR_FUNC(name, a) \
|
||||
else if (strcmp (variantTypeBuf, M_APPLY (M_AS_STR, VARIANTI_GET_FIELD a)) == 0) { \
|
||||
el->type = M_C4(name, _, VARIANTI_GET_FIELD a, _value); \
|
||||
VARIANTI_CALL_INIT(a, el ->value . VARIANTI_GET_FIELD a ); \
|
||||
bool b = VARIANTI_CALL_PARSE_STR(a, el -> value . VARIANTI_GET_FIELD a, str, &str); \
|
||||
if (!b) goto exit; \
|
||||
}
|
||||
|
||||
|
||||
#define VARIANTI_DEFINE_OUT_STR(name, ...) \
|
||||
static inline void M_C(name, _out_str)(FILE *f, \
|
||||
M_C(name,_t) const el) { \
|
||||
@@ -424,10 +472,11 @@
|
||||
static inline bool M_C(name, _in_str)(M_C(name,_t) el, \
|
||||
FILE *f) { \
|
||||
assert (f != NULL && el != NULL); \
|
||||
/* A buffer of 400 bytes should be more than enough for all variant names... */ \
|
||||
char variantTypeBuf[400]; \
|
||||
char variantTypeBuf[M_MAX_IDENTIFIER_LENGTH+1]; \
|
||||
M_C(name, _clean)(el); \
|
||||
if (fgetc(f) != '@') return false; \
|
||||
/* First read the name of the type */ \
|
||||
bool b = true; \
|
||||
int c = fgetc(f); \
|
||||
unsigned int i = 0; \
|
||||
while (c != '@' && c != EOF && i < sizeof(variantTypeBuf) - 1) { \
|
||||
@@ -437,63 +486,80 @@
|
||||
if (c != '@') return false; \
|
||||
variantTypeBuf[i++] = 0; \
|
||||
assert(i < sizeof(variantTypeBuf)); \
|
||||
M_C(name, _clear)(el); \
|
||||
/* In function of the type */ \
|
||||
if (strcmp(variantTypeBuf, "EMPTY") == 0) { \
|
||||
el->type = M_C(name, _EMPTY); \
|
||||
} \
|
||||
M_MAP2(VARIANTI_DEFINE_IN_STR_FUNC , name, __VA_ARGS__) \
|
||||
else return false; \
|
||||
return fgetc(f) == '@'; \
|
||||
else { b = false; } \
|
||||
return b && (fgetc(f) == '@'); \
|
||||
}
|
||||
#define VARIANTI_DEFINE_IN_STR_FUNC(name, a) \
|
||||
else if (strcmp (variantTypeBuf, M_APPLY (M_AS_STR, VARIANTI_GET_FIELD a)) == 0) { \
|
||||
el->type = M_C4(name, _, VARIANTI_GET_FIELD a, _value); \
|
||||
VARIANTI_CALL_INIT(a, el ->value . VARIANTI_GET_FIELD a ); \
|
||||
bool b = VARIANTI_CALL_IN_STR(a, el -> value . VARIANTI_GET_FIELD a, f); \
|
||||
if (!b) return false; \
|
||||
b = VARIANTI_CALL_IN_STR(a, el -> value . VARIANTI_GET_FIELD a, f); \
|
||||
}
|
||||
|
||||
|
||||
#define VARIANTI_DEFINE_PARSE_STR(name, ...) \
|
||||
static inline bool M_C(name, _parse_str)(M_C(name,_t) el, \
|
||||
const char str[], \
|
||||
const char **endp) { \
|
||||
assert (str != NULL && el != NULL); \
|
||||
bool success = false; \
|
||||
/* A buffer of 400 bytes should be more than enough for all variant names... */ \
|
||||
char variantTypeBuf[400]; \
|
||||
int c = *str++; \
|
||||
unsigned int i = 0; \
|
||||
if (c != '@') goto exit; \
|
||||
/* First read the name of the type */ \
|
||||
c = *str++; \
|
||||
while (c != '@' && c != 0 && i < sizeof(variantTypeBuf) - 1) { \
|
||||
variantTypeBuf[i++] = c; \
|
||||
c = *str++; \
|
||||
#define VARIANTI_STRINGIFY_NAME(a) \
|
||||
M_APPLY(M_AS_STR, VARIANTI_GET_FIELD a)
|
||||
|
||||
#define VARIANTI_DEFINE_OUT_SERIAL(name, ...) \
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _out_serial)(m_serial_write_t f, \
|
||||
M_C(name,_t) const el) { \
|
||||
const int field_max = M_NARGS(__VA_ARGS__); \
|
||||
static const char *const field_name[] = \
|
||||
{ M_REDUCE(VARIANTI_STRINGIFY_NAME, M_ID, __VA_ARGS__) }; \
|
||||
assert (f != NULL && f->interface != NULL && el != NULL); \
|
||||
m_serial_return_code_t ret; \
|
||||
switch (el->type) { \
|
||||
case M_C(name, _EMPTY): \
|
||||
return f->interface->write_variant_start(f, field_name, field_max, -1); \
|
||||
break; \
|
||||
M_MAP2(VARIANTI_DEFINE_OUT_SERIAL_FUNC , name, __VA_ARGS__) \
|
||||
default: assert(false); break; \
|
||||
} \
|
||||
if (c != '@') goto exit; \
|
||||
variantTypeBuf[i++] = 0; \
|
||||
assert(i < sizeof(variantTypeBuf)); \
|
||||
M_C(name, _clear)(el); \
|
||||
/* In function of the type */ \
|
||||
if (strcmp(variantTypeBuf, "EMPTY") == 0) { \
|
||||
el->type = M_C(name, _EMPTY); \
|
||||
} \
|
||||
M_MAP2(VARIANTI_DEFINE_PARSE_STR_FUNC , name, __VA_ARGS__) \
|
||||
else goto exit; \
|
||||
success = (*str++ == '@'); \
|
||||
exit: \
|
||||
if (endp) *endp = str; \
|
||||
return success; \
|
||||
ret |= f->interface->write_variant_end(f); \
|
||||
return ret & M_SERIAL_FAIL; \
|
||||
}
|
||||
#define VARIANTI_DEFINE_PARSE_STR_FUNC(name, a) \
|
||||
else if (strcmp (variantTypeBuf, M_APPLY (M_AS_STR, VARIANTI_GET_FIELD a)) == 0) { \
|
||||
el->type = M_C4(name, _, VARIANTI_GET_FIELD a, _value); \
|
||||
#define VARIANTI_DEFINE_OUT_SERIAL_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
ret = f->interface->write_variant_start(f, field_name, field_max, \
|
||||
M_C4(name, _, VARIANTI_GET_FIELD a, _value) -1); \
|
||||
VARIANTI_CALL_OUT_SERIAL(a, f, el -> value . VARIANTI_GET_FIELD a); \
|
||||
break;
|
||||
|
||||
|
||||
#define VARIANTI_DEFINE_IN_SERIAL(name, ...) \
|
||||
static inline m_serial_return_code_t \
|
||||
M_C(name, _in_serial)(M_C(name,_t) el, \
|
||||
m_serial_read_t f) { \
|
||||
const int field_max = M_NARGS(__VA_ARGS__); \
|
||||
static const char *const field_name[] = \
|
||||
{ M_REDUCE(VARIANTI_STRINGIFY_NAME, M_ID, __VA_ARGS__) }; \
|
||||
assert (f != NULL && f->interface != NULL && el != NULL); \
|
||||
m_serial_return_code_t ret; \
|
||||
int id = -1; \
|
||||
M_C(name, _clean)(el); \
|
||||
ret = f->interface->read_variant_start(f, field_name, field_max, &id); \
|
||||
if (ret != M_SERIAL_OK_CONTINUE) return ret; \
|
||||
assert (id >= 0 && id < field_max); \
|
||||
el->type = id+1; \
|
||||
switch (id+1) { \
|
||||
M_MAP2(VARIANTI_DEFINE_IN_SERIAL_FUNC , name, __VA_ARGS__) \
|
||||
default: assert(false); break; \
|
||||
} \
|
||||
if (ret != M_SERIAL_OK_DONE) \
|
||||
ret = f->interface->read_variant_end(f); \
|
||||
return ret; \
|
||||
}
|
||||
#define VARIANTI_DEFINE_IN_SERIAL_FUNC(name, a) \
|
||||
case M_C4(name, _, VARIANTI_GET_FIELD a, _value): \
|
||||
VARIANTI_CALL_INIT(a, el ->value . VARIANTI_GET_FIELD a ); \
|
||||
bool b = VARIANTI_CALL_PARSE_STR(a, el -> value . VARIANTI_GET_FIELD a, str, &str); \
|
||||
if (!b) goto exit; \
|
||||
}
|
||||
ret = VARIANTI_CALL_IN_SERIAL(a, el -> value . VARIANTI_GET_FIELD a, f); \
|
||||
break; \
|
||||
|
||||
|
||||
#define VARIANTI_DEFINE_CLEAN_FUNC(name, ...) \
|
||||
|
||||
Reference in new issue
Block a user