aboutsummaryrefslogtreecommitdiff
path: root/util.c
blob: f2c464ead736373e06078777b40590eb47c27c65 (plain) (blame)
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;
}