Subversion Repositories Tewi

Rev

Rev 21 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 nishi 1
/* $Id: string.c 70 2024-09-19 09:23:45Z nishi $ */
3 nishi 2
 
3
#include <string.h>
4
#include <stdlib.h>
5 nishi 5
#include <stdbool.h>
20 nishi 6
#include <stdio.h>
5 nishi 7
#include <ctype.h>
3 nishi 8
 
9
char* cm_strcat(const char* a, const char* b) {
70 nishi 10
	if(a == NULL) a = "";
11
	if(b == NULL) b = "";
3 nishi 12
	char* str = malloc(strlen(a) + strlen(b) + 1);
13
	memcpy(str, a, strlen(a));
14
	memcpy(str + strlen(a), b, strlen(b));
15
	str[strlen(a) + strlen(b)] = 0;
16
	return str;
17
}
18
 
16 nishi 19
char* cm_strcat3(const char* a, const char* b, const char* c) {
20
	char* tmp = cm_strcat(a, b);
21
	char* str = cm_strcat(tmp, c);
22
	free(tmp);
23
	return str;
24
}
25
 
3 nishi 26
char* cm_strdup(const char* str) { return cm_strcat(str, ""); }
4 nishi 27
 
70 nishi 28
bool cm_endswith(const char* str, const char* end) {
29
	if(strlen(str) < strlen(end)) return false;
30
	int i;
31
	for(i = strlen(str) - strlen(end); i < strlen(str); i++) {
32
		if(str[i] != end[i - strlen(str) + strlen(end)]) return false;
33
	}
34
	return true;
35
}
36
 
37
bool cm_nocase_endswith(const char* str, const char* end) {
38
	if(strlen(str) < strlen(end)) return false;
39
	int i;
40
	for(i = strlen(str) - strlen(end); i < strlen(str); i++) {
41
		if(tolower(str[i]) != tolower(end[i - strlen(str) + strlen(end)])) return false;
42
	}
43
	return true;
44
}
45
 
6 nishi 46
char* cm_trimstart(const char* str) {
4 nishi 47
	int i;
6 nishi 48
	for(i = 0; str[i] != 0; i++) {
49
		if(str[i] != ' ' && str[i] != '\t') {
4 nishi 50
			return cm_strdup(str + i);
51
		}
52
	}
53
	return cm_strdup("");
54
}
55
 
6 nishi 56
char* cm_trimend(const char* str) {
4 nishi 57
	char* s = cm_strdup(str);
58
	int i;
6 nishi 59
	for(i = strlen(s) - 1; i >= 0; i--) {
60
		if(s[i] != '\t' && s[i] != ' ') {
4 nishi 61
			s[i + 1] = 0;
62
			break;
63
		}
64
	}
65
	return s;
66
}
67
 
6 nishi 68
char* cm_trim(const char* str) {
4 nishi 69
	char* tmp = cm_trimstart(str);
70
	char* s = cm_trimend(tmp);
71
	free(tmp);
72
	return s;
73
}
5 nishi 74
 
6 nishi 75
char** cm_split(const char* str, const char* by) {
5 nishi 76
	int i;
77
	char** r = malloc(sizeof(*r));
78
	r[0] = NULL;
79
	char* b = malloc(1);
80
	b[0] = 0;
81
	char cbuf[2];
82
	cbuf[1] = 0;
83
	bool dq = false;
84
	bool sq = false;
6 nishi 85
	for(i = 0;; i++) {
5 nishi 86
		int j;
87
		bool has = false;
6 nishi 88
		for(j = 0; by[j] != 0; j++) {
89
			if(by[j] == str[i]) {
5 nishi 90
				has = true;
91
				break;
92
			}
93
		}
6 nishi 94
		if(!(dq || sq) && (has || str[i] == 0)) {
95
			if(strlen(b) > 0) {
5 nishi 96
				char** old = r;
97
				int j;
6 nishi 98
				for(j = 0; old[j] != NULL; j++)
99
					;
5 nishi 100
				r = malloc(sizeof(*r) * (j + 2));
101
				for(j = 0; old[j] != NULL; j++) r[j] = old[j];
102
				r[j] = b;
103
				r[j + 1] = NULL;
104
				free(old);
105
			}
106
			b = malloc(1);
107
			b[0] = 0;
108
			if(str[i] == 0) break;
6 nishi 109
		} else {
110
			if(str[i] == '"' && !sq) {
5 nishi 111
				dq = !dq;
6 nishi 112
			} else if(str[i] == '\'' && !dq) {
5 nishi 113
				sq = !sq;
6 nishi 114
			} else {
5 nishi 115
				cbuf[0] = str[i];
116
				char* tmp = b;
117
				b = cm_strcat(tmp, cbuf);
118
				free(tmp);
119
			}
120
		}
121
	}
122
	free(b);
123
	return r;
124
}
125
 
6 nishi 126
bool cm_strcaseequ(const char* a, const char* b) {
5 nishi 127
	if(a == NULL) return false;
128
	if(b == NULL) return false;
129
	if(strlen(a) != strlen(b)) return false;
130
	int i;
6 nishi 131
	for(i = 0; a[i] != 0; i++) {
5 nishi 132
		if(tolower(a[i]) != tolower(b[i])) return false;
133
	}
134
	return true;
135
}
20 nishi 136
 
137
int cm_hex(const char* str, int len) {
138
	int n = 0;
139
	int i;
140
	for(i = 0; i < len; i++) {
141
		char c = str[i];
142
		n *= 16;
143
		if('0' <= c && c <= '9') {
144
			n += c - '0';
145
		} else if('a' <= c && c <= 'f') {
146
			n += c - 'a' + 10;
147
		} else if('A' <= c && c <= 'F') {
148
			n += c - 'A' + 10;
149
		}
150
	}
151
	return n;
152
}
153
 
154
char* cm_html_escape(const char* str) {
155
	int i;
156
	char* result = malloc(1);
157
	result[0] = 0;
158
	char cbuf[2];
159
	cbuf[1] = 0;
160
	for(i = 0; str[i] != 0; i++) {
161
		cbuf[0] = str[i];
162
		if(str[i] == '&') {
163
			char* tmp = result;
164
			result = cm_strcat(tmp, "&amp;");
165
			free(tmp);
166
		} else if(str[i] == '<') {
167
			char* tmp = result;
168
			result = cm_strcat(tmp, "&lt;");
169
			free(tmp);
170
		} else if(str[i] == '>') {
171
			char* tmp = result;
172
			result = cm_strcat(tmp, "&gt;");
173
			free(tmp);
174
		} else {
175
			char* tmp = result;
176
			result = cm_strcat(tmp, cbuf);
177
			free(tmp);
178
		}
179
	}
180
	return result;
181
}
21 nishi 182
 
183
char* cm_url_escape(const char* str) {
184
	int i;
185
	char* result = malloc(1);
186
	result[0] = 0;
187
	char cbuf[2];
188
	cbuf[1] = 0;
189
	for(i = 0; str[i] != 0; i++) {
190
		cbuf[0] = str[i];
191
		if('!' <= str[i] && str[i] <= '@' && str[i] != '.' && str[i] != '-' && str[i] != '/' && !('0' <= str[i] && str[i] <= '9')) {
192
			char code[4];
193
			sprintf(code, "%%%02X", str[i]);
194
			char* tmp = result;
195
			result = cm_strcat(tmp, code);
196
			free(tmp);
197
		} else {
198
			char* tmp = result;
199
			result = cm_strcat(tmp, cbuf);
200
			free(tmp);
201
		}
202
	}
203
	return result;
204
}