Created
November 17, 2015 11:01
-
-
Save ThirteenFish/8253ab3a55101bd86455 to your computer and use it in GitHub Desktop.
Fun with C11 _Generic()
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 <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