libc: A bit of nice refactoring
This commit is contained in:
parent
a3ed950be8
commit
d60ad184f1
@ -14,16 +14,19 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int _fd;
|
int _fd; // The underlying file descriptor.
|
||||||
int _err;
|
int _err; // The error status flag.
|
||||||
int _eof;
|
int _eof; // The end-of-file status flag.
|
||||||
size_t _bufcap;
|
struct
|
||||||
size_t _bufsize;
|
{
|
||||||
size_t _bufindex;
|
size_t capacity; // The buffer's total capacity.
|
||||||
char* _buffer;
|
size_t size; // The buffer's used size.
|
||||||
int _flags;
|
size_t index; // The read index into the buffer.
|
||||||
int _pending;
|
char* buffer; // The memory used for the buffer.
|
||||||
int _mode;
|
int status; // The buffer status flags.
|
||||||
|
int mode; // The buffering mode.
|
||||||
|
} _buf;
|
||||||
|
int _flags; // The file access mode with which the file was opened.
|
||||||
} FILE;
|
} FILE;
|
||||||
|
|
||||||
#define EOF -1
|
#define EOF -1
|
||||||
|
@ -13,7 +13,12 @@ FILE* stdout = nullptr;
|
|||||||
|
|
||||||
FILE* s_open_files[FOPEN_MAX];
|
FILE* s_open_files[FOPEN_MAX];
|
||||||
|
|
||||||
#define FFLAG_FREE_AFTER_BUFFER_USE (1 << 0)
|
enum FileStatusFlags
|
||||||
|
{
|
||||||
|
BufferIsMalloced = (1 << 0),
|
||||||
|
LastRead = (1 << 1),
|
||||||
|
LastWrite = (1 << 2),
|
||||||
|
};
|
||||||
|
|
||||||
static const char* read_tmpdir()
|
static const char* read_tmpdir()
|
||||||
{
|
{
|
||||||
@ -57,12 +62,12 @@ static int fdopen_check_compatible_mode(int fd, int new_flags)
|
|||||||
|
|
||||||
static int flush_write_buffer(FILE* stream)
|
static int flush_write_buffer(FILE* stream)
|
||||||
{
|
{
|
||||||
if (stream->_mode == _IONBF) return 0;
|
if (stream->_buf.mode == _IONBF) return 0;
|
||||||
|
|
||||||
ssize_t result = write(stream->_fd, stream->_buffer, stream->_bufsize);
|
ssize_t result = write(stream->_fd, stream->_buf.buffer, stream->_buf.size);
|
||||||
|
|
||||||
stream->_bufindex = 0;
|
stream->_buf.index = 0;
|
||||||
stream->_bufsize = 0;
|
stream->_buf.size = 0;
|
||||||
|
|
||||||
return result < 0 ? EOF : 0;
|
return result < 0 ? EOF : 0;
|
||||||
}
|
}
|
||||||
@ -74,20 +79,20 @@ static ssize_t write_into_buffer(FILE* stream, const u8* data, ssize_t size)
|
|||||||
while (size > 0)
|
while (size > 0)
|
||||||
{
|
{
|
||||||
ssize_t nwritten;
|
ssize_t nwritten;
|
||||||
if (stream->_mode != _IONBF)
|
if (stream->_buf.mode != _IONBF)
|
||||||
{
|
{
|
||||||
if ((stream->_bufsize + size) > stream->_bufcap)
|
if ((stream->_buf.size + size) > stream->_buf.capacity)
|
||||||
{
|
{
|
||||||
if (flush_write_buffer(stream) < 0) return -1;
|
if (flush_write_buffer(stream) < 0) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t size_remaining = stream->_bufcap - stream->_bufsize;
|
ssize_t size_remaining = stream->_buf.capacity - stream->_buf.size;
|
||||||
nwritten = size > size_remaining ? size_remaining : size;
|
nwritten = size > size_remaining ? size_remaining : size;
|
||||||
memcpy(stream->_buffer + stream->_bufsize, data, nwritten);
|
memcpy(stream->_buf.buffer + stream->_buf.size, data, nwritten);
|
||||||
|
|
||||||
stream->_bufsize += nwritten;
|
stream->_buf.size += nwritten;
|
||||||
|
|
||||||
if (stream->_mode == _IOLBF && memchr(data, '\n', nwritten))
|
if (stream->_buf.mode == _IOLBF && memchr(data, '\n', nwritten))
|
||||||
{
|
{
|
||||||
if (flush_write_buffer(stream) < 0) return -1;
|
if (flush_write_buffer(stream) < 0) return -1;
|
||||||
}
|
}
|
||||||
@ -112,7 +117,7 @@ extern "C"
|
|||||||
|
|
||||||
int fflush(FILE* stream)
|
int fflush(FILE* stream)
|
||||||
{
|
{
|
||||||
if (stream && stream->_mode != _IONBF) flush_write_buffer(stream);
|
if (stream && stream->_buf.mode != _IONBF) flush_write_buffer(stream);
|
||||||
else if (!stream)
|
else if (!stream)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < FOPEN_MAX; i++)
|
for (int i = 0; i < FOPEN_MAX; i++)
|
||||||
@ -142,12 +147,12 @@ extern "C"
|
|||||||
f->_fd = fd;
|
f->_fd = fd;
|
||||||
clearerr(f);
|
clearerr(f);
|
||||||
|
|
||||||
f->_pending = 0;
|
|
||||||
f->_flags = flags;
|
f->_flags = flags;
|
||||||
f->_mode = isatty(fd) ? _IOLBF : _IOFBF;
|
f->_buf.status = 0;
|
||||||
f->_bufsize = f->_bufindex = 0;
|
f->_buf.mode = isatty(fd) ? _IOLBF : _IOFBF;
|
||||||
f->_buffer = nullptr;
|
f->_buf.size = f->_buf.index = 0;
|
||||||
setvbuf(f, NULL, f->_mode, 0);
|
f->_buf.buffer = nullptr;
|
||||||
|
setvbuf(f, NULL, f->_buf.mode, 0);
|
||||||
|
|
||||||
s_open_files[fd] = f;
|
s_open_files[fd] = f;
|
||||||
|
|
||||||
@ -168,12 +173,12 @@ extern "C"
|
|||||||
f->_fd = fd;
|
f->_fd = fd;
|
||||||
clearerr(f);
|
clearerr(f);
|
||||||
|
|
||||||
f->_pending = 0;
|
|
||||||
f->_flags = flags;
|
f->_flags = flags;
|
||||||
f->_mode = buffering_mode < 0 ? (isatty(fd) ? _IOLBF : _IOFBF) : buffering_mode;
|
f->_buf.status = 0;
|
||||||
f->_bufsize = f->_bufindex = 0;
|
f->_buf.mode = buffering_mode < 0 ? (isatty(fd) ? _IOLBF : _IOFBF) : buffering_mode;
|
||||||
f->_buffer = nullptr;
|
f->_buf.size = f->_buf.index = 0;
|
||||||
setvbuf(f, NULL, f->_mode, 0);
|
f->_buf.buffer = nullptr;
|
||||||
|
setvbuf(f, NULL, f->_buf.mode, 0);
|
||||||
|
|
||||||
s_open_files[fd] = f;
|
s_open_files[fd] = f;
|
||||||
|
|
||||||
@ -195,7 +200,7 @@ extern "C"
|
|||||||
|
|
||||||
s_open_files[stream->_fd] = nullptr;
|
s_open_files[stream->_fd] = nullptr;
|
||||||
|
|
||||||
if (stream->_buffer && (stream->_pending & FFLAG_FREE_AFTER_BUFFER_USE)) free(stream->_buffer);
|
if (stream->_buf.buffer && (stream->_buf.status & FileStatusFlags::BufferIsMalloced)) free(stream->_buf.buffer);
|
||||||
|
|
||||||
if (!path) { fail("FIXME: freopen() called with path=nullptr"); }
|
if (!path) { fail("FIXME: freopen() called with path=nullptr"); }
|
||||||
|
|
||||||
@ -205,12 +210,12 @@ extern "C"
|
|||||||
stream->_fd = fd;
|
stream->_fd = fd;
|
||||||
clearerr(stream);
|
clearerr(stream);
|
||||||
|
|
||||||
stream->_pending = 0;
|
|
||||||
stream->_flags = flags;
|
stream->_flags = flags;
|
||||||
stream->_mode = isatty(fd) ? _IOLBF : _IOFBF;
|
stream->_buf.status = 0;
|
||||||
stream->_bufsize = stream->_bufindex = 0;
|
stream->_buf.mode = isatty(fd) ? _IOLBF : _IOFBF;
|
||||||
stream->_buffer = nullptr;
|
stream->_buf.size = stream->_buf.index = 0;
|
||||||
setvbuf(stream, NULL, stream->_mode, 0);
|
stream->_buf.buffer = nullptr;
|
||||||
|
setvbuf(stream, NULL, stream->_buf.mode, 0);
|
||||||
|
|
||||||
s_open_files[fd] = stream;
|
s_open_files[fd] = stream;
|
||||||
|
|
||||||
@ -223,7 +228,7 @@ extern "C"
|
|||||||
|
|
||||||
if (close(stream->_fd) < 0) return EOF;
|
if (close(stream->_fd) < 0) return EOF;
|
||||||
|
|
||||||
if (stream->_buffer && (stream->_pending & FFLAG_FREE_AFTER_BUFFER_USE)) free(stream->_buffer);
|
if (stream->_buf.buffer && (stream->_buf.status & FileStatusFlags::BufferIsMalloced)) free(stream->_buf.buffer);
|
||||||
|
|
||||||
s_open_files[stream->_fd] = nullptr;
|
s_open_files[stream->_fd] = nullptr;
|
||||||
|
|
||||||
@ -610,28 +615,28 @@ extern "C"
|
|||||||
|
|
||||||
int setvbuf(FILE* stream, char* buf, int mode, size_t size)
|
int setvbuf(FILE* stream, char* buf, int mode, size_t size)
|
||||||
{
|
{
|
||||||
int pending = 0;
|
int status = 0;
|
||||||
if (mode < 0 || mode > _IOFBF) return errno = EINVAL, -1;
|
if (mode < 0 || mode > _IOFBF) return errno = EINVAL, -1;
|
||||||
if (stream->_bufsize != 0 || stream->_bufindex != 0) return -1; // Buffer is already in use.
|
if (stream->_buf.size != 0 || stream->_buf.index != 0) return -1; // Buffer is already in use.
|
||||||
if (mode != _IONBF && buf == NULL)
|
if (mode != _IONBF && buf == NULL)
|
||||||
{
|
{
|
||||||
size = BUFSIZ;
|
size = BUFSIZ;
|
||||||
buf = (char*)calloc(size, 1);
|
buf = (char*)calloc(size, 1);
|
||||||
if (!buf) return -1;
|
if (!buf) return -1;
|
||||||
pending = FFLAG_FREE_AFTER_BUFFER_USE;
|
status = FileStatusFlags::BufferIsMalloced;
|
||||||
}
|
}
|
||||||
else
|
else if (mode == _IONBF)
|
||||||
{
|
{
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream->_buffer && (stream->_pending & FFLAG_FREE_AFTER_BUFFER_USE)) free(stream->_buffer);
|
if (stream->_buf.buffer && (stream->_buf.status & FileStatusFlags::BufferIsMalloced)) free(stream->_buf.buffer);
|
||||||
|
|
||||||
stream->_buffer = buf;
|
stream->_buf.buffer = buf;
|
||||||
stream->_bufcap = size;
|
stream->_buf.capacity = size;
|
||||||
stream->_mode = mode;
|
stream->_buf.mode = mode;
|
||||||
stream->_pending = pending;
|
stream->_buf.status = status;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user