Mercurial > hg > nnchat
comparison th_string.c @ 0:728243125263
Import.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 20 Mar 2008 00:15:03 +0000 |
parents | |
children | ecfa4e3597e3 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:728243125263 |
---|---|
1 /* | |
2 * Miscellaneous string-handling related utility-functions | |
3 * Programmed and designed by Matti 'ccr' Hamalainen | |
4 * (C) Copyright 2002-2008 Tecnic Software productions (TNSP) | |
5 * | |
6 * Please read file 'COPYING' for information on license and distribution. | |
7 */ | |
8 #ifdef HAVE_CONFIG_H | |
9 #include <config.h> | |
10 #endif | |
11 #include "th_string.h" | |
12 | |
13 #define LPREV (pNode->pPrev) | |
14 #define LNEXT (pNode->pNext) | |
15 | |
16 /* Allocate memory for a string with given length | |
17 */ | |
18 char_t *th_stralloc(const size_t l) | |
19 { | |
20 assert(l > 0); | |
21 return th_malloc(sizeof(char_t) * l); | |
22 } | |
23 | |
24 | |
25 char_t *th_strrealloc(char_t * s, const size_t l) | |
26 { | |
27 assert(l > 0); | |
28 return th_realloc(s, sizeof(char_t) * 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 } | |
47 | |
48 | |
49 /* Duplicate a string [strdup] | |
50 */ | |
51 char_t *th_strdup(char_t * pStr) | |
52 { | |
53 char_t *pResult, *s, *d; | |
54 | |
55 if (!pStr) return NULL; | |
56 | |
57 /* Allocate memory for destination */ | |
58 pResult = th_stralloc(th_strlen(pStr) + 1); | |
59 if (!pResult) | |
60 return NULL; | |
61 | |
62 /* Copy to the destination */ | |
63 s = pStr; | |
64 d = pResult; | |
65 while (*s) { | |
66 *(d++) = *(s++); | |
67 } | |
68 *d = 0; | |
69 | |
70 return pResult; | |
71 } | |
72 | |
73 | |
74 /* Concatenate a string [strcat] | |
75 */ | |
76 char_t *th_strcat(char_t * pDest, char_t * pSource) | |
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; | |
122 assert(pSource); | |
123 assert(pDest); | |
124 | |
125 /* Copy to the destination */ | |
126 i = n; | |
127 s = pSource; | |
128 d = pDest; | |
129 while (*s && (i > 0)) { | |
130 *(d++) = *(s++); | |
131 i--; | |
132 } | |
133 | |
134 /* Fill rest of space with zeros */ | |
135 while (i > 0) { | |
136 *(d++) = 0; | |
137 i--; | |
138 } | |
139 | |
140 /* Ensure that last is always zero */ | |
141 pDest[n - 1] = 0; | |
142 | |
143 return pDest; | |
144 } | |
145 | |
146 | |
147 /* Compare given strings [strcmp, strncmp] | |
148 */ | |
149 int th_strcmp(char_t * pStr1, char_t * pStr2) | |
150 { | |
151 char_t *s1, *s2; | |
152 assert(pStr1); | |
153 assert(pStr2); | |
154 | |
155 /* Check the string pointers */ | |
156 if (pStr1 == pStr2) | |
157 return 0; | |
158 | |
159 /* Go through the string */ | |
160 s1 = pStr1; | |
161 s2 = pStr2; | |
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)) { | |
185 s1++; | |
186 s2++; | |
187 n--; | |
188 } | |
189 | |
190 if (n > 0) | |
191 return ((*s1) - (*s2)); | |
192 else | |
193 return 0; | |
194 } | |
195 | |
196 | |
197 /* Compare two strings ignoring case [strcasecmp, strncasecmp] | |
198 */ | |
199 int th_strcasecmp(char_t * pStr1, char_t * pStr2) | |
200 { | |
201 char_t *s1, *s2; | |
202 assert(pStr1); | |
203 assert(pStr2); | |
204 | |
205 /* Check the string pointers */ | |
206 if (pStr1 == pStr2) | |
207 return 0; | |
208 | |
209 /* Go through the string */ | |
210 s1 = pStr1; | |
211 s2 = pStr2; | |
212 while (*s1 && *s2 && (th_tolower(*s1) == th_tolower(*s2))) { | |
213 s1++; | |
214 s2++; | |
215 } | |
216 | |
217 return (th_tolower(*s1) - th_tolower(*s2)); | |
218 } | |
219 | |
220 | |
221 int th_strncasecmp(char_t * pStr1, char_t * pStr2, size_t n) | |
222 { | |
223 char_t *s1, *s2; | |
224 assert(pStr1); | |
225 assert(pStr2); | |
226 | |
227 /* Check the string pointers */ | |
228 if (pStr1 == pStr2) | |
229 return 0; | |
230 | |
231 /* Go through the string */ | |
232 s1 = pStr1; | |
233 s2 = pStr2; | |
234 while ((n > 0) && *s1 && *s2 && (th_tolower(*s1) == th_tolower(*s2))) { | |
235 s1++; | |
236 s2++; | |
237 n--; | |
238 } | |
239 | |
240 if (n > 0) | |
241 return (th_tolower(*s1) - th_tolower(*s2)); | |
242 else | |
243 return 0; | |
244 } | |
245 | |
246 | |
247 /* Remove all occurences of control characters, in-place. | |
248 * Resulting string is always shorter or same length than original. | |
249 */ | |
250 void th_strip_ctrlchars(char_t * pStr) | |
251 { | |
252 char_t *i, *j; | |
253 assert(pStr); | |
254 | |
255 i = pStr; | |
256 j = pStr; | |
257 while (*i) { | |
258 if (!th_iscntrl(*i)) | |
259 *(j++) = *i; | |
260 i++; | |
261 } | |
262 | |
263 *j = 0; | |
264 } | |
265 | |
266 | |
267 /* Locate a substring [strstr] | |
268 */ | |
269 char_t *th_strstr(char_t * haystack, char_t * needle) | |
270 { | |
271 char_t *h, *n, *s; | |
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 | |
315 /* Check the string pointers */ | |
316 if (!pStr) | |
317 return -1; | |
318 | |
319 /* Allocate memory for destination */ | |
320 th_free(*ppResult); | |
321 *ppResult = th_stralloc(th_strlen(pStr) + 1); | |
322 if (!*ppResult) | |
323 return -2; | |
324 | |
325 /* Copy to the destination */ | |
326 th_strcpy(*ppResult, pStr); | |
327 | |
328 return 0; | |
329 } | |
330 | |
331 | |
332 /* Concatenates a given string into string pointed by *ppResult. | |
333 */ | |
334 int th_pstrcat(char_t ** ppResult, char_t * pStr) | |
335 { | |
336 assert(ppResult); | |
337 | |
338 /* Check the string pointers */ | |
339 if (!pStr) | |
340 return -1; | |
341 | |
342 if (*ppResult != NULL) { | |
343 *ppResult = th_strrealloc(*ppResult, th_strlen(*ppResult) + th_strlen(pStr) + 1); | |
344 if (*ppResult == NULL) | |
345 return -1; | |
346 | |
347 th_strcat(*ppResult, pStr); | |
348 } else { | |
349 *ppResult = th_stralloc(th_strlen(pStr) + 1); | |
350 if (*ppResult == NULL) | |
351 return -1; | |
352 | |
353 th_strcpy(*ppResult, pStr); | |
354 } | |
355 | |
356 return 0; | |
357 } | |
358 | |
359 | |
360 /* Find next non-whitespace character in string. | |
361 * Updates iPos into the position of such character and | |
362 * returns pointer to the string. | |
363 */ | |
364 char_t *th_findnext(char_t * pStr, size_t * iPos) | |
365 { | |
366 assert(pStr); | |
367 | |
368 /* Terminating NULL-character is not whitespace! */ | |
369 while (th_isspace(pStr[*iPos])) | |
370 (*iPos)++; | |
371 return &pStr[*iPos]; | |
372 } | |
373 | |
374 | |
375 /* Find next chSep-character from string | |
376 */ | |
377 char_t *th_findsep(char_t * pStr, size_t * iPos, char_t chSep) | |
378 { | |
379 assert(pStr); | |
380 | |
381 /* Terminating NULL-character is not digit! */ | |
382 while (pStr[*iPos] && (pStr[*iPos] != chSep)) | |
383 (*iPos)++; | |
384 return &pStr[*iPos]; | |
385 } | |
386 | |
387 | |
388 /* Find next chSep- or whitespace from string | |
389 */ | |
390 char_t *th_findseporspace(char_t * pStr, size_t * iPos, char_t chSep) | |
391 { | |
392 assert(pStr); | |
393 | |
394 /* Terminating NULL-character is not digit! */ | |
395 while (!th_isspace(pStr[*iPos]) && (pStr[*iPos] != chSep)) | |
396 (*iPos)++; | |
397 return &pStr[*iPos]; | |
398 } | |
399 | |
400 | |
401 /* Compare a string to a pattern. Case-SENSITIVE version. | |
402 * The matching pattern can consist of any normal characters plus | |
403 * wildcards ? and *. "?" matches any character and "*" matches | |
404 * any number of characters. | |
405 */ | |
406 BOOL th_strmatch(char_t * pStr, char_t * pPattern) | |
407 { | |
408 BOOL didMatch, isAnyMode, isEnd; | |
409 char_t *tmpPattern; | |
410 | |
411 /* Check given pattern and string */ | |
412 if (!pStr) | |
413 return FALSE; | |
414 if (!pPattern) | |
415 return FALSE; | |
416 | |
417 /* Initialize */ | |
418 tmpPattern = NULL; | |
419 didMatch = TRUE; | |
420 isEnd = FALSE; | |
421 isAnyMode = FALSE; | |
422 | |
423 /* Start comparision */ | |
424 do { | |
425 didMatch = FALSE; | |
426 switch (*pPattern) { | |
427 case '?': | |
428 /* Any single character matches */ | |
429 if (*pStr) { | |
430 didMatch = TRUE; | |
431 pPattern++; | |
432 pStr++; | |
433 } | |
434 break; | |
435 | |
436 case '*': | |
437 didMatch = TRUE; | |
438 pPattern++; | |
439 if (!*pPattern) | |
440 isEnd = TRUE; | |
441 isAnyMode = TRUE; | |
442 tmpPattern = pPattern; | |
443 break; | |
444 | |
445 case 0: | |
446 if (isAnyMode) { | |
447 if (*pStr) | |
448 pStr++; | |
449 else | |
450 isEnd = TRUE; | |
451 } else { | |
452 if (*pStr) { | |
453 if (tmpPattern) { | |
454 isAnyMode = TRUE; | |
455 pPattern = tmpPattern; | |
456 } else | |
457 didMatch = FALSE; | |
458 } else | |
459 isEnd = TRUE; | |
460 } | |
461 break; | |
462 default: | |
463 if (isAnyMode) { | |
464 if ((*pPattern) == (*pStr)) { | |
465 isAnyMode = FALSE; | |
466 didMatch = TRUE; | |
467 } else { | |
468 if (*pStr) { | |
469 didMatch = TRUE; | |
470 pStr++; | |
471 } | |
472 } | |
473 } else { | |
474 if ((*pPattern) == (*pStr)) { | |
475 didMatch = TRUE; | |
476 if (*pPattern) | |
477 pPattern++; | |
478 if (*pStr) | |
479 pStr++; | |
480 } else { | |
481 if (tmpPattern) { | |
482 didMatch = TRUE; | |
483 isAnyMode = TRUE; | |
484 pPattern = tmpPattern; | |
485 } | |
486 } | |
487 } | |
488 | |
489 if (!*pStr && !*pPattern) | |
490 isEnd = TRUE; | |
491 break; | |
492 | |
493 } /* switch */ | |
494 | |
495 } while ((didMatch) && (!isEnd)); | |
496 | |
497 return didMatch; | |
498 } | |
499 | |
500 | |
501 /* Compare a string to a pattern. Case-INSENSITIVE version. | |
502 */ | |
503 BOOL th_strcasematch(char_t * pStr, char_t * pPattern) | |
504 { | |
505 BOOL didMatch, isAnyMode, isEnd; | |
506 char_t *tmpPattern; | |
507 | |
508 /* Check given pattern and string */ | |
509 if (!pStr) | |
510 return FALSE; | |
511 if (!pPattern) | |
512 return FALSE; | |
513 | |
514 /* Initialize */ | |
515 tmpPattern = NULL; | |
516 didMatch = TRUE; | |
517 isEnd = FALSE; | |
518 isAnyMode = FALSE; | |
519 | |
520 /* Start comparision */ | |
521 do { | |
522 switch (*pPattern) { | |
523 case '?': | |
524 /* Any single character matches */ | |
525 if (*pStr) { | |
526 pPattern++; | |
527 pStr++; | |
528 } else | |
529 didMatch = FALSE; | |
530 break; | |
531 | |
532 case '*': | |
533 pPattern++; | |
534 if (!*pPattern || (*pPattern == '?')) | |
535 isEnd = TRUE; | |
536 isAnyMode = TRUE; | |
537 tmpPattern = pPattern; | |
538 break; | |
539 | |
540 case 0: | |
541 if (isAnyMode) { | |
542 if (*pStr) | |
543 pStr++; | |
544 else | |
545 isEnd = TRUE; | |
546 } else { | |
547 if (*pStr) { | |
548 if (tmpPattern) { | |
549 isAnyMode = TRUE; | |
550 pPattern = tmpPattern; | |
551 } else | |
552 didMatch = FALSE; | |
553 } else | |
554 isEnd = TRUE; | |
555 } | |
556 break; | |
557 | |
558 default: | |
559 if (isAnyMode) { | |
560 if (th_tolower(*pPattern) == th_tolower(*pStr)) { | |
561 isAnyMode = FALSE; | |
562 } else { | |
563 if (*pStr) | |
564 pStr++; | |
565 else | |
566 didMatch = FALSE; | |
567 } | |
568 } else { | |
569 if (th_tolower(*pPattern) == th_tolower(*pStr)) { | |
570 if (*pPattern) | |
571 pPattern++; | |
572 if (*pStr) | |
573 pStr++; | |
574 } else { | |
575 if (tmpPattern) { | |
576 isAnyMode = TRUE; | |
577 pPattern = tmpPattern; | |
578 } else | |
579 didMatch = FALSE; | |
580 } | |
581 } | |
582 | |
583 if (!*pStr && !*pPattern) | |
584 isEnd = TRUE; | |
585 break; | |
586 | |
587 } /* switch */ | |
588 | |
589 } while ((didMatch) && (!isEnd)); | |
590 | |
591 return didMatch; | |
592 } | |
593 | |
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 } |