mcabber/src/utils.c
changeset 803 8f8d8f8157a2
parent 802 dd860da62002
child 816 a6628f0aabc1
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... */