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:
46
main.c
46
main.c
@@ -203,22 +203,58 @@ char *ast_to_str(node_t *ast, size_t size)
|
|||||||
return out;
|
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)
|
int main(void)
|
||||||
{
|
{
|
||||||
const char input[] = "[->+<]]";
|
const char *filepath = "./input.txt";
|
||||||
buffer_t *buffer =
|
FILE *handle = fopen(filepath, "r");
|
||||||
buffer_init_str("*internal*", input, sizeof(input) / sizeof(input[0]));
|
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);
|
struct PResult res = parse_input(buffer);
|
||||||
if (res.nodes == NULL)
|
if (res.nodes == NULL)
|
||||||
{
|
{
|
||||||
fputs("Exiting early...\n", stderr);
|
fputs("Exiting early...\n", stderr);
|
||||||
free(buffer);
|
goto error;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
char *str = ast_to_str(res.nodes, res.size);
|
char *str = ast_to_str(res.nodes, res.size);
|
||||||
|
|
||||||
free(str);
|
free(str);
|
||||||
free(res.nodes);
|
free(res.nodes);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
free(file_data);
|
||||||
return 0;
|
return 0;
|
||||||
|
error:
|
||||||
|
if (buffer)
|
||||||
|
free(buffer);
|
||||||
|
if (res.nodes)
|
||||||
|
free(res.nodes);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user