一份开源的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 }

 

posted @ 2013-08-15 10:07  Kevin!=NULL  阅读(559)  评论(0编辑  收藏  举报