aboutsummaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authorSyndamia <kamen@syndamia.com>2023-12-08 16:39:59 +0200
committerSyndamia <kamen@syndamia.com>2023-12-08 16:39:59 +0200
commitf26e610c2f0bdb07fce3f7a100b3ef6159c2ffe7 (patch)
treea7b590d71d7e25ddd870eab949e7ce065f80f3db /util.c
parent0382fccd17bdab223166f20541005bf45f113726 (diff)
downloadpico-web-f26e610c2f0bdb07fce3f7a100b3ef6159c2ffe7.tar
pico-web-f26e610c2f0bdb07fce3f7a100b3ef6159c2ffe7.tar.gz
pico-web-f26e610c2f0bdb07fce3f7a100b3ef6159c2ffe7.zip
[browser] Implemented anchor parsing and navigation
Diffstat (limited to 'util.c')
-rw-r--r--util.c92
1 files changed, 83 insertions, 9 deletions
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;
+}