Skip to content

Instantly share code, notes, and snippets.

@skaslev
Created October 5, 2018 14:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skaslev/eb3adf2ac8745cc60b0d46720bcdf1b1 to your computer and use it in GitHub Desktop.
Save skaslev/eb3adf2ac8745cc60b0d46720bcdf1b1 to your computer and use it in GitHub Desktop.
buf.c
#include "buf.h"
#include "die.h"
void buf_do_realloc_(void **a, size_t nr, size_t sz)
{
struct buf *b;
b = realloc(buf_get_(*a), offsetof(struct buf, data) + nr * sz);
if (!b)
die_errno("realloc");
b->cap = nr;
if (!*a)
b->len = 0;
*a = &b->data;
}
#ifndef BUF_H_
#define BUF_H_
#include <stdlib.h>
#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) \
((type *)((void *)(ptr) - offsetof(type, member)))
/* Based on Sean Barrett's stretchy buffer at http://www.nothings.org/stb/stretchy_buffer.txt
* init: NULL, free: buf_free(), push_back: buf_push(), size: buf_len()
*/
struct buf {
size_t len, cap;
char data[];
};
#define buf_len(a) ((a) ? buf_get_(a)->len : 0)
#define buf_cap(a) ((a) ? buf_get_(a)->cap : 0)
#define buf_free(a) free(buf_get_(a))
#define buf_for_each(it, a) \
for ((it) = (a); (it) < (a) + buf_len(a); (it)++)
#define buf_push(a, v) ({ \
if (buf_len(a) == buf_cap(a)) { \
size_t cap = buf_new_cap_(buf_cap(a)); \
buf_reserve(a, cap); \
} \
(a)[buf_get_(a)->len++] = (v); \
})
#define buf_resize(a, n) ({ \
buf_reserve(a, n); \
if (a) \
buf_get_(a)->len = (n); \
})
#define buf_reserve(a, n) ({ \
if ((n) > buf_cap(a)) \
buf_do_realloc_((void **) &(a), n, sizeof(*(a))); \
})
/* Private */
#define buf_get_(a) \
((a) ? (struct buf *)(container_of(a, struct buf, data)) : NULL)
static inline size_t buf_new_cap_(size_t old_cap)
{
size_t cap = 3 * old_cap / 2;
if (cap < 16)
cap = 16;
return cap;
}
void buf_do_realloc_(void **a, size_t nr, size_t sz);
#endif // BUF_H_
#include <math.h>
#include <stdio.h>
#include "buf.h"
#define my_buf_push(a, v) ({ \
size_t cap, old_cap = buf_cap(a); \
buf_push(a, v); \
cap = buf_cap(a); \
if (old_cap != cap) \
printf("realloc: %ld old: %ld\n", cap, old_cap); \
})
int main(int argc, char **argv)
{
float *a = NULL, *it;
int i;
for (i = 0; i < 10000000000; i++) {
float f = i * i;
my_buf_push(a, f);
my_buf_push(a, pow(f, 1.0 / 3.0));
my_buf_push(a, i);
}
buf_for_each(it, a)
printf("a[%ld] = %f\n", it - a, *it);
return 0;
}
#ifndef DIE_H_
#define DIE_H_
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void die(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
exit(-1);
}
#define die_errno(msg) die("%s: %s", msg, strerror(errno))
#endif // DIE_H_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment