From f5ffa6ab2675a47c8ee1753e65df1b6e974a5be8 Mon Sep 17 00:00:00 2001 From: ninya9k <> Date: Tue, 14 Nov 2023 14:10:49 +0000 Subject: [PATCH] socket ring buffer and readline --- uttt.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/uttt.c b/uttt.c index 6807490..207e207 100644 --- a/uttt.c +++ b/uttt.c @@ -29,7 +29,15 @@ const struct ut_state ut_initial = { .playBoard = -1, .player = 'X', .host_player = '\0', - }; +}; + +struct ut_socket_buffer { + int fd; + char *buf; + size_t len; + size_t start; + size_t stop; +}; const char *HELP_TEXT = "\ Usage: uttt (--local | --host | --join)\n\ @@ -295,6 +303,60 @@ int ut_writefill(int fd, const char *x, size_t l) return 0; } +int ut_socket_buffer_size(struct ut_socket_buffer *sockbuf) { + int size = sockbuf->stop - sockbuf->start; + if (size < 0) {size += sockbuf->len;} + return size; +} + +/* Copies up to (and including) first '\n' in socket buffer, otherwise whole buffer */ +int ut_readline_buffer(struct ut_socket_buffer *sockbuf, char *line, size_t len) { + int size = ut_socket_buffer_size(sockbuf); + for (int i = sockbuf->start; i < sockbuf->start + size; i++) { + if (i > len) {return -1;} + line[i] = sockbuf->buf[i % sockbuf->len]; + if (sockbuf->buf[i] == '\n') { + sockbuf->start = (sockbuf->start + i + 1) % sockbuf->len; + return i + 1; + } + } + sockbuf->start = (sockbuf->start + size) % sockbuf->len; + return size; +} + +int ut_readline_socket(struct ut_socket_buffer *sockbuf, char *line, size_t len) { + while (len > 0) { + int r = read(sockbuf->fd, line, len); + if (r < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {continue;} + else {return -2;} + } + else if (r == 0) {return -2;} + for (int i = 0; i < r; i++) { + if (line[i] == '\n') { + int size = ut_socket_buffer_size(sockbuf); + if (r - i >= sockbuf->len - size) {return -1;} + for (int j = 0; j < r - i; j++) { + sockbuf->buf[(sockbuf->stop + j) % sockbuf->len] = line[i + j]; + } + sockbuf->stop = (sockbuf->stop + r - i) % sockbuf->len; + return i; + } + } + line += r; + len -= r; + } +} + +int ut_readline(struct ut_socket_buffer *sockbuf, char *line, size_t len) { + int nb = ut_readline_buffer(sockbuf, line, len); + if (nb < 0) {return nb;} + if (line[nb - 1] == '\n') {return nb - 1;} + int ns = ut_readline_socket(sockbuf, line + nb, len - nb); + if (ns < 0) {return ns;} + return nb + ns; +} + #define MAX_LINE 128 int ut_dprintf(int fd, const char *restrict format, ...)