diff options
Diffstat (limited to 'rushs/tinyprintf/tinylibstream/src/tinylibstream.c')
| -rw-r--r-- | rushs/tinyprintf/tinylibstream/src/tinylibstream.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/rushs/tinyprintf/tinylibstream/src/tinylibstream.c b/rushs/tinyprintf/tinylibstream/src/tinylibstream.c new file mode 100644 index 0000000..dca1c01 --- /dev/null +++ b/rushs/tinyprintf/tinylibstream/src/tinylibstream.c @@ -0,0 +1,221 @@ +#include <stdlib.h> +#include <string.h> + +#include "../include/libstream.h" + +int get_flags(const char *mode) +{ + int flags; + if (strcmp(mode, "r") == 0) + { + flags = O_RDONLY; + } + else if (strcmp(mode, "r+") == 0) + { + flags = O_RDWR; + } + else if (strcmp(mode, "w") == 0) + { + flags = O_WRONLY | O_TRUNC | O_CREAT; + } + else + { + flags = O_RDWR | O_TRUNC | O_CREAT; + } + + return flags; +} + +struct stream *lbs_fopen(const char *path, const char *mode) +{ + int fd = open(path, get_flags(mode)); + + return lbs_fdopen(fd, mode); +} + +struct stream *lbs_fdopen(int fd, const char *mode) +{ + if (fd == -1) + { + return NULL; + } + + struct stream *s = malloc(sizeof(struct stream)); + if (s == NULL) + { + return NULL; + } + + s->flags = get_flags(mode); + s->error = 0; + s->fd = fd; + if (isatty(fd)) + { + s->buffering_mode = STREAM_LINE_BUFFERED; + } + else + { + s->buffering_mode = STREAM_BUFFERED; + } + s->buffered_size = 0; + s->already_read = 0; + + return s; +} + +int lbs_fflush(struct stream *stream) +{ + if (stream == NULL || stream->buffered_size == 0) + { + return 0; + } + + if (stream->io_operation == STREAM_READING) + { + if (!stream_readable(stream)) + { + stream->error = 1; + return LBS_EOF; + } + if (stream_remaining_buffered(stream) != 0 + && lseek(stream->fd, -stream_remaining_buffered(stream), SEEK_CUR) + == -1) + { + stream->error = 1; + return LBS_EOF; + } + stream->buffered_size = 0; + stream->already_read = 0; + } + else + { + if (!stream_writable(stream)) + { + stream->error = 1; + return LBS_EOF; + } + ssize_t w; + if ((w = write(stream->fd, stream->buffer, stream->buffered_size)) + == -1) + { + stream->error = 1; + return LBS_EOF; + } + stream->buffered_size = 0; + stream->already_read = 0; + } + return 0; +} + +int lbs_fclose(struct stream *stream) +{ + if (stream == NULL) + { + return 1; + } + + lbs_fflush(stream); + if (close(stream->fd) == -1) + { + return 1; + } + + free(stream); + + return 0; +} + +int lbs_fputc(int c, struct stream *stream) +{ + if (!stream_writable(stream)) + { + stream->error = 1; + return -1; + } + + if (stream->io_operation == STREAM_READING) + { + if (lbs_fflush(stream) != 0) + { + return -1; + } + stream->buffered_size = 0; + stream->already_read = 0; + } + stream->io_operation = STREAM_WRITING; + + if (stream_unused_buffer_space(stream) == 0 + || stream->buffering_mode == STREAM_UNBUFFERED) + { + if (lbs_fflush(stream) != 0) + { + return -1; + } + } + + stream->buffer[stream->buffered_size] = c; + stream->buffered_size++; + if (stream_unused_buffer_space(stream) == 0 + || stream->buffering_mode == STREAM_UNBUFFERED + || (stream->buffering_mode == STREAM_LINE_BUFFERED && c == '\n')) + { + if (lbs_fflush(stream) != 0) + { + return -1; + } + } + + return c; +} + +int refill_buffer(struct stream *stream) +{ + stream->already_read = 0; + ssize_t r; + if ((r = read(stream->fd, stream->buffer, LBS_BUFFER_SIZE)) == -1) + { + stream->error = 1; + return -1; + } + if (r == 0) + { + return -1; + } + stream->buffered_size = r; + return r; +} + +int lbs_fgetc(struct stream *stream) +{ + if (!stream_readable(stream)) + { + stream->error = 1; + return -1; + } + if (stream->io_operation == STREAM_WRITING) + { + if (lbs_fflush(stream) != 0) + { + stream->error = 1; + return -1; + } + stream->already_read = 0; + } + stream->io_operation = STREAM_READING; + + if (stream_remaining_buffered(stream) == 0) + { + int r; + if ((r = refill_buffer(stream)) == -1) + { + stream->error = 1; + return -1; + } + } + + int res = stream->buffer[stream->already_read++]; + + unsigned char c = res; + + return c; +} |
