aboutsummaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
authorSyndamia <kamen@syndamia.com>2024-01-06 11:15:57 +0200
committerSyndamia <kamen@syndamia.com>2024-01-06 11:15:57 +0200
commitcb86d3213519727a7fecd05b18b6a8adff230976 (patch)
tree6eb60c98731014da7df5d05212ab94b14e6db29a /src/util.c
parent56c2acfdbf1e4ee5d3fd44814a31ae64f57b3f49 (diff)
downloadpico-web-cb86d3213519727a7fecd05b18b6a8adff230976.tar
pico-web-cb86d3213519727a7fecd05b18b6a8adff230976.tar.gz
pico-web-cb86d3213519727a7fecd05b18b6a8adff230976.zip
(src) Moved source files to a src folder
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 0000000..822a4d2
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,180 @@
+#include <util.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <regex.h>
+
+/*
+ * Networking
+ */
+
+uint16_t atop(const char *port) {
+ return htons(atoi(port));
+}
+
+struct in_addr aton(const char* cp, int* output) {
+ struct in_addr inp;
+ *output = inet_aton(cp, &inp);
+ return inp;
+}
+
+/*
+ * Error handling
+ */
+
+void herrc(int output, const char* funcName) {
+ if (output < 0 && errno != EINTR) {
+ perror(funcName);
+ }
+}
+
+void herr(int output, const char* funcName) {
+ if (output < 0) {
+ perror(funcName);
+ exit(errno);
+ }
+}
+
+/*
+ * sds string substitution
+ */
+
+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;
+}
+
+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();
+ /*
+ * Substitute all occurences of regex with repl in str
+ */
+ // sdslen is in O(1) time
+ while (strInd < sdslen(str)) {
+ /* Run regex */
+ if (regexec(regex, MATCHSTART, 10, pmatch, 0) != 0) {
+ /* If there are no matches, return the rest of the string as-is */
+ ret = sdscat(ret, MATCHSTART);
+ break;
+ }
+
+ /* Store everything before the match as-is */
+ ret = sdscatlen(ret, MATCHSTART, pmatch[0].rm_so);
+
+ /* Replace match with repl
+ * repl can include matched subexpressions */
+ for(size_t i = 0; i < replLen; i++) {
+ if (repl[i] <= '\10') {
+ if (pmatch[repl[i] % 10].rm_so > -1) {
+ sds match = getMatch(MATCHSTART, pmatch[repl[i] % 10]);
+ ret = sdscatsds(ret, match);
+ sdsfree(match);
+ }
+ }
+ else
+ ret = sdscatlen(ret, &repl[i], 1);
+ }
+
+ /* Add index of current match to matches */
+ 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);
+}
+
+/*
+ * other
+ */
+
+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;
+}
+
+int streq(const char* first, const char* second) {
+ return strcmp(first, second) == 0;
+}
+
+void shiftLeft(char* str, size_t size, size_t shift) {
+ while (*(str + shift - 1) != '\0') {
+ *str = *(str + shift);
+ str++;
+ }
+}
+
+int isNumber(char* str) {
+ while (*str >= ' ') {
+ if (*str < '0' || *str > '9') return 0;
+ str++;
+ }
+ return 1;
+}
+
+int charCount(char* str, char cmp) {
+ int count = 0;
+ while (*str != '\0') {
+ count += *str == cmp;
+ str++;
+ }
+ return count;
+}