Implement caching for file streams

This commit is contained in:
bumbread 2022-06-24 14:54:51 +11:00
parent 1e58a85f02
commit c2cc9e5129
3 changed files with 78 additions and 18 deletions

View File

@ -239,6 +239,7 @@ size_t strnlen_s(const char *s, size_t maxsize) {
} }
char *strdup(const char *str1) { char *strdup(const char *str1) {
if(str1 == NULL) return NULL;
size_t len = strlen(str1); size_t len = strlen(str1);
char *copy = calloc(len+1, 1); char *copy = calloc(len+1, 1);
strcpy(copy, str1); strcpy(copy, str1);

View File

@ -1,4 +1,6 @@
#define __STDC_WANT_LIB_EXT2__ 1
#include <stdio.h> #include <stdio.h>
#include <win.h> #include <win.h>
#include <stddef.h> #include <stddef.h>
@ -7,6 +9,7 @@
#include <threads.h> #include <threads.h>
#include <uchar.h> #include <uchar.h>
#include <errno.h> #include <errno.h>
#include <string.h>
enum str_type { enum str_type {
STR_R, STR_R,
@ -33,6 +36,7 @@ struct FILE {
str_mode mode; str_mode mode;
int buftype; int buftype;
size_t bufsize; size_t bufsize;
int bufidx;
char *buffer; char *buffer;
mbstate_t mbstate; mbstate_t mbstate;
mtx_t lock; mtx_t lock;
@ -59,13 +63,20 @@ static inline FILE *new_file(
) { ) {
FILE *file = malloc(sizeof(FILE)); FILE *file = malloc(sizeof(FILE));
if(file == NULL) return NULL; if(file == NULL) return NULL;
mtx_init(&file->lock, mtx_recursive);
file->handle = handle; file->handle = handle;
file->name = name; // TODO: strdup this file->name = strdup(name);
file->type = type; file->type = type;
file->flags = flags; file->flags = flags;
file->mode = mode; file->mode = mode;
// Buffer for cache
file->buftype = buftype;
file->bufsize = bufsize;
file->buffer = buffer;
file->bufidx = 0;
// Multibyte state
file->mbstate = (mbstate_t){0}; file->mbstate = (mbstate_t){0};
mtx_init(&file->lock, mtx_recursive); // Append to list of all streams
if(file_list_last != NULL) { if(file_list_last != NULL) {
file_list_last->next = file; file_list_last->next = file;
file->prev = file_list_last; file->prev = file_list_last;
@ -86,9 +97,8 @@ static inline void dispose_file(FILE *file) {
// Only close the file if it's not a standard handle // Only close the file if it's not a standard handle
if(file->name) { if(file->name) {
CloseHandle(file->handle); CloseHandle(file->handle);
//TODO: free(file->name); free(file->name);
} }
// TODO: flush streams
FILE *prev = file->prev; FILE *prev = file->prev;
FILE *next = file->next; FILE *next = file->next;
if(prev != NULL) prev->next = next; if(prev != NULL) prev->next = next;
@ -128,6 +138,7 @@ int setvbuf(
int mode, int mode,
size_t size size_t size
) { ) {
mtx_lock(&stream->lock);
if(mode == _IONBF) { if(mode == _IONBF) {
stream->buftype = mode; stream->buftype = mode;
stream->buffer = NULL; stream->buffer = NULL;
@ -146,24 +157,52 @@ int setvbuf(
stream->buftype = mode; stream->buftype = mode;
stream->buffer = buf; stream->buffer = buf;
stream->bufsize = size; stream->bufsize = size;
mtx_unlock(&stream->lock);
return 0; return 0;
} }
void setbuf(FILE *restrict stream, char *restrict buf) {
int mode = _IOFBF;
if(buf == NULL) {
mode = _IONBF;
}
setvbuf(stream, buf, mode, BUFSIZ);
}
int fflush(FILE *stream) { int fflush(FILE *stream) {
if(stream->mode == _IOFBF) { mtx_lock(&stream->lock);
if(stream->buftype != _IONBF) {
DWORD written;
BOOL ok = WriteFile(
stream->handle,
stream->buffer,
stream->bufidx,
&written,
NULL
);
if(!ok) {
errno = EIO;
return EOF;
} }
else if(stream->mode == _IONBF) { stream->bufidx = 0;
} }
mtx_unlock(&stream->lock);
return 0; return 0;
} }
int fputc(int c, FILE *stream) { static int try_fputc(FILE *stream, char c) {
mtx_lock(&stream->lock); if(stream->buftype != _IONBF) {
stream->buffer[stream->bufidx++] = c;
if(stream->bufidx > stream->bufsize) {
return fflush(stream);
}
if(stream->buftype == _IOLBF && c == '\n') {
return fflush(stream);
}
return c;
}
DWORD written; DWORD written;
BOOL ok = WriteFile(stream->handle, &c, 1, &written, NULL); BOOL ok = WriteFile(stream->handle, &c, 1, &written, NULL);
mtx_unlock(&stream->lock);
if(!ok) { if(!ok) {
errno = EIO; errno = EIO;
return EOF; return EOF;
@ -171,9 +210,28 @@ int fputc(int c, FILE *stream) {
return c; return c;
} }
void setbuf(FILE *restrict stream, char *restrict buf) { static int try_fputs(FILE *stream, char *str, size_t len) {
if(buf != NULL) for(size_t i = 0; i != len; ++i) {
setvbuf(stream, buf, _IOFBF, BUFSIZ); int cw = try_fputc(stream, str[i]);
else if(cw == EOF) return EOF;
setvbuf(stream, buf, _IONBF, BUFSIZ); }
return 1;
}
int fputc(int c, FILE *stream) {
mtx_lock(&stream->lock);
int res = try_fputc(stream, c);
mtx_unlock(&stream->lock);
return res;
}
int fputs(const char *restrict s, FILE *stream) {
mtx_lock(&stream->lock);
while(*s) {
int res = try_fputc(stream, *s);
if(res == EOF) return EOF;
++s;
}
mtx_unlock(&stream->lock);
return 1;
} }

View File

@ -2,6 +2,7 @@
#include <stdio.h> #include <stdio.h>
int main() { int main() {
for(int i = 0; i != 512; ++i)
fputc('Z', stdout); fputc('Z', stdout);
return 0; return 0;
} }