strsrch.cpp

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 132 行

CPP
132
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/



#include "variety.h"
#include <string.h>
#include "strsrch.def"

#define NOT_FOUND (-1)


extern "C" long StringSearch
    ( const char *  str
    , unsigned int  strlen
    , const char *  pattern
    , unsigned int  patlen )
/**************************/
{

// If the pattern is of length 0, return 0:

    if( patlen == 0 ) {
        return( 0 );
    }

// If the pattern is longer than the string, indicate NOT_FOUND:

    if( patlen > strlen ) {
        return( NOT_FOUND );
    }

// If the pattern is of length 1, use memchr:

    if( patlen == 1 ) {
        const char *  loc;

        loc = (const char *)memchr( str, *pattern, strlen );
        return( loc == NULL ? NOT_FOUND : loc - str );
    }

// Use the Boyer-Moore algorithm:

    {
        auto unsigned char  SkipTable[256];
             unsigned int   extra_patlen;   // pattern size > 255
             unsigned int   str_index;
             unsigned int   pat_index;
             unsigned int   skip;

// First, construct the SkipTable. For each character found in the pattern,
// the corresponding SkipTable entry contains the offset from the last
// character in the pattern of the LAST occurrence of that character
// in the pattern. For characters that do not occur in the pattern,
// the SkipTable entry contains the length of the pattern.

        if( patlen > 255 ) {
            extra_patlen = patlen - 255;
            patlen       = 255;
        } else {
            extra_patlen = 0;
        }
        memset( SkipTable, patlen, 256 );
        for( pat_index = 0; pat_index < patlen; ++pat_index ) {
            int c;

            c = (unsigned char) pattern[pat_index];
            SkipTable[c] = (unsigned char)(patlen - pat_index - 1);
        }

// Now, search for the string. Each comparison of "str" to "pattern" proceeds
// from right-to-left. When a mismatch occurs, the mismatched character is
// used to extract from SkipTable the amount to skip before attempting
// another match. If extra_patlen > 0, we use memcmp to compare the rest
// of the pattern.

        str_index = patlen;
        pat_index = patlen;
        for( ;; ) {
            if( pat_index == 0 ) {              // possible match?
                if( extra_patlen == 0 ) break;  // yes!
                if( memcmp( str + str_index + patlen,
                            pattern + patlen,
                            extra_patlen ) == 0 ) break;
                str_index += patlen + 1;       // advance only 1 char
                pat_index  = patlen;
            }
            --pat_index;
            --str_index;
            while( str[str_index] != pattern[pat_index] ) {
                skip       = SkipTable[str[str_index]];
                str_index += (patlen - pat_index > skip)
                                     ? (patlen - pat_index)
                                     : skip;
                if( str_index >= strlen - extra_patlen ) {
                    return( NOT_FOUND );
                }
                pat_index = patlen - 1;
            }
        }
        return( str_index );
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?