diff options
Diffstat (limited to 'util.c')
| -rw-r--r-- | util.c | 92 |
1 files changed, 83 insertions, 9 deletions
@@ -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; +} |
