1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include <util.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <regex.h>
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;
}
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 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();
// sdslen is in O(1) time
while (strInd < sdslen(str)) {
/* 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;
}
/* 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;
}
|