Skip to content

Instantly share code, notes, and snippets.

@Hadaward
Last active May 24, 2024 13:29
Show Gist options
  • Select an option

  • Save Hadaward/b744fe4d8681102cbb41902a890d54f3 to your computer and use it in GitHub Desktop.

Select an option

Save Hadaward/b744fe4d8681102cbb41902a890d54f3 to your computer and use it in GitHub Desktop.
Implementation of Any type in C
#ifndef ANY_H
#define ANY_H
#include <stdbool.h>
#include <stdint.h>
enum Variant {
V_ANY,
V_STRING,
V_CHAR,
V_INT,
V_DOUBLE,
V_FLOAT,
V_LONG,
V_BOOL,
V_NULL,
V_LONG_DOUBLE,
V_POINTER,
};
typedef struct Any {
union {
char c;
char *s;
int i;
double d;
float f;
long l;
long double ld;
void *vp;
bool b;
} value;
enum Variant type;
} Any;
#define typeof(var) _Generic( (var),\
char: V_CHAR,\
char *: V_STRING,\
int: V_INT,\
int *: V_INT,\
double: V_DOUBLE,\
double *: V_DOUBLE,\
float: V_FLOAT,\
float *: V_FLOAT,\
long: V_LONG,\
long *: V_LONG,\
void *: V_POINTER,\
bool: V_BOOL,\
bool *: V_BOOL,\
long double: V_LONG_DOUBLE,\
default: V_NULL)
Any __any__(enum Variant type, void *ptr) {
Any x;
x.type = type;
if (type == V_CHAR) {
x.value.c = *(char *) ptr;
} else if (type == V_STRING) {
x.value.s = (char *) ptr;
} else if (type == V_INT) {
x.value.i = *(int *) ptr;
} else if (type == V_DOUBLE) {
x.value.d = *(double *) ptr;
} else if (type == V_FLOAT) {
x.value.f = *(float *) ptr;
} else if (type == V_LONG) {
x.value.l = *(long *) ptr;
} else if (type == V_LONG_DOUBLE) {
x.value.ld = *(long double *) ptr;
} else if (type == V_BOOL) {
x.value.b = *(bool *) ptr;
} else {
x.value.vp = ptr;
}
return x;
}
#define ptr(value) ((void*)(&(value)))
#define any(v) ({\
enum Variant type = typeof(v);\
__any__(type, ptr(v));\
})
#define unwrap(any, type) *(type *)_unwrap(&(any))
void *_unwrap(Any *any) {
switch (any->type) {
case V_CHAR: return &any->value.c;
case V_STRING: return any->value.s;
case V_INT: return &any->value.i;
case V_DOUBLE: return &any->value.d;
case V_FLOAT: return &any->value.f;
case V_LONG: return &any->value.l;
case V_LONG_DOUBLE: return &any->value.ld;
case V_BOOL: return &any->value.b;
case V_POINTER: return any->value.vp;
default: return NULL;
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment