一份开源的BM算法
mstring.h
1 /* 2 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com> 3 ** 4 ** This program is free software; you can redistribute it and/or modify 5 ** it under the terms of the GNU General Public License as published by 6 ** the Free Software Foundation; either version 2 of the License, or 7 ** (at your option) any later version. 8 ** 9 ** This program is distributed in the hope that it will be useful, 10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 ** GNU General Public License for more details. 13 ** 14 ** You should have received a copy of the GNU General Public License 15 ** along with this program; if not, write to the Free Software 16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 */ 18 19 /* $Id: mstring.h,v 1.5 2003/10/20 15:03:20 chrisgreen Exp $ */ 20 21 #ifndef __MSTRING_H__ 22 #define __MSTRING_H__ 23 24 /* I N C L U D E S ******************************************************/ 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <ctype.h> 29 30 31 32 33 /* P R O T O T Y P E S *************************************************/ 34 class BMSearch 35 { 36 public: 37 BMSearch() 38 { 39 skip = NULL; 40 shift = NULL; 41 } 42 ~BMSearch(); 43 int Match(const char* pBuf, int nBufLen, const char* ptrn, int nLen, bool bOneTimeFlag); 44 private: 45 int mSearch(const char *buf, int blen, const char *ptrn, int plen, int *skip, int *shift, bool bOneTimeFlag); 46 int *make_skip(const char *ptrn, int plen); 47 int *make_shift(const char *ptrn, int plen); 48 49 int* skip; 50 int* shift; 51 52 }; 53 54 55 #endif /* __MSTRING_H__ */
mstring.cpp
1 #include <stdafx.h> 2 #include "mstring.h" 3 BMSearch::~BMSearch() 4 { 5 if (skip) 6 { 7 free(skip); 8 skip = NULL; 9 } 10 if (shift) 11 { 12 free(shift); 13 shift = NULL; 14 } 15 } 16 int BMSearch::Match(const char* pBuf, int nBufLen, const char* ptrn, int nLen, bool bOneTimeFlag) 17 { 18 if (skip) 19 { 20 free(skip); 21 skip = NULL; 22 } 23 if (shift) 24 { 25 free(shift); 26 shift = NULL; 27 } 28 29 if (NULL == pBuf || 30 NULL == ptrn || 31 nBufLen <=0 || 32 nLen <= 0 33 ) 34 { 35 return 0; 36 } 37 38 skip = make_skip(ptrn, nLen); 39 shift = make_shift(ptrn, nLen); 40 41 if (NULL == skip || NULL == shift) 42 return 0; 43 44 return mSearch(pBuf, nBufLen, ptrn, nLen, skip, shift, bOneTimeFlag); 45 46 47 } 48 /**************************************************************** 49 * 50 * Function: make_skip(char *, int) 51 * 52 * Purpose: Create a Boyer-Moore skip table for a given pattern 53 * 54 * Parameters: 55 * ptrn => pattern 56 * plen => length of the data in the pattern buffer 57 * 58 * Returns: 59 * int * - the skip table 60 * 61 ****************************************************************/ 62 int * BMSearch::make_skip(const char *ptrn, int plen) 63 { 64 int *skip = (int *) malloc(256 * sizeof(int)); 65 int *sptr = &skip[256]; 66 67 if (skip == NULL) 68 return NULL; 69 70 while(sptr-- != skip) 71 *sptr = plen + 1; 72 73 while(plen != 0) 74 skip[(unsigned char) *ptrn++] = plen--; 75 76 return skip; 77 } 78 79 80 81 /**************************************************************** 82 * 83 * Function: make_shift(char *, int) 84 * 85 * Purpose: Create a Boyer-Moore shift table for a given pattern 86 * 87 * Parameters: 88 * ptrn => pattern 89 * plen => length of the data in the pattern buffer 90 * 91 * Returns: 92 * int * - the shift table 93 * 94 ****************************************************************/ 95 int *BMSearch::make_shift(const char *ptrn, int plen) 96 { 97 int *shift = (int *) malloc(plen * sizeof(int)); 98 int *sptr = shift + plen - 1; 99 const char *pptr = ptrn + plen - 1; 100 char c; 101 102 if (shift == NULL) 103 return NULL; 104 105 c = ptrn[plen - 1]; 106 107 *sptr = 1; 108 109 while(sptr-- != shift) 110 { 111 const char *p1 = ptrn + plen - 2, *p2, *p3; 112 113 do 114 { 115 while(p1 >= ptrn && *p1-- != c); 116 117 p2 = ptrn + plen - 2; 118 p3 = p1; 119 120 while(p3 >= ptrn && *p3-- == *p2-- && p2 >= pptr); 121 } 122 while(p3 >= ptrn && p2 >= pptr); 123 124 *sptr = static_cast<int>(shift + plen - sptr + p2 - p3); 125 126 pptr--; 127 } 128 129 return shift; 130 } 131 132 133 134 /**************************************************************** 135 * 136 * Function: mSearch(char *, int, char *, int) 137 * 138 * Purpose: Determines if a string contains a (non-regex) 139 * substring. 140 * 141 * Parameters: 142 * buf => data buffer we want to find the data in 143 * blen => data buffer length 144 * ptrn => pattern to find 145 * plen => length of the data in the pattern buffer 146 * skip => the B-M skip array 147 * shift => the B-M shift array 148 * 149 * Returns: 150 * Integer value, 1 on success (str constains substr), 0 on 151 * failure (substr not in str) 152 * 153 ****************************************************************/ 154 int BMSearch::mSearch(const char *buf, int blen, const char *ptrn, int plen, int *skip, int *shift, bool bOneTimeFlag) 155 { 156 int b_idx = plen; 157 int nCount = 0; 158 bool bContinue = false; 159 160 if(0 == blen || 0 == plen) 161 return 1; 162 163 while(b_idx <= blen) 164 { 165 int p_idx = plen, skip_stride, shift_stride; 166 167 while(buf[--b_idx] == ptrn[--p_idx]) 168 { 169 if(b_idx < 0) 170 return 0; 171 172 if(p_idx == 0) 173 { 174 if (bOneTimeFlag) 175 return 1; 176 else 177 { 178 nCount++; 179 bContinue = true; 180 break; 181 } 182 } 183 } 184 185 if (bContinue) 186 { 187 b_idx += 2*plen; 188 bContinue = false; 189 } 190 else 191 { 192 skip_stride = skip[(unsigned char) buf[b_idx]]; 193 shift_stride = shift[p_idx]; 194 195 b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride; 196 } 197 } 198 199 return nCount; 200 }