summaryrefslogtreecommitdiff
path: root/rushs/evalexpr/tinylibstream/src/tinylibstream.c
diff options
context:
space:
mode:
Diffstat (limited to 'rushs/evalexpr/tinylibstream/src/tinylibstream.c')
-rw-r--r--rushs/evalexpr/tinylibstream/src/tinylibstream.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/rushs/evalexpr/tinylibstream/src/tinylibstream.c b/rushs/evalexpr/tinylibstream/src/tinylibstream.c
new file mode 100644
index 0000000..dca1c01
--- /dev/null
+++ b/rushs/evalexpr/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;
+}