141 lines
3.6 KiB
C++
141 lines
3.6 KiB
C++
// This may look like C code, but it is really -*- C++ -*-
|
|
|
|
// ------------------------------------------------------------------
|
|
// The Goldware Library
|
|
// Copyright (C) 1990-1999 Odinn Sorensen
|
|
// Copyright (C) 2000 Alexander S. Aganichev
|
|
// ------------------------------------------------------------------
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Library General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2 of the License, or (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Library General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Library General Public
|
|
// License along with this program; if not, write to the Free
|
|
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
// MA 02111-1307, USA
|
|
// ------------------------------------------------------------------
|
|
// $Id$
|
|
// ------------------------------------------------------------------
|
|
// Boyer-Moore-Horspool pattern match.
|
|
// ------------------------------------------------------------------
|
|
// Based on Public Domain version by Thad Smith 7/21/1992, based on a
|
|
// 7/92 public domain BMH version by Raymond Gardner.
|
|
// With fixes found by Jeff Dunlop 10/21/93.
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
#include <climits>
|
|
#include <gstrall.h>
|
|
#include <gmemdbg.h>
|
|
#include <gbmh.h>
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
gbmh::gbmh() {
|
|
|
|
pat = NULL;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
gbmh::~gbmh() {
|
|
|
|
throw_deletearray(pat);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void gbmh::init(const char* pattern, bool ignorecase) {
|
|
|
|
ignore_case = ignorecase;
|
|
patlen = strlen(pattern);
|
|
|
|
pat = new char [patlen+1];
|
|
throw_new(pat);
|
|
|
|
// Copy pattern
|
|
strcpy(pat, pattern);
|
|
if(ignore_case) {
|
|
#ifndef _MSC_VER
|
|
strupr(pat);
|
|
#else /* strupr() is wrong on windows 9x (patch from Ianos Gnatiuc 2:469/335.155) */
|
|
for(char *ptr = pat; *ptr; ptr++)
|
|
*ptr = g_toupper(*ptr);
|
|
#endif
|
|
}
|
|
|
|
// initialize skip array
|
|
int i;
|
|
for(i=0; i<256; i++)
|
|
skip[i] = patlen;
|
|
for(i=0; i<patlen; i++) {
|
|
skip[pat[i] & 0xff] = patlen - i - 1;
|
|
if(ignore_case)
|
|
skip[g_tolower((uint8_t)pat[i])] = patlen - i - 1;
|
|
}
|
|
char lastpatchar = pat[patlen - 1];
|
|
skip[lastpatchar & 0xff] = INT_MAX;
|
|
if(ignore_case)
|
|
skip[g_tolower((uint8_t)lastpatchar)] = INT_MAX;
|
|
|
|
// Horspool's fixed second shift
|
|
skip2 = patlen;
|
|
for(i=0; i<patlen-1; ++i)
|
|
if(pat[i] == lastpatchar)
|
|
skip2 = patlen - i - 1;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
bool gbmh::find(const char* buffer) {
|
|
|
|
int buflen = strlen(buffer);
|
|
|
|
int i = patlen - 1 - buflen;
|
|
if(i >= 0)
|
|
return false;
|
|
|
|
buffer += buflen;
|
|
|
|
while(1) {
|
|
|
|
while((i += skip[buffer[i] & 0xff]) < 0)
|
|
;
|
|
|
|
if(i < (INT_MAX - buflen))
|
|
return false;
|
|
|
|
i -= INT_MAX;
|
|
int j = patlen - 1;
|
|
const char* s = buffer + (i - j);
|
|
|
|
if(ignore_case) {
|
|
while(--j >= 0 and g_toupper((uint8_t)s[j]) == pat[j])
|
|
;
|
|
}
|
|
else {
|
|
while(--j >= 0 and s[j] == pat[j])
|
|
;
|
|
}
|
|
|
|
if(j < 0)
|
|
return true;
|
|
|
|
if((i += skip2) >= 0)
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|