Last active
December 22, 2023 21:09
-
-
Save Rhomboid/8e48620badbb3d9b4c30 to your computer and use it in GitHub Desktop.
X-Macros for serialization of C structs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdint.h> | |
typedef enum { | |
enOne, | |
enTwo, | |
enThree, | |
invalidMax = 2147483647 | |
} MyEnum; | |
// automatically define a struct and its reader and writer functions simultaneously | |
// typedef { ... } MyStruct; | |
// void fread_MyStruct(MyStruct *obj, FILE *fp) { ... } | |
// void fwrite_MyStruct(MyStruct *obj, FILE *fp) { ... } | |
#define SERIALIZABLE_STRUCT_NAME MyStruct | |
#define SERIALIZABLE_STRUCT_MEMBERS \ | |
SERIALIZABLE_STRUCT_MEMBER(MyEnum, anEnum) \ | |
SERIALIZABLE_STRUCT_MEMBER(uint8_t, aChar) \ | |
SERIALIZABLE_STRUCT_MEMBER(float, aFloat) | |
#include "serializable-struct.h" | |
// repeat as many times as necessary | |
#define SERIALIZABLE_STRUCT_NAME AnotherStruct | |
#define SERIALIZABLE_STRUCT_MEMBERS \ | |
SERIALIZABLE_STRUCT_MEMBER(int, foo) \ | |
SERIALIZABLE_STRUCT_MEMBER(double, bar) \ | |
SERIALIZABLE_STRUCT_MEMBER(short, baz) | |
#include "serializable-struct.h" | |
int main(void) | |
{ | |
MyStruct s; | |
s.anEnum = enTwo; | |
s.aChar = 4; | |
s.aFloat = 3.14f; | |
FILE *fp = fopen("output.dat", "wb"); | |
fwrite_MyStruct(&s, fp); | |
printf("file size: %ld\nstruct size: %zu\n", ftell(fp), sizeof(MyStruct)); | |
fclose(fp); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define SERIALIZABLE_STRUCT_MEMBER(type, identifier) \ | |
type identifier; | |
typedef struct { | |
SERIALIZABLE_STRUCT_MEMBERS | |
} SERIALIZABLE_STRUCT_NAME; | |
#define SERIALIZABLE_STRUCT_MAKENAME(functype, structname) \ | |
functype ## _ ## structname | |
#define SERIALIZABLE_STRUCT_DECLAREFUNC2(functype, structname) \ | |
static inline void SERIALIZABLE_STRUCT_MAKENAME(functype, structname) \ | |
(structname *obj, FILE *fp) | |
#define SERIALIZABLE_STRUCT_DECLAREFUNC(functype) \ | |
SERIALIZABLE_STRUCT_DECLAREFUNC2(functype, SERIALIZABLE_STRUCT_NAME) | |
#undef SERIALIZABLE_STRUCT_MEMBER | |
#define SERIALIZABLE_STRUCT_MEMBER(type, identifier) \ | |
fread(&(obj->identifier), sizeof(type), 1, fp); | |
SERIALIZABLE_STRUCT_DECLAREFUNC(fread) { | |
SERIALIZABLE_STRUCT_MEMBERS | |
} | |
#undef SERIALIZABLE_STRUCT_MEMBER | |
#define SERIALIZABLE_STRUCT_MEMBER(type, identifier) \ | |
fwrite(&(obj->identifier), sizeof(type), 1, fp); | |
SERIALIZABLE_STRUCT_DECLAREFUNC(fwrite) { | |
SERIALIZABLE_STRUCT_MEMBERS | |
} | |
#undef SERIALIZABLE_STRUCT_MEMBER | |
#undef SERIALIZABLE_STRUCT_DECLAREFUNC | |
#undef SERIALIZABLE_STRUCT_DECLAREFUNC2 | |
#undef SERIALIZABLE_STRUCT_MAKENAME | |
#undef SERIALIZABLE_STRUCT_MEMBERS | |
#undef SERIALIZABLE_STRUCT_NAME |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
file size: 9 | |
struct size: 12 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment