diff options
| author | Syndamia <kamen@syndamia.com> | 2024-01-06 11:15:57 +0200 |
|---|---|---|
| committer | Syndamia <kamen@syndamia.com> | 2024-01-06 11:15:57 +0200 |
| commit | cb86d3213519727a7fecd05b18b6a8adff230976 (patch) | |
| tree | 6eb60c98731014da7df5d05212ab94b14e6db29a /src/util.c | |
| parent | 56c2acfdbf1e4ee5d3fd44814a31ae64f57b3f49 (diff) | |
| download | pico-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.c | 180 |
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; +} |
