Mercurial > hg > nnchat
comparison th_string.c @ 81:69aed051f84d
Synced th-libs.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 20 Apr 2009 22:02:37 +0300 |
parents | e36df57c5b0f |
children | fe4d5f3b486c |
comparison
equal
deleted
inserted
replaced
80:335b5a74c22e | 81:69aed051f84d |
---|---|
16 | 16 |
17 /* strdup with a NULL check | 17 /* strdup with a NULL check |
18 */ | 18 */ |
19 char *th_strdup(const char *s) | 19 char *th_strdup(const char *s) |
20 { | 20 { |
21 char *res; | 21 char *res; |
22 if (s == NULL) | 22 if (s == NULL) |
23 return NULL; | 23 return NULL; |
24 | 24 |
25 if ((res = th_malloc(strlen(s) + 1)) == NULL) | 25 if ((res = th_malloc(strlen(s) + 1)) == NULL) |
26 return NULL; | 26 return NULL; |
27 | 27 |
28 strcpy(res, s); | 28 strcpy(res, s); |
29 return res; | 29 return res; |
30 } | 30 } |
31 | 31 |
32 | 32 |
33 /* Allocate memory for a string with given length | 33 /* Allocate memory for a string with given length |
34 */ | 34 */ |
35 char *th_stralloc(const size_t l) | 35 char *th_stralloc(const size_t l) |
36 { | 36 { |
37 assert(l > 0); | 37 assert(l > 0); |
38 return th_malloc(sizeof(char) * l); | 38 return th_malloc(sizeof(char) * l); |
39 } | 39 } |
40 | 40 |
41 | 41 |
42 char *th_strrealloc(char * s, const size_t l) | 42 char *th_strrealloc(char * s, const size_t l) |
43 { | 43 { |
44 assert(l > 0); | 44 assert(l > 0); |
45 return th_realloc(s, sizeof(char) * l); | 45 return th_realloc(s, sizeof(char) * l); |
46 } | 46 } |
47 | 47 |
48 | 48 |
49 char *th_strncpy(char * dst, const char * src, size_t n) | 49 char *th_strncpy(char * dst, const char * src, size_t n) |
50 { | 50 { |
51 const char *s = src; | 51 const char *s = src; |
52 char *d = dst; | 52 char *d = dst; |
53 size_t i; | 53 size_t i; |
54 assert(src != NULL); | 54 assert(src != NULL); |
55 assert(dst != NULL); | 55 assert(dst != NULL); |
56 | 56 |
57 /* Copy to the destination */ | 57 /* Copy to the destination */ |
58 i = n; | 58 i = n; |
59 while (*s && (i > 0)) { | 59 while (*s && (i > 0)) { |
60 *(d++) = *(s++); | 60 *(d++) = *(s++); |
61 i--; | 61 i--; |
62 } | 62 } |
63 | 63 |
64 /* Fill rest of space with zeros */ | 64 /* Fill rest of space with zeros */ |
65 while (i > 0) { | 65 while (i > 0) { |
66 *(d++) = 0; | 66 *(d++) = 0; |
67 i--; | 67 i--; |
68 } | 68 } |
69 | 69 |
70 /* Ensure that last is always zero */ | 70 /* Ensure that last is always zero */ |
71 dst[n - 1] = 0; | 71 dst[n - 1] = 0; |
72 | 72 |
73 return dst; | 73 return dst; |
74 } | 74 } |
75 | 75 |
76 | 76 |
77 int th_strncmp(char * str1, char * str2, size_t n) | 77 int th_strncmp(char * str1, char * str2, size_t n) |
78 { | 78 { |
79 char *s1, *s2; | 79 char *s1, *s2; |
80 assert(str1 != NULL); | 80 assert(str1 != NULL); |
81 assert(str2 != NULL); | 81 assert(str2 != NULL); |
82 | 82 |
83 /* Check the string pointers */ | 83 /* Check the string pointers */ |
84 if (str1 == str2) | 84 if (str1 == str2) |
85 return 0; | 85 return 0; |
86 | 86 |
87 /* Go through the string */ | 87 /* Go through the string */ |
88 s1 = str1; | 88 s1 = str1; |
89 s2 = str2; | 89 s2 = str2; |
90 while ((n > 0) && *s1 && *s2 && (*s1 == *s2)) { | 90 while ((n > 0) && *s1 && *s2 && (*s1 == *s2)) { |
91 s1++; | 91 s1++; |
92 s2++; | 92 s2++; |
93 n--; | 93 n--; |
94 } | 94 } |
95 | 95 |
96 if (n > 0) | 96 if (n > 0) |
97 return ((*s1) - (*s2)); | 97 return ((*s1) - (*s2)); |
98 else | 98 else |
99 return 0; | 99 return 0; |
100 } | 100 } |
101 | 101 |
102 | 102 |
103 /* Compare two strings ignoring case [strcasecmp, strncasecmp] | 103 /* Compare two strings ignoring case [strcasecmp, strncasecmp] |
104 */ | 104 */ |
105 int th_strcasecmp(char * str1, char * str2) | 105 int th_strcasecmp(char * str1, char * str2) |
106 { | 106 { |
107 char *s1 = str1, *s2 = str2; | 107 char *s1 = str1, *s2 = str2; |
108 assert(str1 != NULL); | 108 assert(str1 != NULL); |
109 assert(str2 != NULL); | 109 assert(str2 != NULL); |
110 | 110 |
111 /* Check the string pointers */ | 111 /* Check the string pointers */ |
112 if (str1 == str2) | 112 if (str1 == str2) |
113 return 0; | 113 return 0; |
114 | 114 |
115 /* Go through the string */ | 115 /* Go through the string */ |
116 while (*s1 && *s2 && (th_tolower(*s1) == th_tolower(*s2))) { | 116 while (*s1 && *s2 && (th_tolower(*s1) == th_tolower(*s2))) { |
117 s1++; | 117 s1++; |
118 s2++; | 118 s2++; |
119 } | 119 } |
120 | 120 |
121 return (th_tolower(*s1) - th_tolower(*s2)); | 121 return (th_tolower(*s1) - th_tolower(*s2)); |
122 } | 122 } |
123 | 123 |
124 | 124 |
125 int th_strncasecmp(char * str1, char * str2, size_t n) | 125 int th_strncasecmp(char * str1, char * str2, size_t n) |
126 { | 126 { |
127 char *s1 = str1, *s2 = str2; | 127 char *s1 = str1, *s2 = str2; |
128 assert(str1 != NULL); | 128 assert(str1 != NULL); |
129 assert(str2 != NULL); | 129 assert(str2 != NULL); |
130 | 130 |
131 /* Check the string pointers */ | 131 /* Check the string pointers */ |
132 if (str1 == str2) | 132 if (str1 == str2) |
133 return 0; | 133 return 0; |
134 | 134 |
135 /* Go through the string */ | 135 /* Go through the string */ |
136 while ((n > 0) && *s1 && *s2 && (th_tolower(*s1) == th_tolower(*s2))) { | 136 while ((n > 0) && *s1 && *s2 && (th_tolower(*s1) == th_tolower(*s2))) { |
137 s1++; | 137 s1++; |
138 s2++; | 138 s2++; |
139 n--; | 139 n--; |
140 } | 140 } |
141 | 141 |
142 if (n > 0) | 142 if (n > 0) |
143 return (th_tolower(*s1) - th_tolower(*s2)); | 143 return (th_tolower(*s1) - th_tolower(*s2)); |
144 else | 144 else |
145 return 0; | 145 return 0; |
146 } | 146 } |
147 | 147 |
148 | 148 |
149 /* Remove all occurences of control characters, in-place. | 149 /* Remove all occurences of control characters, in-place. |
150 * Resulting string is always shorter or same length than original. | 150 * Resulting string is always shorter or same length than original. |
151 */ | 151 */ |
152 void th_strip_ctrlchars(char * str) | 152 void th_strip_ctrlchars(char * str) |
153 { | 153 { |
154 char *i, *j; | 154 char *i, *j; |
155 assert(str != NULL); | 155 assert(str != NULL); |
156 | 156 |
157 i = str; | 157 i = str; |
158 j = str; | 158 j = str; |
159 while (*i) { | 159 while (*i) { |
160 if (!th_iscntrl(*i)) | 160 if (!th_iscntrl(*i)) |
161 *(j++) = *i; | 161 *(j++) = *i; |
162 i++; | 162 i++; |
163 } | 163 } |
164 | 164 |
165 *j = 0; | 165 *j = 0; |
166 } | 166 } |
167 | 167 |
168 | 168 |
169 /* Copy a given string over in *result. | 169 /* Copy a given string over in *result. |
170 */ | 170 */ |
171 int th_pstrcpy(char ** result, char * str) | 171 int th_pstrcpy(char ** result, char * str) |
172 { | 172 { |
173 assert(result != NULL); | 173 assert(result != NULL); |
174 | 174 |
175 /* Check the string pointers */ | 175 /* Check the string pointers */ |
176 if (str == NULL) | 176 if (str == NULL) |
177 return -1; | 177 return -1; |
178 | 178 |
179 /* Allocate memory for destination */ | 179 /* Allocate memory for destination */ |
180 th_free(*result); | 180 th_free(*result); |
181 *result = th_stralloc(strlen(str) + 1); | 181 *result = th_stralloc(strlen(str) + 1); |
182 if (!*result) | 182 if (!*result) |
183 return -2; | 183 return -2; |
184 | 184 |
185 /* Copy to the destination */ | 185 /* Copy to the destination */ |
186 strcpy(*result, str); | 186 strcpy(*result, str); |
187 | 187 |
188 return 0; | 188 return 0; |
189 } | 189 } |
190 | 190 |
191 | 191 |
192 /* Concatenates a given string into string pointed by *result. | 192 /* Concatenates a given string into string pointed by *result. |
193 */ | 193 */ |
194 int th_pstrcat(char ** result, char * str) | 194 int th_pstrcat(char ** result, char * str) |
195 { | 195 { |
196 assert(result != NULL); | 196 assert(result != NULL); |
197 | 197 |
198 /* Check the string pointers */ | 198 /* Check the string pointers */ |
199 if (str == NULL) | 199 if (str == NULL) |
200 return -1; | 200 return -1; |
201 | 201 |
202 if (*result != NULL) { | 202 if (*result != NULL) { |
203 *result = th_strrealloc(*result, strlen(*result) + strlen(str) + 1); | 203 *result = th_strrealloc(*result, strlen(*result) + strlen(str) + 1); |
204 if (*result == NULL) | 204 if (*result == NULL) |
205 return -1; | 205 return -1; |
206 | 206 |
207 strcat(*result, str); | 207 strcat(*result, str); |
208 } else { | 208 } else { |
209 *result = th_stralloc(strlen(str) + 1); | 209 *result = th_stralloc(strlen(str) + 1); |
210 if (*result == NULL) | 210 if (*result == NULL) |
211 return -1; | 211 return -1; |
212 | 212 |
213 strcpy(*result, str); | 213 strcpy(*result, str); |
214 } | 214 } |
215 | 215 |
216 return 0; | 216 return 0; |
217 } | 217 } |
218 | 218 |
219 | 219 |
220 /* Find next non-whitespace character in string. | 220 /* Find next non-whitespace character in string. |
221 * Updates iPos into the position of such character and | 221 * Updates iPos into the position of such character and |
222 * returns pointer to the string. | 222 * returns pointer to the string. |
223 */ | 223 */ |
224 char *th_findnext(char * str, size_t * iPos) | 224 char *th_findnext(char * str, size_t * iPos) |
225 { | 225 { |
226 assert(str != NULL); | 226 assert(str != NULL); |
227 | 227 |
228 /* Terminating NULL-character is not whitespace! */ | 228 /* Terminating NULL-character is not whitespace! */ |
229 while (th_isspace(str[*iPos])) | 229 while (th_isspace(str[*iPos])) |
230 (*iPos)++; | 230 (*iPos)++; |
231 return &str[*iPos]; | 231 return &str[*iPos]; |
232 } | 232 } |
233 | 233 |
234 | 234 |
235 /* Find next chSep-character from string | 235 /* Find next chSep-character from string |
236 */ | 236 */ |
237 char *th_findsep(char * str, size_t * iPos, char chSep) | 237 char *th_findsep(char * str, size_t * iPos, char chSep) |
238 { | 238 { |
239 assert(str != NULL); | 239 assert(str != NULL); |
240 | 240 |
241 /* Terminating NULL-character is not digit! */ | 241 /* Terminating NULL-character is not digit! */ |
242 while (str[*iPos] && (str[*iPos] != chSep)) | 242 while (str[*iPos] && (str[*iPos] != chSep)) |
243 (*iPos)++; | 243 (*iPos)++; |
244 return &str[*iPos]; | 244 return &str[*iPos]; |
245 } | 245 } |
246 | 246 |
247 | 247 |
248 /* Find next chSep- or whitespace from string | 248 /* Find next chSep- or whitespace from string |
249 */ | 249 */ |
250 char *th_findseporspace(char * str, size_t * iPos, char chSep) | 250 char *th_findseporspace(char * str, size_t * iPos, char chSep) |
251 { | 251 { |
252 assert(str != NULL); | 252 assert(str != NULL); |
253 | 253 |
254 /* Terminating NULL-character is not digit! */ | 254 /* Terminating NULL-character is not digit! */ |
255 while (!th_isspace(str[*iPos]) && (str[*iPos] != chSep)) | 255 while (!th_isspace(str[*iPos]) && (str[*iPos] != chSep)) |
256 (*iPos)++; | 256 (*iPos)++; |
257 return &str[*iPos]; | 257 return &str[*iPos]; |
258 } | 258 } |
259 | 259 |
260 | 260 |
261 /* Compare a string to a pattern. Case-SENSITIVE version. | 261 /* Compare a string to a pattern. Case-SENSITIVE version. |
262 * The matching pattern can consist of any normal characters plus | 262 * The matching pattern can consist of any normal characters plus |
263 * wildcards ? and *. "?" matches any character and "*" matches | 263 * wildcards ? and *. "?" matches any character and "*" matches |
264 * any number of characters. | 264 * any number of characters. |
265 */ | 265 */ |
266 BOOL th_strmatch(char * str, char * pattern) | 266 BOOL th_strmatch(char * str, char * pattern) |
267 { | 267 { |
268 BOOL didMatch = TRUE, isAnyMode = FALSE, isEnd = FALSE; | 268 BOOL didMatch = TRUE, isAnyMode = FALSE, isEnd = FALSE; |
269 char *tmpPattern = NULL; | 269 char *tmpPattern = NULL; |
270 | 270 |
271 /* Check given pattern and string */ | 271 /* Check given pattern and string */ |
272 if (str == NULL || pattern == NULL) | 272 if (str == NULL || pattern == NULL) |
273 return FALSE; | 273 return FALSE; |
274 | 274 |
275 /* Start comparision */ | 275 /* Start comparision */ |
276 do { | 276 do { |
277 didMatch = FALSE; | 277 didMatch = FALSE; |
278 switch (*pattern) { | 278 switch (*pattern) { |
279 case '?': | 279 case '?': |
280 /* Any single character matches */ | 280 /* Any single character matches */ |
281 if (*str) { | 281 if (*str) { |
282 didMatch = TRUE; | 282 didMatch = TRUE; |
283 pattern++; | 283 pattern++; |
284 str++; | 284 str++; |
285 } | 285 } |
286 break; | 286 break; |
287 | 287 |
288 case '*': | 288 case '*': |
289 didMatch = TRUE; | 289 didMatch = TRUE; |
290 pattern++; | 290 pattern++; |
291 if (!*pattern) | 291 if (!*pattern) |
292 isEnd = TRUE; | 292 isEnd = TRUE; |
293 isAnyMode = TRUE; | 293 isAnyMode = TRUE; |
294 tmpPattern = pattern; | 294 tmpPattern = pattern; |
295 break; | 295 break; |
296 | 296 |
297 case 0: | 297 case 0: |
298 if (isAnyMode) { | 298 if (isAnyMode) { |
299 if (*str) | 299 if (*str) |
300 str++; | 300 str++; |
301 else | 301 else |
302 isEnd = TRUE; | 302 isEnd = TRUE; |
303 } else { | 303 } else { |
304 if (*str) { | 304 if (*str) { |
305 if (tmpPattern) { | 305 if (tmpPattern) { |
306 isAnyMode = TRUE; | 306 isAnyMode = TRUE; |
307 pattern = tmpPattern; | 307 pattern = tmpPattern; |
308 } else | 308 } else |
309 didMatch = FALSE; | 309 didMatch = FALSE; |
310 } else | 310 } else |
311 isEnd = TRUE; | 311 isEnd = TRUE; |
312 } | 312 } |
313 break; | 313 break; |
314 default: | 314 default: |
315 if (isAnyMode) { | 315 if (isAnyMode) { |
316 if (*pattern == *str) { | 316 if (*pattern == *str) { |
317 isAnyMode = FALSE; | 317 isAnyMode = FALSE; |
318 didMatch = TRUE; | 318 didMatch = TRUE; |
319 } else { | 319 } else { |
320 if (*str) { | 320 if (*str) { |
321 didMatch = TRUE; | 321 didMatch = TRUE; |
322 str++; | 322 str++; |
323 } | 323 } |
324 } | 324 } |
325 } else { | 325 } else { |
326 if (*pattern == *str) { | 326 if (*pattern == *str) { |
327 didMatch = TRUE; | 327 didMatch = TRUE; |
328 if (*pattern) | 328 if (*pattern) |
329 pattern++; | 329 pattern++; |
330 if (*str) | 330 if (*str) |
331 str++; | 331 str++; |
332 } else { | 332 } else { |
333 if (tmpPattern) { | 333 if (tmpPattern) { |
334 didMatch = TRUE; | 334 didMatch = TRUE; |
335 isAnyMode = TRUE; | 335 isAnyMode = TRUE; |
336 pattern = tmpPattern; | 336 pattern = tmpPattern; |
337 } | 337 } |
338 } | 338 } |
339 } | 339 } |
340 | 340 |
341 if (!*str && !*pattern) | 341 if (!*str && !*pattern) |
342 isEnd = TRUE; | 342 isEnd = TRUE; |
343 break; | 343 break; |
344 | 344 |
345 } /* switch */ | 345 } /* switch */ |
346 | 346 |
347 } while (didMatch && !isEnd); | 347 } while (didMatch && !isEnd); |
348 | 348 |
349 return didMatch; | 349 return didMatch; |
350 } | 350 } |
351 | 351 |
352 | 352 |
353 /* Compare a string to a pattern. Case-INSENSITIVE version. | 353 /* Compare a string to a pattern. Case-INSENSITIVE version. |
354 */ | 354 */ |
355 BOOL th_strcasematch(char * str, char * pattern) | 355 BOOL th_strcasematch(char * str, char * pattern) |
356 { | 356 { |
357 BOOL didMatch = TRUE, isAnyMode = FALSE, isEnd = FALSE; | 357 BOOL didMatch = TRUE, isAnyMode = FALSE, isEnd = FALSE; |
358 char *tmpPattern = NULL; | 358 char *tmpPattern = NULL; |
359 | 359 |
360 /* Check given pattern and string */ | 360 /* Check given pattern and string */ |
361 if (str == NULL || pattern == NULL) | 361 if (str == NULL || pattern == NULL) |
362 return FALSE; | 362 return FALSE; |
363 | 363 |
364 /* Start comparision */ | 364 /* Start comparision */ |
365 do { | 365 do { |
366 switch (*pattern) { | 366 switch (*pattern) { |
367 case '?': | 367 case '?': |
368 /* Any single character matches */ | 368 /* Any single character matches */ |
369 if (*str) { | 369 if (*str) { |
370 pattern++; | 370 pattern++; |
371 str++; | 371 str++; |
372 } else | 372 } else |
373 didMatch = FALSE; | 373 didMatch = FALSE; |
374 break; | 374 break; |
375 | 375 |
376 case '*': | 376 case '*': |
377 pattern++; | 377 pattern++; |
378 if (!*pattern || *pattern == '?') | 378 if (!*pattern || *pattern == '?') |
379 isEnd = TRUE; | 379 isEnd = TRUE; |
380 isAnyMode = TRUE; | 380 isAnyMode = TRUE; |
381 tmpPattern = pattern; | 381 tmpPattern = pattern; |
382 break; | 382 break; |
383 | 383 |
384 case 0: | 384 case 0: |
385 if (isAnyMode) { | 385 if (isAnyMode) { |
386 if (*str) | 386 if (*str) |
387 str++; | 387 str++; |
388 else | 388 else |
389 isEnd = TRUE; | 389 isEnd = TRUE; |
390 } else { | 390 } else { |
391 if (*str) { | 391 if (*str) { |
392 if (tmpPattern) { | 392 if (tmpPattern) { |
393 isAnyMode = TRUE; | 393 isAnyMode = TRUE; |
394 pattern = tmpPattern; | 394 pattern = tmpPattern; |
395 } else | 395 } else |
396 didMatch = FALSE; | 396 didMatch = FALSE; |
397 } else | 397 } else |
398 isEnd = TRUE; | 398 isEnd = TRUE; |
399 } | 399 } |
400 break; | 400 break; |
401 | 401 |
402 default: | 402 default: |
403 if (isAnyMode) { | 403 if (isAnyMode) { |
404 if (th_tolower(*pattern) == th_tolower(*str)) { | 404 if (th_tolower(*pattern) == th_tolower(*str)) { |
405 isAnyMode = FALSE; | 405 isAnyMode = FALSE; |
406 } else { | 406 } else { |
407 if (*str) | 407 if (*str) |
408 str++; | 408 str++; |
409 else | 409 else |
410 didMatch = FALSE; | 410 didMatch = FALSE; |
411 } | 411 } |
412 } else { | 412 } else { |
413 if (th_tolower(*pattern) == th_tolower(*str)) { | 413 if (th_tolower(*pattern) == th_tolower(*str)) { |
414 if (*pattern) | 414 if (*pattern) |
415 pattern++; | 415 pattern++; |
416 if (*str) | 416 if (*str) |
417 str++; | 417 str++; |
418 } else { | 418 } else { |
419 if (tmpPattern) { | 419 if (tmpPattern) { |
420 isAnyMode = TRUE; | 420 isAnyMode = TRUE; |
421 pattern = tmpPattern; | 421 pattern = tmpPattern; |
422 } else | 422 } else |
423 didMatch = FALSE; | 423 didMatch = FALSE; |
424 } | 424 } |
425 } | 425 } |
426 | 426 |
427 if (!*str && !*pattern) | 427 if (!*str && !*pattern) |
428 isEnd = TRUE; | 428 isEnd = TRUE; |
429 break; | 429 break; |
430 | 430 |
431 } /* switch */ | 431 } /* switch */ |
432 | 432 |
433 } while (didMatch && !isEnd); | 433 } while (didMatch && !isEnd); |
434 | 434 |
435 return didMatch; | 435 return didMatch; |
436 } | 436 } |
437 | 437 |