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