From f26e610c2f0bdb07fce3f7a100b3ef6159c2ffe7 Mon Sep 17 00:00:00 2001 From: Syndamia Date: Fri, 8 Dec 2023 16:39:59 +0200 Subject: [browser] Implemented anchor parsing and navigation --- browser.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++----------- util.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ util.h | 7 ++++- 3 files changed, 170 insertions(+), 26 deletions(-) diff --git a/browser.c b/browser.c index fe36782..5e0396f 100644 --- a/browser.c +++ b/browser.c @@ -5,13 +5,35 @@ #include #include +#include #include #include #include +#include #include -sds get_page(const int fd_socket) { +int create_socket(const char* ip, const char* port) { + /* + * Create socket for connecting with server + */ + int fd_socket; + herr(fd_socket = socket(AF_INET, SOCK_STREAM, 0), "socket"); + + struct sockaddr_in sa_server = { + .sin_family = AF_INET, + .sin_port = inet_atop(port), + }; + herr(inet_aton(ip, &sa_server.sin_addr.s_addr), "inet_aton"); + + herr(connect(fd_socket, (struct sockaddr*)&sa_server, sizeof(struct sockaddr_in)), "connect"); + + return fd_socket; +} + +sds get_page(const int fd_socket, const char* URL) { + write(fd_socket, URL, strlen(URL)); + sds page = sdsempty(); char buff[512]; @@ -24,30 +46,73 @@ sds get_page(const int fd_socket) { return page; } -void renderPage(const sds page) { - sds toPrint = gsub(page, "\\*[^*]*\\*", "emph"); +struct md_syntax { + regex_t anchor; +}; + +void renderPage(const sds page, const struct md_syntax* syntax, int* *matches, int *matchesCount) { + sds toPrint = sdsdup(page); + + /* Substitute and register anchors */ + toPrint = gsub_getm(toPrint, &syntax->anchor, "\033[4m\1\033[0m\16", matches, matchesCount); + + int anchorInd = 0; + sds newPrint; + for (int i = 0; i < *matchesCount; i++) { + anchorInd = strchr(toPrint, '\16') - toPrint; + + toPrint[anchorInd] = '\0'; + newPrint = sdsgrowzero(sdsempty(), sdslen(toPrint) + digits(i) + 8 + 4); + sprintf(newPrint, "%s\033[30;46m%d\033[0m%s", toPrint, i, toPrint + anchorInd + 1); + + sdsfree(toPrint); + toPrint = newPrint; + } + write(1, toPrint, sdslen(toPrint)); sdsfree(toPrint); } int main(int argc, char* argv[]) { - int fd_socket; - herr(fd_socket = socket(AF_INET, SOCK_STREAM, 0), "socket"); + /* + * Preparation for rendering + */ - struct sockaddr_in sa_server = { - .sin_family = AF_INET, - .sin_port = inet_atop("8080"), + struct md_syntax md = { + .anchor = NULL, }; - herr(inet_aton("127.0.0.1", &sa_server.sin_addr.s_addr), "inet_aton"); + herr(regcomp(&md.anchor, "\\[\\([^]]*\\)\\](\\([^)]*\\))", 0), "regcomp"); - herr(connect(fd_socket, (struct sockaddr*)&sa_server, sizeof(struct sockaddr_in)), "connect"); + /* + * Server-client communication + */ - /* char msg[] = "hello@/test.txt"; */ - write(fd_socket, argv[1], strlen(argv[1])); + sds address = sdsnew(argv[1]); + int count = 0; + sds page; + int* anchorIndecies = NULL; + int anchorCount = 0; - sds page = get_page(fd_socket); - renderPage(page); - sdsfree(page); + int gotoIndex = 0; + int fd_socket; + while (count < 2) { + fd_socket = create_socket("127.0.0.1", "8080"); + page = get_page(fd_socket, address); + free(anchorIndecies); + anchorCount = 0; + renderPage(page, &md, &anchorIndecies, &anchorCount); + + scanf("%d", &gotoIndex); + sdsfree(address); + char* newplace = strchr(page + anchorIndecies[gotoIndex], '(') + 1; + address = sdscatlen(sdsnew(argv[1]), newplace, strchr(newplace, ')') - newplace); + count++; - close(fd_socket); + close(fd_socket); + } + + sdsfree(page); + sdsfree(address); + free(anchorIndecies); + regfree(&md.anchor); } diff --git a/util.c b/util.c index e210e34..439bcf7 100644 --- a/util.c +++ b/util.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -23,26 +24,99 @@ void herr(int output, const char* funcName) { } } -sds gsub(const sds str, const char* regex, const char* repl) { - regex_t preg; - regcomp(&preg, regex, 0); +sds getMatch(const sds str, const regmatch_t match) { + return sdsnewlen(str + match.rm_so, match.rm_eo - match.rm_so); +} +int validMatch(const regmatch_t match) { + return match.rm_so > -1; +} - int strInd = 0; - regmatch_t pmatch[1] = { +void resizeMatches(int* *matches, int* size) { + if (*size == 0) { + *matches = malloc((*size = 8) * sizeof(int*)); + return; + } + + int* *biggerArr = malloc((*size * 2) * sizeof(int*)); + for (size_t i = 0; i < *size; i++) { + biggerArr[i] = matches[i]; + } + *size *= 2; + free(matches); + *matches = *biggerArr; +} +void pushBackMatch(int* *matches, int *matchesCount, int *matchesSize, int matchStart) { + if (*matchesCount >= *matchesSize) + resizeMatches(matches, matchesSize); + + (*matches)[*matchesCount] = matchStart; + *matchesCount += 1; +} + +#define MATCHSTART str + strInd +sds gsub_getm(sds str, const regex_t *regex, const char* repl, int* *matches, int *matchesCount) { + regmatch_t pmatch[10] = { + { .rm_so = 0, .rm_eo = 0, }, { .rm_so = 0, .rm_eo = 0, }, { .rm_so = 0, .rm_eo = 0, }, + { .rm_so = 0, .rm_eo = 0, }, { .rm_so = 0, .rm_eo = 0, }, { .rm_so = 0, .rm_eo = 0, }, + { .rm_so = 0, .rm_eo = 0, }, { .rm_so = 0, .rm_eo = 0, }, { .rm_so = 0, .rm_eo = 0, }, { .rm_so = 0, .rm_eo = 0, }, }; + int strInd = 0; + int matchesSize = (matchesCount != NULL) ? *matchesCount : 0; + size_t replLen = strlen(repl); + sds ret = sdsempty(); // sdslen is in O(1) time while (strInd < sdslen(str)) { - if (regexec(&preg, str + strInd, 1, pmatch, 0) > 0) { - ret = sdscat(ret, str + strInd); + /* If no matches were found, cat the entire string and stop trying */ + if (regexec(regex, MATCHSTART, 10, pmatch, 0) != 0) { + ret = sdscat(ret, MATCHSTART); break; } - ret = sdscatlen(ret, str + strInd, pmatch[0].rm_so); - ret = sdscat(ret, repl); + + /* Cat everything before the match */ + ret = sdscatlen(ret, MATCHSTART, pmatch[0].rm_so); + + /* Cat repl in place of the match */ + for(size_t i = 0; i < replLen; i++) { + if (repl[i] <= '\10') { + if (pmatch[repl[i] % 10].rm_so > -1) + ret = sdscatsds(ret, getMatch(MATCHSTART, pmatch[repl[i] % 10])); + } + else + ret = sdscatlen(ret, &repl[i], 1); + } + + /* Add current match to matches array */ + if (matchesCount != NULL) { + pushBackMatch(matches, matchesCount, &matchesSize, strInd + pmatch[0].rm_so); + } + + /* Continute after the current match */ strInd += pmatch[0].rm_eo; } + sdsfree(str); return ret; } + +sds gsub(sds str, const regex_t* regex, const char* repl) { + return gsub_getm(str, regex, repl, NULL, NULL); +} + +int digits(int num) { + if (num < 0) num *= -1; + // This is the fastest way to get the number of digits + if (num < 10) return 1; + if (num < 100) return 2; + if (num < 1000) return 3; + if (num < 10000) return 4; + if (num < 100000) return 5; + if (num < 1000000) return 6; + if (num < 10000000) return 7; + if (num < 100000000) return 8; + if (num < 1000000000) return 9; + // 2147483647 (2^31-1) is max value of int + return 10; +} diff --git a/util.h b/util.h index 7ea5311..b8936ab 100644 --- a/util.h +++ b/util.h @@ -3,10 +3,15 @@ #include #include +#include uint16_t inet_atop(const char *port); void herr(int output, const char* funcName); void herrc(int output, const char* funcName); -sds gsub(sds str, const char* regex, const char* repl); + +sds gsub(sds str, const regex_t* regex, const char* repl); +sds gsub_getm(sds str, const regex_t *regex, const char* repl, int* *matches, int *matchesCount); + +int digits(int num); #endif -- cgit v1.2.3