| iMatix home page
| << | < | > | >>
SFL Logo SFL
Version 2.11

 

txtfind

#include "sflfind.h"
char *
txtfind (const char *string,            /*  String containing data           */
         const char *pattern)           /*  Pattern to search for            */

Synopsis

Searches for a case-insensitive text pattern in a string using the Boyer-Moore-Horspool-Sunday algorithm. The string and pattern are null-terminated strings. Returns a pointer to the pattern if found within the string, or NULL if the pattern was not found. Will match strings irrespective of case. To match exact strings, use strfind(). Will not work on multibyte characters.

Examples

    char *result;

    result = txtfind ("AbracaDabra", "cad");
    if (result)
        puts (result);

Source Code - (sflfind.c)

{
    size_t
        shift [256];                    /*  Shift distance for each value    */
    size_t
        string_size,
        pattern_size,
        byte_nbr,                       /*  Index into byte array            */
        match_size;                     /*  Size of matched part             */
    const char
        *match_base = NULL,             /*  Base of match of pattern         */
        *match_ptr  = NULL,             /*  Point within current match       */
        *limit      = NULL;             /*  Last potiental match point       */

    ASSERT (string);                    /*  Expect non-NULL pointers, but    */
    ASSERT (pattern);                   /*  fail gracefully if not debugging */
    if (string == NULL || pattern == NULL)
        return (NULL);

    string_size  = strlen (string);
    pattern_size = strlen (pattern);

    /*  Pattern must be smaller or equal in size to string                   */
    if (string_size < pattern_size)
        return (NULL);                  /*  Otherwise it cannot be found     */

    if (pattern_size == 0)              /*  Empty string matches at start    */
        return (char *) string;

    /*  Build the shift table                                                */

    /*  The shift table determines how far to shift before trying to match   */
    /*  again, if a match at this point fails.  If the byte after where the  */
    /*  end of our pattern falls is not in our pattern, then we start to     */
    /*  match again after that byte; otherwise we line up the last occurence */
    /*  of that byte in our pattern under that byte, and try match again.    */

    for (byte_nbr = 0; byte_nbr < 256; byte_nbr++)
        shift [byte_nbr] = pattern_size + 1;

    for (byte_nbr = 0; byte_nbr < pattern_size; byte_nbr++)
        shift [(byte) tolower (pattern [byte_nbr])] = pattern_size - byte_nbr;

    /*  Search for the string.  If we don't find a match, move up by the     */
    /*  amount we computed in the shift table above, to find location of     */
    /*  the next potiental match.                                            */

    limit = string + (string_size - pattern_size + 1);
    ASSERT (limit > string);

    for (match_base = string;
         match_base < limit;
         match_base += shift [(byte) tolower (*(match_base + pattern_size))])
      {
        match_ptr  = match_base;
        match_size = 0;

        /*  Compare pattern until it all matches, or we find a difference    */
        while (tolower (*match_ptr++) == tolower (pattern [match_size++]))
          {
            ASSERT (match_size <= pattern_size &&
                    match_ptr == (match_base + match_size));

            /*  If we found a match, return the start address                */
            if (match_size >= pattern_size)
                return ((char *)(match_base));
          }
      }
    return (NULL);                      /*  Found nothing                    */
}

| << | < | > | >> iMatix Copyright © 1996-2000 iMatix Corporation