Chunk allocator for file handling

Apparently you can't just `fseek` because it's "not portable" and
"deeply offensive" or whatever, so here's a really dirty chunk based
allocator which uses `fread` to just read chunks of data at a time and
basically runs around this issue.

While it's slower than an fseek solution for general files, this
solution allows pipes and other _weird_ things that count as "files"
to just werk.
This commit is contained in:
2023-09-02 15:52:40 +01:00
parent 7d369f6fad
commit 89b9c0f94d

46
main.c
View File

@@ -203,22 +203,58 @@ char *ast_to_str(node_t *ast, size_t size)
return out;
}
#define MAX(a, b) (a > b ? a : b)
char *fread_all(FILE *fp)
{
const size_t CHUNK_SIZE = 1024, MULT = 2;
struct
{
char *data;
size_t used, available;
} buffer = {calloc(CHUNK_SIZE, sizeof(*buffer.data)), 0, CHUNK_SIZE};
size_t acc = 0, bytes_read = 0;
while ((bytes_read = fread(buffer.data + acc, sizeof(*buffer.data),
CHUNK_SIZE, fp)) != 0)
{
buffer.used += bytes_read;
acc += bytes_read;
if (buffer.used + CHUNK_SIZE >= buffer.available)
{
buffer.available = MAX(buffer.available * MULT, buffer.used + CHUNK_SIZE);
buffer.data = realloc(buffer.data, buffer.available);
}
}
buffer.data = realloc(buffer.data, buffer.used + 1);
buffer.data[buffer.used] = '\0';
return buffer.data;
}
int main(void)
{
const char input[] = "[->+<]]";
buffer_t *buffer =
buffer_init_str("*internal*", input, sizeof(input) / sizeof(input[0]));
const char *filepath = "./input.txt";
FILE *handle = fopen(filepath, "r");
char *file_data = fread_all(handle);
fclose(handle);
buffer_t *buffer = buffer_init_str(filepath, file_data, strlen(file_data));
struct PResult res = parse_input(buffer);
if (res.nodes == NULL)
{
fputs("Exiting early...\n", stderr);
free(buffer);
return 1;
goto error;
}
char *str = ast_to_str(res.nodes, res.size);
free(str);
free(res.nodes);
free(buffer);
free(file_data);
return 0;
error:
if (buffer)
free(buffer);
if (res.nodes)
free(res.nodes);
return 1;
}