comparison th_string.c @ 11:707e35b03f89

Synced th-libs.
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 22 Mar 2008 02:52:01 +0000
parents ecfa4e3597e3
children e47955d42b55
comparison
equal deleted inserted replaced
10:53e127854dca 11:707e35b03f89
13 #define LPREV (pNode->pPrev) 13 #define LPREV (pNode->pPrev)
14 #define LNEXT (pNode->pNext) 14 #define LNEXT (pNode->pNext)
15 15
16 /* Allocate memory for a string with given length 16 /* Allocate memory for a string with given length
17 */ 17 */
18 char_t *th_stralloc(const size_t l) 18 char *th_stralloc(const size_t l)
19 { 19 {
20 assert(l > 0); 20 assert(l > 0);
21 return th_malloc(sizeof(char_t) * l); 21 return th_malloc(sizeof(char) * l);
22 } 22 }
23 23
24 24
25 char_t *th_strrealloc(char_t * s, const size_t l) 25 char *th_strrealloc(char * s, const size_t l)
26 { 26 {
27 assert(l > 0); 27 assert(l > 0);
28 return th_realloc(s, sizeof(char_t) * l); 28 return th_realloc(s, sizeof(char) * l);
29 }
30
31
32 /* Calculate the length of a string [strlen]
33 */
34 size_t th_strlen(char_t * pStr)
35 {
36 size_t l = 0;
37 char_t *s = pStr;
38 assert(pStr);
39
40 while (*s) {
41 s++;
42 l++;
43 }
44
45 return l;
46 } 29 }
47 30
48 31
49 /* Duplicate a string [strdup] 32 /* Duplicate a string [strdup]
50 */ 33 */
51 char_t *th_strdup(char_t * pStr) 34 char *th_strdup(char * str)
52 { 35 {
53 char_t *pResult, *s, *d; 36 char *result, *s, *d;
54 37
55 if (!pStr) return NULL; 38 if (!str) return NULL;
56 39
57 /* Allocate memory for destination */ 40 /* Allocate memory for destination */
58 pResult = th_stralloc(th_strlen(pStr) + 1); 41 result = th_stralloc(strlen(str) + 1);
59 if (!pResult) 42 if (!result)
60 return NULL; 43 return NULL;
61 44
62 /* Copy to the destination */ 45 /* Copy to the destination */
63 s = pStr; 46 s = str;
64 d = pResult; 47 d = result;
65 while (*s) { 48 while (*s) {
66 *(d++) = *(s++); 49 *(d++) = *(s++);
67 } 50 }
68 *d = 0; 51 *d = 0;
69 52
70 return pResult; 53 return result;
71 } 54 }
72 55
73 56
74 /* Concatenate a string [strcat] 57 char *th_strncpy(char * dst, char * src, size_t n)
75 */ 58 {
76 char_t *th_strcat(char_t * pDest, char_t * pSource) 59 char *s, *d;
77 {
78 char_t *s, *d;
79 assert(pSource);
80 assert(pDest);
81
82 /* Copy to the destination */
83 s = pSource;
84 d = pDest;
85
86 while (*d) d++;
87
88 while (*s) {
89 *(d++) = *(s++);
90 }
91 *d = 0;
92
93 return pDest;
94 }
95
96
97 /* Copy a string [strcpy, strncpy]
98 */
99 char_t *th_strcpy(char_t * pDest, char_t * pSource)
100 {
101 char_t *s, *d;
102 assert(pSource);
103 assert(pDest);
104
105 /* Copy to the destination */
106 s = pSource;
107 d = pDest;
108
109 while (*s) {
110 *(d++) = *(s++);
111 }
112 *d = 0;
113
114 return pDest;
115 }
116
117
118 char_t *th_strncpy(char_t * pDest, char_t * pSource, size_t n)
119 {
120 char_t *s, *d;
121 size_t i; 60 size_t i;
122 assert(pSource); 61 assert(src);
123 assert(pDest); 62 assert(dst);
124 63
125 /* Copy to the destination */ 64 /* Copy to the destination */
126 i = n; 65 i = n;
127 s = pSource; 66 s = src;
128 d = pDest; 67 d = dst;
129 while (*s && (i > 0)) { 68 while (*s && (i > 0)) {
130 *(d++) = *(s++); 69 *(d++) = *(s++);
131 i--; 70 i--;
132 } 71 }
133 72
136 *(d++) = 0; 75 *(d++) = 0;
137 i--; 76 i--;
138 } 77 }
139 78
140 /* Ensure that last is always zero */ 79 /* Ensure that last is always zero */
141 pDest[n - 1] = 0; 80 dst[n - 1] = 0;
142 81
143 return pDest; 82 return dst;
144 } 83 }
145 84
146 85
147 /* Compare given strings [strcmp, strncmp] 86 int th_strncmp(char * str1, char * str2, size_t n)
148 */ 87 {
149 int th_strcmp(char_t * pStr1, char_t * pStr2) 88 char *s1, *s2;
150 { 89 assert(str1);
151 char_t *s1, *s2; 90 assert(str2);
152 assert(pStr1);
153 assert(pStr2);
154 91
155 /* Check the string pointers */ 92 /* Check the string pointers */
156 if (pStr1 == pStr2) 93 if (str1 == str2)
157 return 0; 94 return 0;
158 95
159 /* Go through the string */ 96 /* Go through the string */
160 s1 = pStr1; 97 s1 = str1;
161 s2 = pStr2; 98 s2 = str2;
162 while (*s1 && *s2 && (*s1 == *s2)) {
163 s1++;
164 s2++;
165 }
166
167 return ((*s1) - (*s2));
168 }
169
170
171 int th_strncmp(char_t * pStr1, char_t * pStr2, size_t n)
172 {
173 char_t *s1, *s2;
174 assert(pStr1);
175 assert(pStr2);
176
177 /* Check the string pointers */
178 if (pStr1 == pStr2)
179 return 0;
180
181 /* Go through the string */
182 s1 = pStr1;
183 s2 = pStr2;
184 while ((n > 0) && *s1 && *s2 && (*s1 == *s2)) { 99 while ((n > 0) && *s1 && *s2 && (*s1 == *s2)) {
185 s1++; 100 s1++;
186 s2++; 101 s2++;
187 n--; 102 n--;
188 } 103 }
194 } 109 }
195 110
196 111
197 /* Compare two strings ignoring case [strcasecmp, strncasecmp] 112 /* Compare two strings ignoring case [strcasecmp, strncasecmp]
198 */ 113 */
199 int th_strcasecmp(char_t * pStr1, char_t * pStr2) 114 int th_strcasecmp(char * str1, char * str2)
200 { 115 {
201 char_t *s1, *s2; 116 char *s1 = str1, *s2 = str2;
202 assert(pStr1); 117 assert(str1);
203 assert(pStr2); 118 assert(str2);
204 119
205 /* Check the string pointers */ 120 /* Check the string pointers */
206 if (pStr1 == pStr2) 121 if (str1 == str2)
207 return 0; 122 return 0;
208 123
209 /* Go through the string */ 124 /* Go through the string */
210 s1 = pStr1;
211 s2 = pStr2;
212 while (*s1 && *s2 && (th_tolower(*s1) == th_tolower(*s2))) { 125 while (*s1 && *s2 && (th_tolower(*s1) == th_tolower(*s2))) {
213 s1++; 126 s1++;
214 s2++; 127 s2++;
215 } 128 }
216 129
217 return (th_tolower(*s1) - th_tolower(*s2)); 130 return (th_tolower(*s1) - th_tolower(*s2));
218 } 131 }
219 132
220 133
221 int th_strncasecmp(char_t * pStr1, char_t * pStr2, size_t n) 134 int th_strncasecmp(char * str1, char * str2, size_t n)
222 { 135 {
223 char_t *s1, *s2; 136 char *s1 = str1, *s2 = str2;
224 assert(pStr1); 137 assert(str1);
225 assert(pStr2); 138 assert(str2);
226 139
227 /* Check the string pointers */ 140 /* Check the string pointers */
228 if (pStr1 == pStr2) 141 if (str1 == str2)
229 return 0; 142 return 0;
230 143
231 /* Go through the string */ 144 /* Go through the string */
232 s1 = pStr1;
233 s2 = pStr2;
234 while ((n > 0) && *s1 && *s2 && (th_tolower(*s1) == th_tolower(*s2))) { 145 while ((n > 0) && *s1 && *s2 && (th_tolower(*s1) == th_tolower(*s2))) {
235 s1++; 146 s1++;
236 s2++; 147 s2++;
237 n--; 148 n--;
238 } 149 }
245 156
246 157
247 /* Remove all occurences of control characters, in-place. 158 /* Remove all occurences of control characters, in-place.
248 * Resulting string is always shorter or same length than original. 159 * Resulting string is always shorter or same length than original.
249 */ 160 */
250 void th_strip_ctrlchars(char_t * pStr) 161 void th_strip_ctrlchars(char * str)
251 { 162 {
252 char_t *i, *j; 163 char *i, *j;
253 assert(pStr); 164 assert(str);
254 165
255 i = pStr; 166 i = str;
256 j = pStr; 167 j = str;
257 while (*i) { 168 while (*i) {
258 if (!th_iscntrl(*i)) 169 if (!th_iscntrl(*i))
259 *(j++) = *i; 170 *(j++) = *i;
260 i++; 171 i++;
261 } 172 }
262 173
263 *j = 0; 174 *j = 0;
264 } 175 }
265 176
266 177
267 /* Locate a substring [strstr] 178 /* Copy a given string over in *result.
268 */ 179 */
269 char_t *th_strstr(char_t * haystack, char_t * needle) 180 int th_pstrcpy(char ** result, char * str)
270 { 181 {
271 char_t *h, *n, *s; 182 assert(result);
272 assert(haystack);
273 assert(needle);
274
275 /* If 'needle' is empty, we return 'haystack' */
276 if (!*needle)
277 return haystack;
278
279 /* Search for 'needle' in 'haystack' */
280 h = haystack;
281 n = needle;
282 while (*h) {
283 /* Find possible start of 'needle' */
284 while (*h && (*h != *n))
285 h++;
286
287 if (*h == *n) {
288 /* Found, check rest */
289 s = h;
290 n = needle;
291 while (*h) {
292 if (!*n)
293 return s;
294 else
295 if (*h != *n)
296 break;
297 n++;
298 h++;
299 }
300 h = s;
301 h++;
302 }
303 }
304
305 return NULL;
306 }
307
308
309 /* Copy a given string over in *ppResult.
310 */
311 int th_pstrcpy(char_t ** ppResult, char_t * pStr)
312 {
313 assert(ppResult);
314 183
315 /* Check the string pointers */ 184 /* Check the string pointers */
316 if (!pStr) 185 if (!str)
317 return -1; 186 return -1;
318 187
319 /* Allocate memory for destination */ 188 /* Allocate memory for destination */
320 th_free(*ppResult); 189 th_free(*result);
321 *ppResult = th_stralloc(th_strlen(pStr) + 1); 190 *result = th_stralloc(strlen(str) + 1);
322 if (!*ppResult) 191 if (!*result)
323 return -2; 192 return -2;
324 193
325 /* Copy to the destination */ 194 /* Copy to the destination */
326 th_strcpy(*ppResult, pStr); 195 strcpy(*result, str);
327 196
328 return 0; 197 return 0;
329 } 198 }
330 199
331 200
332 /* Concatenates a given string into string pointed by *ppResult. 201 /* Concatenates a given string into string pointed by *result.
333 */ 202 */
334 int th_pstrcat(char_t ** ppResult, char_t * pStr) 203 int th_pstrcat(char ** result, char * str)
335 { 204 {
336 assert(ppResult); 205 assert(result);
337 206
338 /* Check the string pointers */ 207 /* Check the string pointers */
339 if (!pStr) 208 if (!str)
340 return -1; 209 return -1;
341 210
342 if (*ppResult != NULL) { 211 if (*result != NULL) {
343 *ppResult = th_strrealloc(*ppResult, th_strlen(*ppResult) + th_strlen(pStr) + 1); 212 *result = th_strrealloc(*result, strlen(*result) + strlen(str) + 1);
344 if (*ppResult == NULL) 213 if (*result == NULL)
345 return -1; 214 return -1;
346 215
347 th_strcat(*ppResult, pStr); 216 strcat(*result, str);
348 } else { 217 } else {
349 *ppResult = th_stralloc(th_strlen(pStr) + 1); 218 *result = th_stralloc(strlen(str) + 1);
350 if (*ppResult == NULL) 219 if (*result == NULL)
351 return -1; 220 return -1;
352 221
353 th_strcpy(*ppResult, pStr); 222 strcpy(*result, str);
354 } 223 }
355 224
356 return 0; 225 return 0;
357 } 226 }
358 227
359 228
360 /* Find next non-whitespace character in string. 229 /* Find next non-whitespace character in string.
361 * Updates iPos into the position of such character and 230 * Updates iPos into the position of such character and
362 * returns pointer to the string. 231 * returns pointer to the string.
363 */ 232 */
364 char_t *th_findnext(char_t * pStr, size_t * iPos) 233 char *th_findnext(char * str, size_t * iPos)
365 { 234 {
366 assert(pStr); 235 assert(str);
367 236
368 /* Terminating NULL-character is not whitespace! */ 237 /* Terminating NULL-character is not whitespace! */
369 while (th_isspace(pStr[*iPos])) 238 while (th_isspace(str[*iPos]))
370 (*iPos)++; 239 (*iPos)++;
371 return &pStr[*iPos]; 240 return &str[*iPos];
372 } 241 }
373 242
374 243
375 /* Find next chSep-character from string 244 /* Find next chSep-character from string
376 */ 245 */
377 char_t *th_findsep(char_t * pStr, size_t * iPos, char_t chSep) 246 char *th_findsep(char * str, size_t * iPos, char chSep)
378 { 247 {
379 assert(pStr); 248 assert(str);
380 249
381 /* Terminating NULL-character is not digit! */ 250 /* Terminating NULL-character is not digit! */
382 while (pStr[*iPos] && (pStr[*iPos] != chSep)) 251 while (str[*iPos] && (str[*iPos] != chSep))
383 (*iPos)++; 252 (*iPos)++;
384 return &pStr[*iPos]; 253 return &str[*iPos];
385 } 254 }
386 255
387 256
388 /* Find next chSep- or whitespace from string 257 /* Find next chSep- or whitespace from string
389 */ 258 */
390 char_t *th_findseporspace(char_t * pStr, size_t * iPos, char_t chSep) 259 char *th_findseporspace(char * str, size_t * iPos, char chSep)
391 { 260 {
392 assert(pStr); 261 assert(str);
393 262
394 /* Terminating NULL-character is not digit! */ 263 /* Terminating NULL-character is not digit! */
395 while (!th_isspace(pStr[*iPos]) && (pStr[*iPos] != chSep)) 264 while (!th_isspace(str[*iPos]) && (str[*iPos] != chSep))
396 (*iPos)++; 265 (*iPos)++;
397 return &pStr[*iPos]; 266 return &str[*iPos];
398 } 267 }
399 268
400 269
401 /* Compare a string to a pattern. Case-SENSITIVE version. 270 /* Compare a string to a pattern. Case-SENSITIVE version.
402 * The matching pattern can consist of any normal characters plus 271 * The matching pattern can consist of any normal characters plus
403 * wildcards ? and *. "?" matches any character and "*" matches 272 * wildcards ? and *. "?" matches any character and "*" matches
404 * any number of characters. 273 * any number of characters.
405 */ 274 */
406 BOOL th_strmatch(char_t * pStr, char_t * pPattern) 275 BOOL th_strmatch(char * str, char * pattern)
407 { 276 {
408 BOOL didMatch, isAnyMode, isEnd; 277 BOOL didMatch, isAnyMode, isEnd;
409 char_t *tmpPattern; 278 char *tmpPattern;
410 279
411 /* Check given pattern and string */ 280 /* Check given pattern and string */
412 if (!pStr) 281 if (!str)
413 return FALSE; 282 return FALSE;
414 if (!pPattern) 283 if (!pattern)
415 return FALSE; 284 return FALSE;
416 285
417 /* Initialize */ 286 /* Initialize */
418 tmpPattern = NULL; 287 tmpPattern = NULL;
419 didMatch = TRUE; 288 didMatch = TRUE;
421 isAnyMode = FALSE; 290 isAnyMode = FALSE;
422 291
423 /* Start comparision */ 292 /* Start comparision */
424 do { 293 do {
425 didMatch = FALSE; 294 didMatch = FALSE;
426 switch (*pPattern) { 295 switch (*pattern) {
427 case '?': 296 case '?':
428 /* Any single character matches */ 297 /* Any single character matches */
429 if (*pStr) { 298 if (*str) {
430 didMatch = TRUE; 299 didMatch = TRUE;
431 pPattern++; 300 pattern++;
432 pStr++; 301 str++;
433 } 302 }
434 break; 303 break;
435 304
436 case '*': 305 case '*':
437 didMatch = TRUE; 306 didMatch = TRUE;
438 pPattern++; 307 pattern++;
439 if (!*pPattern) 308 if (!*pattern)
440 isEnd = TRUE; 309 isEnd = TRUE;
441 isAnyMode = TRUE; 310 isAnyMode = TRUE;
442 tmpPattern = pPattern; 311 tmpPattern = pattern;
443 break; 312 break;
444 313
445 case 0: 314 case 0:
446 if (isAnyMode) { 315 if (isAnyMode) {
447 if (*pStr) 316 if (*str)
448 pStr++; 317 str++;
449 else 318 else
450 isEnd = TRUE; 319 isEnd = TRUE;
451 } else { 320 } else {
452 if (*pStr) { 321 if (*str) {
453 if (tmpPattern) { 322 if (tmpPattern) {
454 isAnyMode = TRUE; 323 isAnyMode = TRUE;
455 pPattern = tmpPattern; 324 pattern = tmpPattern;
456 } else 325 } else
457 didMatch = FALSE; 326 didMatch = FALSE;
458 } else 327 } else
459 isEnd = TRUE; 328 isEnd = TRUE;
460 } 329 }
461 break; 330 break;
462 default: 331 default:
463 if (isAnyMode) { 332 if (isAnyMode) {
464 if ((*pPattern) == (*pStr)) { 333 if ((*pattern) == (*str)) {
465 isAnyMode = FALSE; 334 isAnyMode = FALSE;
466 didMatch = TRUE; 335 didMatch = TRUE;
467 } else { 336 } else {
468 if (*pStr) { 337 if (*str) {
469 didMatch = TRUE; 338 didMatch = TRUE;
470 pStr++; 339 str++;
471 } 340 }
472 } 341 }
473 } else { 342 } else {
474 if ((*pPattern) == (*pStr)) { 343 if ((*pattern) == (*str)) {
475 didMatch = TRUE; 344 didMatch = TRUE;
476 if (*pPattern) 345 if (*pattern)
477 pPattern++; 346 pattern++;
478 if (*pStr) 347 if (*str)
479 pStr++; 348 str++;
480 } else { 349 } else {
481 if (tmpPattern) { 350 if (tmpPattern) {
482 didMatch = TRUE; 351 didMatch = TRUE;
483 isAnyMode = TRUE; 352 isAnyMode = TRUE;
484 pPattern = tmpPattern; 353 pattern = tmpPattern;
485 } 354 }
486 } 355 }
487 } 356 }
488 357
489 if (!*pStr && !*pPattern) 358 if (!*str && !*pattern)
490 isEnd = TRUE; 359 isEnd = TRUE;
491 break; 360 break;
492 361
493 } /* switch */ 362 } /* switch */
494 363
498 } 367 }
499 368
500 369
501 /* Compare a string to a pattern. Case-INSENSITIVE version. 370 /* Compare a string to a pattern. Case-INSENSITIVE version.
502 */ 371 */
503 BOOL th_strcasematch(char_t * pStr, char_t * pPattern) 372 BOOL th_strcasematch(char * str, char * pattern)
504 { 373 {
505 BOOL didMatch, isAnyMode, isEnd; 374 BOOL didMatch, isAnyMode, isEnd;
506 char_t *tmpPattern; 375 char *tmpPattern;
507 376
508 /* Check given pattern and string */ 377 /* Check given pattern and string */
509 if (!pStr) 378 if (!str)
510 return FALSE; 379 return FALSE;
511 if (!pPattern) 380 if (!pattern)
512 return FALSE; 381 return FALSE;
513 382
514 /* Initialize */ 383 /* Initialize */
515 tmpPattern = NULL; 384 tmpPattern = NULL;
516 didMatch = TRUE; 385 didMatch = TRUE;
517 isEnd = FALSE; 386 isEnd = FALSE;
518 isAnyMode = FALSE; 387 isAnyMode = FALSE;
519 388
520 /* Start comparision */ 389 /* Start comparision */
521 do { 390 do {
522 switch (*pPattern) { 391 switch (*pattern) {
523 case '?': 392 case '?':
524 /* Any single character matches */ 393 /* Any single character matches */
525 if (*pStr) { 394 if (*str) {
526 pPattern++; 395 pattern++;
527 pStr++; 396 str++;
528 } else 397 } else
529 didMatch = FALSE; 398 didMatch = FALSE;
530 break; 399 break;
531 400
532 case '*': 401 case '*':
533 pPattern++; 402 pattern++;
534 if (!*pPattern || (*pPattern == '?')) 403 if (!*pattern || (*pattern == '?'))
535 isEnd = TRUE; 404 isEnd = TRUE;
536 isAnyMode = TRUE; 405 isAnyMode = TRUE;
537 tmpPattern = pPattern; 406 tmpPattern = pattern;
538 break; 407 break;
539 408
540 case 0: 409 case 0:
541 if (isAnyMode) { 410 if (isAnyMode) {
542 if (*pStr) 411 if (*str)
543 pStr++; 412 str++;
544 else 413 else
545 isEnd = TRUE; 414 isEnd = TRUE;
546 } else { 415 } else {
547 if (*pStr) { 416 if (*str) {
548 if (tmpPattern) { 417 if (tmpPattern) {
549 isAnyMode = TRUE; 418 isAnyMode = TRUE;
550 pPattern = tmpPattern; 419 pattern = tmpPattern;
551 } else 420 } else
552 didMatch = FALSE; 421 didMatch = FALSE;
553 } else 422 } else
554 isEnd = TRUE; 423 isEnd = TRUE;
555 } 424 }
556 break; 425 break;
557 426
558 default: 427 default:
559 if (isAnyMode) { 428 if (isAnyMode) {
560 if (th_tolower(*pPattern) == th_tolower(*pStr)) { 429 if (th_tolower(*pattern) == th_tolower(*str)) {
561 isAnyMode = FALSE; 430 isAnyMode = FALSE;
562 } else { 431 } else {
563 if (*pStr) 432 if (*str)
564 pStr++; 433 str++;
565 else 434 else
566 didMatch = FALSE; 435 didMatch = FALSE;
567 } 436 }
568 } else { 437 } else {
569 if (th_tolower(*pPattern) == th_tolower(*pStr)) { 438 if (th_tolower(*pattern) == th_tolower(*str)) {
570 if (*pPattern) 439 if (*pattern)
571 pPattern++; 440 pattern++;
572 if (*pStr) 441 if (*str)
573 pStr++; 442 str++;
574 } else { 443 } else {
575 if (tmpPattern) { 444 if (tmpPattern) {
576 isAnyMode = TRUE; 445 isAnyMode = TRUE;
577 pPattern = tmpPattern; 446 pattern = tmpPattern;
578 } else 447 } else
579 didMatch = FALSE; 448 didMatch = FALSE;
580 } 449 }
581 } 450 }
582 451
583 if (!*pStr && !*pPattern) 452 if (!*str && !*pattern)
584 isEnd = TRUE; 453 isEnd = TRUE;
585 break; 454 break;
586 455
587 } /* switch */ 456 } /* switch */
588 457
589 } while ((didMatch) && (!isEnd)); 458 } while ((didMatch) && (!isEnd));
590 459
591 return didMatch; 460 return didMatch;
592 } 461 }
593 462
594
595 /*
596 * Handling of string-lists and hashes
597 */
598 t_str_node *th_strnode_new(char_t * pcStr, ulint_t nUsed, void *pData)
599 {
600 t_str_node *pResult;
601
602 /* Allocate memory for new node */
603 pResult = (t_str_node *) th_calloc(1, sizeof(t_str_node));
604 if (!pResult)
605 return NULL;
606
607 /* Set fields */
608 th_pstrcpy(&pResult->pcStr, pcStr);
609 pResult->nUsed = nUsed;
610 pResult->pData = pData;
611
612 return pResult;
613 }
614
615
616 void th_strnode_free(t_str_node * pNode)
617 {
618 assert(pNode);
619
620 th_free(pNode->pcStr);
621 th_free(pNode);
622 }
623
624
625 /* Insert a new node into strlist
626 */
627 void th_strlist_insert(t_str_node ** strList, t_str_node * pNode)
628 {
629 assert(strList);
630 assert(pNode);
631
632 /* Insert into linked list */
633 if (*strList) {
634 /* The first node's pPrev points to last node */
635 LPREV = (*strList)->pPrev; /* New node's prev = Previous last node */
636 (*strList)->pPrev->pNext = pNode; /* Previous last node's next = New node */
637 (*strList)->pPrev = pNode; /* New last node = New node */
638 LNEXT = NULL; /* But next is NULL! */
639 } else {
640 (*strList) = pNode; /* First node ... */
641 LPREV = pNode; /* ... it's also last */
642 LNEXT = NULL; /* But next is NULL! */
643 }
644
645 }
646
647
648 /* Free a given strlist
649 */
650 void th_strlist_free(t_str_node * strList)
651 {
652 t_str_node *pNode, *nNode;
653
654 pNode = strList;
655 while (pNode) {
656 nNode = pNode->pNext;
657 th_strnode_free(pNode);
658 pNode = nNode;
659 }
660 }
661
662
663 /* Create a strIndex from strlist
664 */
665 t_str_index *th_strlist_makeindex(t_str_node * strList)
666 {
667 t_str_index *pResult;
668 t_str_node *pCurr;
669 ulint_t n;
670 assert(strList);
671
672 /* Computer number of nodes */
673 for (n = 0, pCurr = strList; pCurr; pCurr = pCurr->pNext)
674 n++;
675
676 /* Check number of nodes */
677 if (n == 0)
678 return NULL;
679
680 /* Allocate memory for index */
681 pResult = (t_str_index *) th_calloc(1, sizeof(t_str_index));
682 if (!pResult)
683 return NULL;
684
685 pResult->n = n;
686 pResult->ppIndex = (t_str_node **) th_calloc(n, sizeof(t_str_node *));
687 if (!pResult->ppIndex) {
688 th_free(pResult);
689 return NULL;
690 }
691
692 /* Create the index */
693 for (n = 0, pCurr = strList; pCurr && (n < pResult->n); pCurr = pCurr->pNext)
694 pResult->ppIndex[n++] = pCurr;
695
696 return pResult;
697 }
698
699
700 /* Insert a node into given strhash
701 */
702 int th_strhash_insert(t_str_hash strHash, t_str_node * pNode, BOOL ignoreCase)
703 {
704 int i;
705 assert(strHash);
706 assert(pNode);
707 assert(pNode->pcStr);
708
709 if (ignoreCase)
710 i = th_tolower(pNode->pcStr[0]);
711 else
712 i = pNode->pcStr[0];
713
714 /* Check the hashcode */
715 if ((i < 0) && (i >= SET_HASH_MAXINDEX))
716 return -1;
717
718 if (strHash[i]) {
719 /* The first node's pPrev points to last node */
720 pNode->pPrev = strHash[i]->pPrev; /* New node's prev = Previous last node */
721 strHash[i]->pPrev->pNext = pNode; /* Previous last node's next = New node */
722 strHash[i]->pPrev = pNode; /* New last node = New node */
723 pNode->pNext = NULL; /* But next is NULL! */
724 } else {
725 strHash[i] = pNode; /* First node */
726 pNode->pPrev = pNode; /* But also last */
727 pNode->pNext = NULL; /* But next is NULL! */
728 }
729
730 return 0;
731 }
732
733
734 /* Free a given strhash
735 */
736 void th_strhash_free(t_str_hash strHash)
737 {
738 int i;
739 assert(strHash);
740
741 for (i = 0; i < SET_HASH_MAXINDEX; i++)
742 th_strlist_free(strHash[i]);
743 }
744
745
746 /* Change pData for matching entries to new value
747 */
748 void th_strhash_change_pdata(t_str_hash strHash, void *pFind, void *pNew)
749 {
750 t_str_node *pCurr;
751 int i;
752 assert(strHash);
753
754 for (i = 0; i < SET_HASH_MAXINDEX; i++) {
755 /* Find from linked list */
756 pCurr = strHash[i];
757 while (pCurr) {
758 if (pCurr->pData == pFind)
759 pCurr->pData = pNew;
760
761 pCurr = pCurr->pNext;
762 }
763 }
764 }
765
766
767 /* Search a string from a given stringhash, either case-sensitive or insensitive
768 */
769 t_str_node *th_strhash_search(t_str_hash strHash, char_t * findStr, BOOL ignoreCase)
770 {
771 t_str_node *pCurr;
772 int i;
773 BOOL isFound;
774 assert(strHash);
775 assert(findStr);
776
777 isFound = FALSE;
778 pCurr = NULL;
779
780 /* Check hashcode */
781 if (ignoreCase)
782 i = ((unsigned char) th_tolower(findStr[0]));
783 else
784 i = ((unsigned char) findStr[0]);
785
786 if ((i < 0) && (i >= SET_HASH_MAXINDEX))
787 return NULL;
788
789 /* Find from linked list */
790 pCurr = strHash[i];
791
792 if (ignoreCase) {
793 /* Case in-sensitive search */
794 while (pCurr && !isFound) {
795 if (th_strcasecmp(findStr, pCurr->pcStr) == 0)
796 isFound = TRUE;
797 else
798 pCurr = pCurr->pNext;
799 }
800 } else {
801 /* Case sensitive search */
802 while (pCurr && !isFound) {
803 if (th_strcmp(findStr, pCurr->pcStr) == 0)
804 isFound = TRUE;
805 else
806 pCurr = pCurr->pNext;
807 }
808 }
809
810 /* Return result */
811 if (isFound)
812 return pCurr;
813 else
814 return NULL;
815 }
816
817
818 /* Create a strIndex from strHash
819 */
820 t_str_index *th_strhash_makeindex(t_str_hash strHash)
821 {
822 t_str_index *pResult;
823 t_str_node *pCurr;
824 unsigned int n, i;
825 assert(strHash);
826
827 /* Computer number of nodes */
828 for (n = i = 0; i < SET_HASH_MAXINDEX; i++) {
829 pCurr = strHash[i];
830 while (pCurr) {
831 n++;
832 pCurr = pCurr->pNext;
833 }
834 }
835
836 /* Check number of nodes */
837 if (n <= 0)
838 return NULL;
839
840 /* Allocate memory for index */
841 pResult = (t_str_index *) th_calloc(1, sizeof(t_str_index));
842 if (!pResult)
843 return NULL;
844
845 pResult->n = n;
846 pResult->ppIndex = (t_str_node **) th_calloc(n, sizeof(t_str_node *));
847 if (!pResult->ppIndex) {
848 th_free(pResult);
849 return NULL;
850 }
851
852 /* Create the index */
853 for (n = i = 0; (i < SET_HASH_MAXINDEX) && (n < pResult->n); i++) {
854 pCurr = strHash[i];
855 while (pCurr && (n < pResult->n)) {
856 pResult->ppIndex[n++] = pCurr;
857 pCurr = pCurr->pNext;
858 }
859 }
860
861 return pResult;
862 }
863
864
865 /* Free a given strIndex
866 */
867 void th_strindex_free(t_str_index * strIndex)
868 {
869 if (strIndex) {
870 th_free(strIndex->ppIndex);
871 th_free(strIndex);
872 }
873 }
874
875
876 /* Compare two t_str_nodes by nUsed
877 */
878 int th_strindex_cmp_used(const void *pNode1, const void *pNode2)
879 {
880 t_str_node *pStr1, *pStr2;
881
882 pStr1 = *(t_str_node **) pNode1;
883 pStr2 = *(t_str_node **) pNode2;
884
885 if (pStr1->nUsed > pStr2->nUsed)
886 return -1;
887 else if (pStr1->nUsed < pStr2->nUsed)
888 return 1;
889 else
890 return 0;
891 }
892
893
894 /* Sort an strIndex by nUsed, using th_strindex_cmp_used()
895 */
896 void th_strindex_sort_nused(t_str_index * strIndex)
897 {
898 assert(strIndex);
899 assert(strIndex->ppIndex);
900
901 qsort(strIndex->ppIndex, strIndex->n, sizeof(t_str_node *), th_strindex_cmp_used);
902 }
903
904
905 /* Compare two t_str_nodes via strcmp()
906 */
907 int th_strindex_cmp_alpha(const void *pNode1, const void *pNode2)
908 {
909 t_str_node *pStr1, *pStr2;
910
911 pStr1 = *(t_str_node **) pNode1;
912 pStr2 = *(t_str_node **) pNode2;
913
914 return th_strcmp(pStr1->pcStr, pStr2->pcStr);
915 }
916
917
918 /* Sort an strIndex by nUsed, using th_strindex_cmp_used()
919 */
920 void th_strindex_sort_alpha(t_str_index * strIndex)
921 {
922 assert(strIndex);
923 assert(strIndex->ppIndex);
924
925 qsort(strIndex->ppIndex, strIndex->n, sizeof(t_str_node *), th_strindex_cmp_alpha);
926 }