LibC: Implement setbuf() and setvbuf()
This commit is contained in:
parent
c440204fa5
commit
401b460d75
|
@ -1,5 +1,6 @@
|
|||
#include <BAN/Assert.h>
|
||||
#include <BAN/Debug.h>
|
||||
#include <BAN/Math.h>
|
||||
|
||||
#include <bits/printf.h>
|
||||
#include <errno.h>
|
||||
|
@ -16,12 +17,15 @@ struct FILE
|
|||
{
|
||||
int fd { -1 };
|
||||
mode_t mode { 0 };
|
||||
int buffer_type { _IOLBF };
|
||||
bool eof { false };
|
||||
bool error { false };
|
||||
|
||||
int pid { -1 };
|
||||
|
||||
unsigned char buffer[BUFSIZ] {};
|
||||
unsigned char inline_buffer_storage[BUFSIZ] {};
|
||||
unsigned char* buffer = inline_buffer_storage;
|
||||
uint32_t buffer_size = BUFSIZ;
|
||||
uint32_t buffer_index { 0 };
|
||||
};
|
||||
|
||||
|
@ -44,7 +48,7 @@ struct ScopeLock
|
|||
static FILE s_files[FOPEN_MAX] {
|
||||
{ .fd = STDIN_FILENO, .mode = O_RDONLY },
|
||||
{ .fd = STDOUT_FILENO, .mode = O_WRONLY },
|
||||
{ .fd = STDERR_FILENO, .mode = O_WRONLY },
|
||||
{ .fd = STDERR_FILENO, .mode = O_WRONLY, .buffer_type = _IONBF },
|
||||
{ .fd = STDDBG_FILENO, .mode = O_WRONLY },
|
||||
};
|
||||
|
||||
|
@ -73,7 +77,7 @@ int fclose(FILE* file)
|
|||
ScopeLock _(file);
|
||||
(void)fflush(file);
|
||||
int ret = (close(file->fd) == -1) ? EOF : 0;
|
||||
file->fd = -1;
|
||||
file = {};
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -104,20 +108,19 @@ FILE* fdopen(int fd, const char* mode_str)
|
|||
errno = EINVAL;
|
||||
return nullptr;
|
||||
}
|
||||
mode &= ~O_TRUNC;
|
||||
|
||||
// FIXME: when threads are implemented
|
||||
for (int i = 0; i < FOPEN_MAX; i++)
|
||||
{
|
||||
if (s_files[i].fd == -1)
|
||||
{
|
||||
s_files[i] = {
|
||||
.fd = fd,
|
||||
.mode = mode & O_ACCMODE,
|
||||
};
|
||||
ScopeLock _(&s_files[i]);
|
||||
if (s_files[i].fd != -1)
|
||||
continue;
|
||||
s_files[i].fd = fd;
|
||||
s_files[i].mode = mode & O_ACCMODE;
|
||||
ASSERT(s_files[i].buffer == s_files[i].inline_buffer_storage);
|
||||
ASSERT(s_files[i].buffer_size == BUFSIZ);
|
||||
return &s_files[i];
|
||||
}
|
||||
}
|
||||
|
||||
errno = EMFILE;
|
||||
return nullptr;
|
||||
|
@ -229,15 +232,15 @@ FILE* fopen(const char* pathname, const char* mode_str)
|
|||
// FIXME: when threads are implemented
|
||||
for (int i = 0; i < FOPEN_MAX; i++)
|
||||
{
|
||||
if (s_files[i].fd == -1)
|
||||
{
|
||||
s_files[i] = {
|
||||
.fd = fd,
|
||||
.mode = mode & O_ACCMODE
|
||||
};
|
||||
ScopeLock _(&s_files[i]);
|
||||
if (s_files[i].fd != -1)
|
||||
continue;
|
||||
s_files[i].fd = fd;
|
||||
s_files[i].mode = mode & O_ACCMODE;
|
||||
ASSERT(s_files[i].buffer == s_files[i].inline_buffer_storage);
|
||||
ASSERT(s_files[i].buffer_size == BUFSIZ);
|
||||
return &s_files[i];
|
||||
}
|
||||
}
|
||||
|
||||
errno = EMFILE;
|
||||
return nullptr;
|
||||
|
@ -308,11 +311,9 @@ FILE* freopen(const char* pathname, const char* mode_str, FILE* file)
|
|||
|
||||
ScopeLock _(file);
|
||||
|
||||
(void)fflush(file);
|
||||
|
||||
if (pathname)
|
||||
{
|
||||
close(file->fd);
|
||||
fclose(file);
|
||||
file->fd = open(pathname, mode, 0666);
|
||||
file->mode = mode & O_ACCMODE;
|
||||
if (file->fd == -1)
|
||||
|
@ -320,15 +321,13 @@ FILE* freopen(const char* pathname, const char* mode_str, FILE* file)
|
|||
}
|
||||
else
|
||||
{
|
||||
mode &= O_ACCMODE;
|
||||
if ((file->mode & mode) != mode)
|
||||
{
|
||||
close(file->fd);
|
||||
file->fd = -1;
|
||||
fclose(file);
|
||||
errno = EBADF;
|
||||
return nullptr;
|
||||
}
|
||||
file->mode = mode;
|
||||
file->mode = mode & O_ACCMODE;
|
||||
}
|
||||
|
||||
return file;
|
||||
|
@ -537,16 +536,16 @@ FILE* popen(const char* command, const char* mode_str)
|
|||
// FIXME: when threads are implemented
|
||||
for (int i = 0; i < FOPEN_MAX; i++)
|
||||
{
|
||||
if (s_files[i].fd == -1)
|
||||
{
|
||||
s_files[i] = {
|
||||
.fd = read ? fds[0] : fds[1],
|
||||
.mode = (unsigned)(read ? O_RDONLY : O_WRONLY),
|
||||
.pid = pid
|
||||
};
|
||||
ScopeLock _(&s_files[i]);
|
||||
if (s_files[i].fd != -1)
|
||||
continue;
|
||||
s_files[i].fd = read ? fds[0] : fds[1];
|
||||
s_files[i].mode = (unsigned)(read ? O_RDONLY : O_WRONLY);
|
||||
s_files[i].pid = pid;
|
||||
ASSERT(s_files[i].buffer == s_files[i].inline_buffer_storage);
|
||||
ASSERT(s_files[i].buffer_size == BUFSIZ);
|
||||
return &s_files[i];
|
||||
}
|
||||
}
|
||||
|
||||
errno = EMFILE;
|
||||
return nullptr;
|
||||
|
@ -574,7 +573,7 @@ int putchar(int c)
|
|||
int putc_unlocked(int c, FILE* file)
|
||||
{
|
||||
file->buffer[file->buffer_index++] = c;
|
||||
if (c == '\n' || file->buffer_index == sizeof(file->buffer))
|
||||
if (file->buffer_type == _IONBF || (file->buffer_type == _IOLBF && c == '\n') || file->buffer_index >= file->buffer_size)
|
||||
if (fflush(file) == EOF)
|
||||
return EOF;
|
||||
return (unsigned char)c;
|
||||
|
@ -628,11 +627,32 @@ int scanf(const char* format, ...)
|
|||
return ret;
|
||||
}
|
||||
|
||||
// TODO
|
||||
void setbuf(FILE*, char*);
|
||||
void setbuf(FILE* file, char* buffer)
|
||||
{
|
||||
int type = buffer ? _IOFBF : _IONBF;
|
||||
setvbuf(file, buffer, type, BUFSIZ);
|
||||
}
|
||||
|
||||
// TODO
|
||||
int setvbuf(FILE*, char*, int, size_t);
|
||||
int setvbuf(FILE* file, char* buffer, int type, size_t size)
|
||||
{
|
||||
if (file->fd == -1)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer == nullptr)
|
||||
{
|
||||
buffer = reinterpret_cast<char*>(file->inline_buffer_storage);
|
||||
size = BAN::Math::min<size_t>(size, BUFSIZ);
|
||||
}
|
||||
|
||||
file->buffer_type = type;
|
||||
file->buffer_size = size;
|
||||
file->buffer = reinterpret_cast<unsigned char*>(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snprintf(char* buffer, size_t max_size, const char* format, ...)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue