diff options
author | Alex Xu (Hello71) <alex_y_xu@yahoo.ca> | 2018-08-08 15:16:14 -0400 |
---|---|---|
committer | Alex Xu (Hello71) <alex_y_xu@yahoo.ca> | 2018-08-08 15:16:14 -0400 |
commit | 0183098f9cb37a5389b8ff19dee98a4293752ce6 (patch) | |
tree | 22b8fb52d009192427d48f8c8de1e5831b30521d /readall.c | |
download | random-seed-0183098f9cb37a5389b8ff19dee98a4293752ce6.tar.xz random-seed-0183098f9cb37a5389b8ff19dee98a4293752ce6.zip |
Initial commit
Diffstat (limited to 'readall.c')
-rw-r--r-- | readall.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/readall.c b/readall.c new file mode 100644 index 0000000..9f55697 --- /dev/null +++ b/readall.c @@ -0,0 +1,82 @@ +/* by Nominal Animal, 2017: https://stackoverflow.com/a/44894946 */ + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> + +#include "readall.h" + +/* Size of each input chunk to be + read and allocate for. */ +#ifndef READALL_CHUNK +#define READALL_CHUNK 262144 +#endif + +/* This function returns one of the READALL_ constants above. + If the return value is zero == READALL_OK, then: + (*dataptr) points to a dynamically allocated buffer, with + (*sizeptr) chars read from the file. + The buffer is allocated for one extra char, which is NUL, + and automatically appended after the data. + Initial values of (*dataptr) and (*sizeptr) are ignored. +*/ +int readall(FILE *in, char **dataptr, size_t *sizeptr) +{ + char *data = NULL, *temp; + size_t size = 0; + size_t used = 0; + size_t n; + + /* None of the parameters can be NULL. */ + if (in == NULL || dataptr == NULL || sizeptr == NULL) + return READALL_INVALID; + + /* A read error already occurred? */ + if (ferror(in)) + return READALL_ERROR; + + while (1) { + + if (used + READALL_CHUNK + 1 > size) { + size = used + READALL_CHUNK + 1; + + /* Overflow check. Some ANSI C compilers + may optimize this away, though. */ + if (size <= used) { + free(data); + return READALL_TOOMUCH; + } + + temp = realloc(data, size); + if (temp == NULL) { + free(data); + return READALL_NOMEM; + } + data = temp; + } + + n = fread(data + used, 1, READALL_CHUNK, in); + if (n == 0) + break; + + used += n; + } + + if (ferror(in)) { + free(data); + return READALL_ERROR; + } + + temp = realloc(data, used + 1); + if (temp == NULL) { + free(data); + return READALL_NOMEM; + } + data = temp; + data[used] = '\0'; + + *dataptr = data; + *sizeptr = used; + + return READALL_OK; +} |