| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- //
- // assembly: System
- // namespace: System.Text.RegularExpressions
- // file: quicksearch.cs
- //
- // Authors: Dan Lewis ([email protected])
- // Juraj Skripsky ([email protected])
- //
- // (c) 2002 Dan Lewis
- // (c) 2003 Juraj Skripsky
- //
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- using System;
- using System.Collections;
- namespace System.Text.RegularExpressions {
- internal class QuickSearch {
- // simplified boyer-moore for fast substring matching
- // (for short strings, we use simple scans)
- public QuickSearch (string str, bool ignore)
- : this(str, ignore, false)
- {
- }
-
- public QuickSearch (string str, bool ignore, bool reverse) {
- this.str = str;
- this.len = str.Length;
- this.ignore = ignore;
- this.reverse = reverse;
- if (ignore)
- str = str.ToLower ();
- // create the shift table only for "long" search strings
- if(len > THRESHOLD)
- SetupShiftTable ();
- }
-
- public string String {
- get { return str; }
- }
- public int Length {
- get { return len; }
- }
- public bool IgnoreCase {
- get { return ignore; }
- }
- public int Search (string text, int start, int end) {
- int ptr = start;
-
- if ( reverse )
- {
- if (start < end)
- return -1;
- if ( ptr > text.Length)
- {
- ptr = text.Length;
- }
- // use simple scan for a single-character search string
- if (len == 1)
- {
- while (--ptr >= end)
- {
- if(str[0] == GetChar(text[ptr]))
- return ptr ;
-
- }
- return -1;
- }
-
- if ( end < len)
- end = len - 1 ;
- ptr--;
- while (ptr >= end)
- {
- int i = len -1 ;
- while (str[i] == GetChar(text[ptr - len +1 + i]))
- {
- if (-- i < 0)
- return ptr - len + 1;
- }
- if (ptr > end)
- {
- ptr -= GetShiftDistance (text[ptr - len ]);
-
- }
- else
- break;
- }
- }
- else
- {
- // use simple scan for a single-character search string
- if (len == 1)
- {
- while (ptr <= end)
- {
- if(str[0] == GetChar(text[ptr]))
- return ptr;
- else
- ptr++;
- }
- return -1;
- }
- if (end > text.Length - len)
- end = text.Length - len;
- while (ptr <= end)
- {
- int i = len - 1;
- while (str[i] == GetChar(text[ptr + i]))
- {
- if (-- i < 0)
- return ptr;
- }
- if (ptr < end)
- ptr += GetShiftDistance (text[ptr + len]);
- else
- break;
- }
- }
- return -1;
-
- }
- // private
- private void SetupShiftTable () {
- shift = new Hashtable ();
- if (reverse)
- {
- for (int i = len ; i > 0; -- i)
- {
- char c = str[i -1];
- shift[GetChar(c)] = i;
- }
- }
- else
- {
- for (int i = 0; i < len; ++ i)
- {
- char c = str[i];
- shift[GetChar(c)] = len - i;
- }
- }
-
- }
-
- private int GetShiftDistance (char c) {
- if(shift == null)
- return 1;
- object s = shift[c];
- return (s != null ? (int)s : len + 1);
- }
- private char GetChar(char c) {
- return (!ignore ? c : Char.ToLower(c));
- }
-
- private string str;
- private int len;
- private bool ignore;
- private bool reverse;
- private Hashtable shift;
- private readonly static int THRESHOLD = 5;
- }
- }
|