Skip to content

Instantly share code, notes, and snippets.

@ThirteenFish
Created November 17, 2015 11:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ThirteenFish/8253ab3a55101bd86455 to your computer and use it in GitHub Desktop.
Save ThirteenFish/8253ab3a55101bd86455 to your computer and use it in GitHub Desktop.
Fun with C11 _Generic()
#include <stdio.h>
#include <string.h>
typedef struct {int v;} volume;
typedef struct {int s;} onoff;
struct settings {
int a;
char * b;
volume v;
onoff s;
};
/*---------------------------------------------------------------------------*/
void encode_int (int a, char ** string) {
*string += sprintf(*string, "i32:%x;", a);
}
void encode_char_p(char * b, char ** string) {
*string += sprintf(*string, "str:%s;", b);
}
void encode_volume(volume v, char ** string) {
*string += sprintf(*string, "vol:%d;", v.v);
}
void encode_onoff(onoff s, char ** string) {
*string += sprintf(*string, "swt:%d;", s.s);
}
/*---------------------------------------------------------------------------*/
void decode_int (int * a, char ** string) {
sscanf(*string, "i32:%x;", a);
*string = strchr(*string, ';') + 1;
}
void decode_char_p(char ** b, char ** string) {
sscanf(*string, "str:%[^;];", *b);
*string = strchr(*string, ';') + 1;
}
void decode_volume(volume * v, char ** string) {
sscanf(*string, "vol:%d;", &(v->v));
*string = strchr(*string, ';') + 1;
}
void decode_onoff(onoff * s, char ** string) {
sscanf(*string, "swt:%d;", &(s->s));
*string = strchr(*string, ';') + 1;
}
/*---------------------------------------------------------------------------*/
void print_int (int a, char * prefix) {
printf("%s%d\n", prefix, a);
}
void print_char_p(char * b, char * prefix) {
printf("%s%s\n", prefix, b);
}
void print_volume(volume v, char * prefix) {
printf("%sVolume: %d\n", prefix, v.v);
}
void print_onoff(onoff s, char * prefix) {
printf("%sSwitch: ", prefix);
if(s.s)
puts("on");
else
puts("off");
}
/*---------------------------------------------------------------------------*/
#define visit_settings(settings, func, data) \
do { \
func(settings.a, data); \
func(settings.b, data); \
func(settings.v, data); \
func(settings.s, data); \
} while (0)
#define encode(setting, string) _Generic((setting), \
int: encode_int, \
char *: encode_char_p, \
volume: encode_volume, \
onoff: encode_onoff \
)(setting, string)
#define decode(setting, string) _Generic((setting), \
int: decode_int, \
char *: decode_char_p, \
volume: decode_volume, \
onoff: decode_onoff \
)(&setting, string)
#define print(setting, prefix) _Generic((setting), \
int: print_int, \
char *: print_char_p, \
volume: print_volume, \
onoff: print_onoff \
)(setting, prefix)
/*---------------------------------------------------------------------------*/
int main(void) {
struct settings out = {
.a = 9001,
.b = "Generic text",
.v = {11},
.s = {0},
};
char buffer[255];
char * index = buffer;
visit_settings(out, print, " <- ");
visit_settings(out, encode, &index);
puts(buffer);
char b[15];
struct settings in = {.b=b};
index = buffer;
visit_settings(in, decode, &index);
visit_settings(in, print, " -> ");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment