aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--browser.c97
-rw-r--r--util.c92
-rw-r--r--util.h7
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 <arpa/inet.h>
#include <unistd.h>
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sds/sds.h>
+#include <regex.h>
#include <util.h>
-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 <arpa/inet.h>
#include <stdlib.h>
+#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <regex.h>
@@ -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 <inttypes.h>
#include <sds/sds.h>
+#include <regex.h>
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