Created
October 5, 2018 14:53
-
-
Save skaslev/eb3adf2ac8745cc60b0d46720bcdf1b1 to your computer and use it in GitHub Desktop.
buf.c
This file contains 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 "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; | |
} |
This file contains 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
#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_ |
This file contains 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 <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; | |
} |
This file contains 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
#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