diff options
author | Juan Manuel Tomás <jtomas1815@gmail.com> | 2020-07-17 16:23:43 -0300 |
---|---|---|
committer | Juan Manuel Tomás <jtomas1815@gmail.com> | 2020-07-17 16:23:43 -0300 |
commit | d608bef678fa97b3af910fa62598c55f33650825 (patch) | |
tree | 90f1b4029be89a3ed3c55593b9787371c8037a35 /src/server | |
parent | c1d93b0bc5a2abcf5e7cadd17ef9db7f57a524fc (diff) | |
download | jet-d608bef678fa97b3af910fa62598c55f33650825.tar.gz jet-d608bef678fa97b3af910fa62598c55f33650825.zip |
Restructure source files
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/buffer.cpp | 45 | ||||
-rw-r--r-- | src/server/client.cpp | 93 | ||||
-rw-r--r-- | src/server/page.cpp | 87 | ||||
-rw-r--r-- | src/server/point.cpp | 139 |
4 files changed, 364 insertions, 0 deletions
diff --git a/src/server/buffer.cpp b/src/server/buffer.cpp new file mode 100644 index 0000000..7b4c92d --- /dev/null +++ b/src/server/buffer.cpp @@ -0,0 +1,45 @@ +struct Buffer { + const char *name; + Page *storage; + + Buffer(const char *name) : name(name), storage(new Page()) {} + + void free_storage() { + while (storage) { + Page *iter = storage; + storage = storage->next; + delete iter; + } + } + + void read_file(const char *pathname) { + free_storage(); + int file = open(pathname, O_RDONLY); + storage = new Page(); + int bytes_read = read(file, storage->elements, PAGE_SIZE); + Page *iter = storage; + while (bytes_read > 0) { + iter->gap_start = bytes_read; + iter->element_count = bytes_read; + iter->next = new Page(); + iter->next->prev = iter; + iter = iter->next; + bytes_read = read(file, iter->elements, PAGE_SIZE); + } + if (iter->element_count == 0) { + delete iter; + } + close(file); + } + + void write_file(const char *pathname) { + int file = open(pathname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + Page *iter = storage; + while (iter) { + write(file, iter->elements, iter->gap_start); + write(file, iter->elements + iter->gap_end, PAGE_SIZE - iter->gap_end); + iter = iter->next; + } + close(file); + } +}; diff --git a/src/server/client.cpp b/src/server/client.cpp new file mode 100644 index 0000000..bed62c5 --- /dev/null +++ b/src/server/client.cpp @@ -0,0 +1,93 @@ +#define MAX_MSG_SIZE 128 +#define pos(x, y) (x) + (y) * window_w + +struct Client { + int sockfd; + Point cursor; + Point window_start; + + Client(const Buffer &b) : cursor(b), window_start(cursor) {} + + void parse_message() { + int8_t message[MAX_MSG_SIZE] = {}; + read(sockfd, message, MAX_MSG_SIZE - 1); + int8_t *iter = message; + while (*iter) { + switch (*iter) { + case OP_MOVE1: + move(iter[1]); + iter += 2; + break; + case OP_MOVE2: + move(decode2(iter, 1)); + iter += 3; + break; + case OP_MOVE4: + move(decode4(iter, 1)); + iter += 5; + break; + case OP_MOVE8: + move(decode8(iter, 1)); + iter += 9; + break; + case OP_INSERT: + push(iter[1]); + iter += 2; + break; + case OP_DELETE: + pop(); + iter += 1; + break; + case OP_SHOW: + show(decode2(iter, 1), decode2(iter, 3)); + iter += 6; + break; + } + } + } + + void show(size_t window_w, size_t window_h) { + char *view = new char[window_w * window_h]; + + Point window_end(window_start); + for (int i = 0; i < window_h; i++) { + for (int j = 0; j < window_w; j++) { + view[pos(j, i)] = window_end.element(); + if (window_end.element() == '\n') { + for (int k = j + 1; k < window_w; k++) { + view[pos(k, i)] = 0; + } + j = window_w; + } else if (window_end.element() == '\t') { + for (int k = j + 1; k < j + 8; k++) { + view[pos(k, i)] = 0; + } + j = j + 7; + } + window_end++; + } + } + + write(sockfd, view, window_w * window_h); + delete[] view; + } + + void move(int64_t target) { + while (target > 0) { + cursor++; + target--; + } + while (target < 0) { + cursor--; + target++; + } + } + + void push(int8_t input) { + cursor.push(input); + } + + void pop() { + cursor.pop(); + } +}; diff --git a/src/server/page.cpp b/src/server/page.cpp new file mode 100644 index 0000000..77cf686 --- /dev/null +++ b/src/server/page.cpp @@ -0,0 +1,87 @@ +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +struct Page { + uint8_t *elements; + Page *next; + Page *prev; + uint16_t gap_start; + uint16_t gap_end; + uint16_t element_count; + + Page() { + elements = new uint8_t[PAGE_SIZE]; + gap_start = 0; + gap_end = PAGE_SIZE; + element_count = 0; + next = nullptr; + prev = nullptr; + } + + ~Page() { + if (prev) prev->next = next; + if (next) next->prev = prev; + delete[] elements; + } + + void split() { + Page *front = new Page(); + + memcpy(front->elements, elements + PAGE_SIZE / 2, PAGE_SIZE / 2); + + front->gap_start = PAGE_SIZE / 2; + front->gap_end = PAGE_SIZE; + front->element_count = PAGE_SIZE / 2; + + gap_start = PAGE_SIZE / 2; + gap_end = PAGE_SIZE; + element_count = PAGE_SIZE / 2; + + if (next) { + next->prev = front; + } + front->next = next; + front->prev = this; + next = front; + } + + void copy_to(Page *dest) { + memcpy(dest->elements, elements, PAGE_SIZE); + dest->gap_start = gap_start; + dest->gap_end = gap_end; + dest->element_count = element_count; + } + + void move_gap_forward() { + elements[gap_start] = elements[gap_end]; + gap_start++; + gap_end++; + } + + void move_gap_backward() { + gap_end--; + gap_start--; + elements[gap_end] = elements[gap_start]; + } + + void push(uint8_t c) { + elements[gap_start] = c; + gap_start++; + element_count++; + } + + void pop() { + gap_start--; + element_count--; + } + + bool is_empty() { + return element_count == 0; + } + + bool is_full() { + return gap_start == gap_end; + } + +}; diff --git a/src/server/point.cpp b/src/server/point.cpp new file mode 100644 index 0000000..ab9f70f --- /dev/null +++ b/src/server/point.cpp @@ -0,0 +1,139 @@ +#include <stdint.h> +#include <stdbool.h> + +struct Point { + Page *page; + uint16_t index; + + uint16_t index_to_offset() { + if (index < page->gap_start) { + return index; + } else { + return index + (page->gap_end - page->gap_start); + } + } + + uint8_t prev_byte() { + if (index == 0) { + if (page->prev) { + return page->prev->elements[Point(page->prev, page->prev->element_count - 1).index_to_offset()]; + } else { + return 0; + } + } else { + return page->elements[Point(page, index - 1).index_to_offset()]; + } + } + + uint8_t next_byte() { + if (index == page->element_count) { + if (page->next) { + return page->next->elements[Point(page->next, 0).index_to_offset()]; + } else { + return 0; + } + } else { + return page->elements[index_to_offset()]; + } + } + + void move_forward() { + if (index < page->element_count) { + index++; + } else if (page->next) { + page = page->next; + index = 0; + } + } + + void move_backward() { + if (index > 0) { + index--; + } else if (page->prev) { + page = page->prev; + index = page->element_count; + } + } + + + public: + + Point() : page(0), index(0) {} + Point(Page* page, uint16_t index) : page(page), index(index) {} + Point(const Buffer &b) : page(b.storage), index(0) {} + Point(const Point &p) : page(p.page), index(p.index) {} + + bool operator==(Point p) { + return page == p.page && index == p.index; + } + + bool operator!=(Point p) { + return page != p.page || index != p.index; + } + + bool at_start() { + return index == 0 && !page->prev; + } + + bool at_end() { + return index == page->element_count && !page->next; + } + + void operator++(int) { + if (index == page->element_count) move_forward(); + move_forward(); + } + + void operator--(int) { + move_backward(); + if (index == 0) move_backward(); + } + + char element() { + return next_byte(); + } + + void align_gap() { + while (page->gap_end < index_to_offset()) { + page->move_gap_forward(); + } + while (page->gap_end > index_to_offset()) { + page->move_gap_backward(); + } + } + + void push(uint8_t c) { + if (page->is_full()) { + page->split(); + if (index >= PAGE_SIZE / 2) { + page = page->next; + index -= PAGE_SIZE / 2; + } + } + align_gap(); + page->push(c); + move_forward(); + } + + void pop() { + if (!at_start()) { + align_gap(); + page->pop(); + move_backward(); + if (index == 0) { + move_backward(); + } + } + if (page->is_empty()) { + if (page->prev) { + move_backward(); + delete page->next; + } else if (page->next) { + page->next->copy_to(page); + delete page->next; + index = 0; + } + } + } + +}; |