Skip to content

Instantly share code, notes, and snippets.

@trya
Last active July 27, 2020 08:21
Show Gist options
  • Save trya/4ccc8d1f07b320c73665fd2579845d5f to your computer and use it in GitHub Desktop.
Save trya/4ccc8d1f07b320c73665fd2579845d5f to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdint.h>
typedef struct fixed_point {
long long i; // integer part
unsigned long long d; // decimal part
} fixed_point;
#define DEFINE_ARRAY_TYPE(T) \
typedef struct array_ ## T { size_t sz; T d[]; } array_ ## T; \
void array_print_ ## T (const array_ ## T *a) \
{ \
printf("{ "); \
if (a->sz > 0) print_ ## T (&a->d[0]); \
for (size_t i = 1; i < a->sz; i++) { \
printf(", "); \
print_ ## T (&a->d[i]); \
} \
printf(" }\n"); \
} \
array_ ## T * array_ ## T ## _new(size_t n) \
{ \
array_ ## T *a = malloc(sizeof(array_ ## T) + sizeof(T[n])); \
if (a) a->sz = n; \
return a; \
} \
array_ ## T * array_ ## T ## _new_zero(size_t n) \
{ \
array_ ## T *a = calloc(sizeof(array_ ## T) + sizeof(T[n]), 1); \
if (a) a->sz = n; \
return a; \
} \
array_ ## T * array_ ## T ## _new_init(size_t n, size_t m, const T v[m]) \
{ \
array_ ## T *a = array_ ## T ## _new(n); \
if (a) { \
size_t i; \
for (i = 0; i < m; i++) a->d[i] = v[i]; \
if (i < n) memset(a->d+i, 0, sizeof(T)*(n-m)); \
} \
return a; \
}
#define ARRAY(T, ...) (T []){ __VA_ARGS__ }
#define ARRAY_SZ(a) (sizeof((a))/sizeof((a)[0]))
#define ARRAY_NEW(T, sz) array_ ## T ## _new((sz))
#define ARRAY_NEW_INIT(T, sz, a) array_ ## T ## _new_init(sz, ARRAY_SZ((a)), (a))
#define ARRAY_NEW_COPY(T, a) array_ ## T ## _new_init(ARRAY_SZ((a)), ARRAY_SZ((a)), (a))
#define print_format(x) _Generic((x), \
char: "%c", \
int: "%d", \
float: "%f", \
double: "%f", \
default: "unknown_type")
#define GEN_PRINT_FUNC(T) \
void print_ ## T (const T *x) \
{ \
printf(print_format(*(x)), *(x)); \
}
#define SUPPORTED_ARRAY_TYPES(X) \
X(char) \
X(int) \
X(float) \
X(double) \
X(fixed_point)
GEN_PRINT_FUNC(char)
GEN_PRINT_FUNC(int)
GEN_PRINT_FUNC(float)
GEN_PRINT_FUNC(double)
void print_fixed_point(const fixed_point *fp)
{
printf("%lld.%llu", fp->i, fp->d);
}
SUPPORTED_ARRAY_TYPES(DEFINE_ARRAY_TYPE)
void array_print_default(void *p) { puts("unknown_array_type"); }
#define array_print_LIST(T) \
array_ ## T *: array_print_ ## T, \
const array_ ## T *: array_print_ ## T,
#define array_print(a) _Generic((a), \
SUPPORTED_ARRAY_TYPES(array_print_LIST) \
default: array_print_default)((a))
void print_string(const array_char *s)
{
printf("%s\n", s->d);
}
int main(void)
{
array_char *s = ARRAY_NEW_COPY(char, "ebin");
array_int *i = ARRAY_NEW_COPY(int, ARRAY(int, 1, 2, 3));
array_float *f = ARRAY_NEW_COPY(float, ARRAY(float, 100, INFINITY, NAN));
array_double *d = ARRAY_NEW_COPY(double, ARRAY(double, 333.333, 222.222, 111.111));
array_fixed_point *fp = ARRAY_NEW_COPY(fixed_point, ARRAY(fixed_point, {1,234}, {90,2143}));
array_print(s);
print_string(s);
array_print(i);
array_print(f);
array_print(d);
array_print(fp);
int i2[] = { 3, 2, 1 };
memcpy(i->d, &i2, sizeof(i2));
array_print(i);
array_int *i3 = ARRAY_NEW_INIT(int, 4, ARRAY(int, 123, 234, 345));
array_print(i3);
array_int *i4 = array_int_new_zero(10);
array_print(i4);
array_int *i5 = array_int_new(0);
array_print(i5);
array_int *i6 = ARRAY_NEW_INIT(int, 4, ARRAY(int, 123, 234, 345, 456, 567));
array_print(i6);
free(s);
free(i);
free(f);
free(d);
free(fp);
free(i3);
free(i4);
free(i5);
free(i6);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment