1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| #define FIELD_LIST \ X(int, id, "ID", FIELD_KEY) \ X(char*, name, "Name", FIELD_REQUIRED) \ X(int, age, "Age", FIELD_OPTIONAL) \ X(float, salary, "Salary", FIELD_OPTIONAL) \ X(time_t, created_at, "Created At", FIELD_READONLY)
typedef enum { FIELD_OPTIONAL = 0x01, FIELD_REQUIRED = 0x02, FIELD_KEY = 0x04, FIELD_READONLY = 0x08 } field_attrs_t;
typedef struct person { #define X(type, name, desc, attrs) type name; FIELD_LIST #undef X } person_t;
typedef struct field_info { const char *name; const char *description; size_t offset; size_t size; field_attrs_t attributes; } field_info_t;
static const field_info_t person_fields[] = { #define X(type, name, desc, attrs) \ { #name, desc, offsetof(person_t, name), sizeof(type), attrs }, FIELD_LIST #undef X };
#define PERSON_FIELD_COUNT (sizeof(person_fields) / sizeof(field_info_t))
void person_serialize(const person_t *person, char *buffer, size_t buffer_size) { size_t offset = 0; #define X(type, name, desc, attrs) \ if (offset < buffer_size) { \ offset += snprintf(buffer + offset, buffer_size - offset, \ #name ": "); \ offset += serialize_##type(person->name, buffer + offset, \ buffer_size - offset); \ if (offset < buffer_size) { \ offset += snprintf(buffer + offset, buffer_size - offset, ", "); \ } \ } FIELD_LIST #undef X }
int person_validate(const person_t *person, char *error_buffer, size_t error_size) { #define X(type, name, desc, attrs) \ if ((attrs & FIELD_REQUIRED) && !validate_##type(person->name)) { \ snprintf(error_buffer, error_size, "Field " #name " is required"); \ return -1; \ } FIELD_LIST #undef X return 0; }
|