Subversion Repositories Tewi

Rev

Rev 70 | Details | Compare with Previous | Last modification | View Log | RSS feed

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