Mercurial > ~mikael > mcabber > hg
comparison mcabber/src/utils.c @ 803:8f8d8f8157a2
Take care of the strcasestr lacking (Cygwin)
author | Soren Andersen <somian@pobox.com> |
---|---|
date | Mon, 10 Apr 2006 23:30:39 +0200 |
parents | dd860da62002 |
children | a6628f0aabc1 |
comparison
equal
deleted
inserted
replaced
802:dd860da62002 | 803:8f8d8f8157a2 |
---|---|
508 | 508 |
509 return xtext; | 509 return xtext; |
510 } | 510 } |
511 | 511 |
512 | 512 |
513 /* Cygwin's newlib does not have strcasestr() */ | |
514 /* The author of the code before the endif is | |
515 * Jeffrey Stedfast <fejj@ximian.com> | |
516 * and this code is reusable in compliance with the GPL v2. -- somian */ | |
517 | |
518 #if !defined(HAVE_STRCASESTR) | |
519 | |
520 # define lowercase(c) (isupper ((int) (c)) ? tolower ((int) (c)) : (int) (c)) | |
521 # define bm_index(c, icase) ((icase) ? lowercase (c) : (int) (c)) | |
522 # define bm_equal(c1, c2, icase) ((icase) ? lowercase (c1) == lowercase (c2) : (c1) == (c2)) | |
523 | |
524 /* FIXME: this is just a guess... should really do some performace tests to get an accurate measure */ | |
525 # define bm_optimal(hlen, nlen) (((hlen) ? (hlen) > 20 : 1) && (nlen) > 10 ? 1 : 0) | |
526 | |
527 static unsigned char * | |
528 __boyer_moore (const unsigned char *haystack, size_t haystacklen, | |
529 const unsigned char *needle, size_t needlelen, int icase) | |
530 { | |
531 register unsigned char *hc_ptr, *nc_ptr; | |
532 unsigned char *he_ptr, *ne_ptr, *h_ptr; | |
533 size_t skiptable[256], n; | |
534 register int i; | |
535 | |
536 #ifdef BOYER_MOORE_CHECKS | |
537 /* we don't need to do these checks since memmem/strstr/etc do it already */ | |
538 /* if the haystack is shorter than the needle then we can't possibly match */ | |
539 if (haystacklen < needlelen) | |
540 return NULL; | |
541 | |
542 /* instant match if the pattern buffer is 0-length */ | |
543 if (needlelen == 0) | |
544 return (unsigned char *) haystack; | |
545 #endif /* BOYER_MOORE_CHECKS */ | |
546 | |
547 /* set a pointer at the end of each string */ | |
548 ne_ptr = (unsigned char *) needle + needlelen - 1; | |
549 he_ptr = (unsigned char *) haystack + haystacklen - 1; | |
550 | |
551 /* create our skip table */ | |
552 for (i = 0; i < 256; i++) | |
553 skiptable[i] = needlelen; | |
554 for (nc_ptr = (unsigned char *) needle; nc_ptr < ne_ptr; nc_ptr++) | |
555 skiptable[bm_index (*nc_ptr, icase)] = (size_t) (ne_ptr - nc_ptr); | |
556 | |
557 h_ptr = (unsigned char *) haystack; | |
558 while (haystacklen >= needlelen) { | |
559 hc_ptr = h_ptr + needlelen - 1; /* set the haystack compare pointer */ | |
560 nc_ptr = ne_ptr; /* set the needle compare pointer */ | |
561 | |
562 /* work our way backwards till they don't match */ | |
563 for (i = 0; nc_ptr > (unsigned char *) needle; nc_ptr--, hc_ptr--, i++) | |
564 if (!bm_equal (*nc_ptr, *hc_ptr, icase)) | |
565 break; | |
566 | |
567 if (!bm_equal (*nc_ptr, *hc_ptr, icase)) { | |
568 n = skiptable[bm_index (*hc_ptr, icase)]; | |
569 if (n == needlelen && i) | |
570 if (bm_equal (*ne_ptr, ((unsigned char *) needle)[0], icase)) | |
571 n--; | |
572 h_ptr += n; | |
573 haystacklen -= n; | |
574 } else | |
575 return (unsigned char *) h_ptr; | |
576 } | |
577 | |
578 return NULL; | |
579 } | |
580 | |
581 /* | |
582 * strcasestr: | |
583 * @haystack: string to search | |
584 * @needle: substring to search for | |
585 * | |
586 * Finds the first occurence of the substring @needle within the | |
587 * string @haystack ignoring case. | |
588 * | |
589 * Returns a pointer to the beginning of the substring match within | |
590 * @haystack, or NULL if the substring is not found. | |
591 **/ | |
592 char * | |
593 strcasestr (const char *haystack, const char *needle) | |
594 { | |
595 register unsigned char *h, *n, *hc, *nc; | |
596 size_t needlelen; | |
597 | |
598 needlelen = strlen (needle); | |
599 | |
600 if (needlelen == 0) { | |
601 return (char *) haystack; | |
602 } else if (bm_optimal (0, needlelen)) { | |
603 return (char *) __boyer_moore ((const unsigned char *) haystack, | |
604 strlen (haystack), | |
605 (const unsigned char *) needle, | |
606 needlelen, 1); | |
607 } | |
608 | |
609 h = (unsigned char *) haystack; | |
610 n = (unsigned char *) needle; | |
611 | |
612 while (*(h + needlelen - 1)) { | |
613 if (lowercase (*h) == lowercase (*n)) { | |
614 for (hc = h + 1, nc = n + 1; *hc && *nc; hc++, nc++) | |
615 if (lowercase (*hc) != lowercase (*nc)) | |
616 break; | |
617 | |
618 if (!*nc) | |
619 return (char *) h; | |
620 } | |
621 h++; | |
622 } | |
623 return NULL; | |
624 } | |
625 #endif /* !HAVE_STRCASESTR */ | |
626 | |
513 /* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */ | 627 /* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */ |