Skip to content

Instantly share code, notes, and snippets.

@RobertDurfee
Last active October 5, 2020 21:31
Show Gist options
  • Save RobertDurfee/3b2222a01f025f9bc42bd52054dc3725 to your computer and use it in GitHub Desktop.
Save RobertDurfee/3b2222a01f025f9bc42bd52054dc3725 to your computer and use it in GitHub Desktop.
A simple, generic implementation of an array with amortized O(1) append in C.
#ifndef LIST_H
#define LIST_H
#include <stdlib.h> // size_t, malloc, realloc, free
#include <stdint.h> // uint32_t
#include <stdio.h> // printf
#include <stdbool.h> // bool
#define TOKENPASTE(X, Y) X ## Y
#define INDENT(DEPTH) printf("%*c", DEPTH * 2, ' ')
#define LIST_CONS(LIST) TOKENPASTE(LIST, Cons)
#define LIST_NEXT(LIST) TOKENPASTE(LIST, Next)
#define LIST_AT(LIST) TOKENPASTE(LIST, At)
#define LIST_EQUALS(LIST) TOKENPASTE(LIST, Equals)
#define LIST_DEBUG(LIST) TOKENPASTE(LIST, Debug)
#define LIST_DES(LIST) TOKENPASTE(LIST, Des)
#define LIST_GEN_DECL(LIST, ELEM) \
\
struct LIST { \
ELEM *elems; \
size_t capacity; \
size_t len; \
}; \
\
struct LIST *LIST_CONS(LIST)(struct LIST *list, size_t capacity); \
\
ELEM *LIST_NEXT(LIST)(struct LIST *list); \
\
ELEM *LIST_AT(LIST)(struct LIST *list, size_t i); \
\
bool LIST_EQUALS(LIST)(const struct LIST *a, const struct LIST *b); \
\
void LIST_DEBUG(LIST)(const struct LIST *list, uint32_t depth); \
\
struct LIST *LIST_DES(LIST)(struct LIST *list);
#define LIST_GEN_DEF(LIST, ELEM, ELEM_EQUALS, ELEM_DEBUG, ELEM_DES) \
\
struct LIST *LIST_CONS(LIST)(struct LIST *list, size_t capacity) { \
list->elems = (ELEM *)malloc(capacity * sizeof(ELEM)); \
list->capacity = capacity; \
list->len = 0; \
return list; \
} \
\
ELEM *LIST_NEXT(LIST)(struct LIST *list) { \
if (list->len == list->capacity) { \
list->capacity *= 2; \
list->elems = (ELEM *)realloc(list->elems, list->capacity * sizeof(ELEM)); \
} \
return &list->elems[list->len]; \
} \
\
ELEM *LIST_AT(LIST)(struct LIST *list, size_t i) { \
return &list->elems[i]; \
} \
\
bool LIST_EQUALS(LIST)(const struct LIST *a, const struct LIST *b) { \
size_t i; \
if (a->len != b->len) { \
return false; \
} \
for (i = 0; i < a->len; i++) { \
if (!ELEM_EQUALS(&a->elems[i], &b->elems[i])) { \
return false; \
} \
} \
return true; \
} \
\
void LIST_DEBUG(LIST)(const struct LIST *list, uint32_t depth) { \
size_t i; \
printf(#LIST " {\n"); \
INDENT(depth); printf(" elems: [\n"); \
for (i = 0; i < list->len; i++) { \
INDENT(depth); ELEM_DEBUG(&list->elems[i], depth + 1); printf(",\n"); \
} \
INDENT(depth); printf(" ],\n"); \
INDENT(depth); printf(" capacity: %lu,\n", list->capacity); \
INDENT(depth); printf(" len: %lu,\n", list->len); \
INDENT(depth); printf("}"); \
} \
\
struct LIST *LIST_DES(LIST)(struct LIST *list) { \
size_t i; \
for (i = 0; i < list->len; i++) { \
ELEM_DES(&list->elems[i]); \
} \
free(list->elems); \
list->capacity = 0; \
list->len = 0; \
return list; \
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment