home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / ECO30603.ZIP / ECO30603.LZH / ECOLIBII / ECO_SRCH.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-06-21  |  10.5 KB  |  266 lines

  1. (*
  2.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  3.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  4.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  5.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  6.     ▓▓▓▓▓▓▓▓·──                                              ──·▓▓▓▓▓▓▓▓▓▓▓
  7.     ▓▓▓▓▓▓▓▓│                                                  │░░▓▓▓▓▓▓▓▓▓
  8.     ▓▓▓▓▓▓▓▓   Unit was conceived, designed and written         ░░▓▓▓▓▓▓▓▓▓
  9.     ▓▓▓▓▓▓▓▓   by Floor A.C. Naaijkens for                      ░░▓▓▓▓▓▓▓▓▓
  10.     ▓▓▓▓▓▓▓▓   UltiHouse Software / The ECO Group.              ░░▓▓▓▓▓▓▓▓▓
  11.     ▓▓▓▓▓▓▓▓                                                    ░░▓▓▓▓▓▓▓▓▓
  12.     ▓▓▓▓▓▓▓▓   (C) MCMXCII by EUROCON PANATIONAL CORPORATION.   ░░▓▓▓▓▓▓▓▓▓
  13.     ▓▓▓▓▓▓▓▓   All Rights Reserved for The ECO Group.           ░░▓▓▓▓▓▓▓▓▓
  14.     ▓▓▓▓▓▓▓▓                                                    ░░▓▓▓▓▓▓▓▓▓
  15.     ▓▓▓▓▓▓▓▓│                                                  │░░▓▓▓▓▓▓▓▓▓
  16.     ▓▓▓▓▓▓▓▓·──                                              ──·░░▓▓▓▓▓▓▓▓▓
  17.     ▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓▓▓▓
  18.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  19.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  20.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  21. *)
  22. {$A-,B-,D+,E-,F-,I-,L-,N-,O+,R-,S-,V-}
  23. {$M 65520,0,655350}
  24. unit eco_srch;
  25. interface
  26.  
  27. const
  28.   maxbuffer = 32768;
  29.  
  30. var
  31.   maxpos :                        word;
  32.   buffer : array[1..maxbuffer] of byte;
  33.   target :                      string;
  34.   table1 :         array[char] of byte;
  35.   table2 :                      string;
  36.   ch     :                        char;
  37.  
  38.  
  39. procedure make_boyer_moore_table(
  40.   var target : string;
  41.   var table1;
  42.   var table2;
  43.   casesensitive : boolean
  44. );
  45.  
  46. function boyer_moore_search(
  47.   var text_array; start,
  48.   text_length: word; var target: string; var table1;
  49.   var table2; casesensitive: boolean
  50. ): word;
  51.  
  52.  
  53.  
  54.  
  55. implementation
  56.  
  57.  
  58.  
  59. uses
  60.   crt;
  61.  
  62.  
  63.  
  64.  
  65.   procedure make_boyer_moore_table;
  66.   var
  67.     l_target :              string absolute target;
  68.     l_table1 : array[char] of byte absolute table1;
  69.     l_table2 :              string absolute table2;
  70.     reverse  :                              string;
  71.     i,j,k    :                             integer;
  72.     ch       :                                char;
  73.  
  74.   begin { make_boyer_moore_table }
  75.  
  76.     {-------------------------------------------------------}
  77.     { creation of the first table, it contains values for   }
  78.     { every caracter in the ascii table. all caracters not  }
  79.     { contained in the search string are given the largest  }
  80.     { possible value.                                       }
  81.     {-------------------------------------------------------}
  82.  
  83.     {-------------------------------------------------------}
  84.     { first set target to all uppercase if search is not to }
  85.     { be sensitive                                          }
  86.     {-------------------------------------------------------}
  87.     if not casesensitive then for i := 1 to length(l_target) do
  88.       l_target[i] := upcase(l_target[i]);
  89.  
  90.     {--------------------------------------------------------}
  91.     { initialize the table to the largest skip value ie:     }
  92.     {             length(target)                             }
  93.     {--------------------------------------------------------}
  94.  
  95.     fillchar(l_table1, sizeof(l_table1), target[0]);
  96.  
  97.     {--------------------------------------------------------}
  98.     { replace values for caracters contained in target with  }
  99.     { their distance from the right. except for the last     }
  100.     { caracter!!!                                            }
  101.     {--------------------------------------------------------}
  102.  
  103.     for i := 1 to ord(target[0])-1 do begin
  104.       l_table1[target[i]] := ord(target[0])-i;
  105.     end;
  106.  
  107.     {--------------------------------------------------------}
  108.     { in case of a case insensitive search, the distance     }
  109.     { should be the same for a caracter be-it upper-case or  }
  110.     { lower-case. the distance is allways the right-most     }
  111.     { occurance of the caracter                              }
  112.     {--------------------------------------------------------}
  113.  
  114.     if not casesensitive then begin
  115.       for ch := 'a' to 'z' do begin
  116.         if l_table1[ch] < l_table1[upcase(ch)] then begin
  117.           l_table1[upcase(ch)] := l_table1[ch];
  118.         end else begin
  119.           l_table1[ch] := l_table1[upcase(ch)];
  120.         end;
  121.       end;
  122.     end;
  123.  
  124.     {--------------------------------------------------------}
  125.     { creation of the second table, it contains values for   }
  126.     { each position in the search string. essentially, each  }
  127.     { value is the distance the distance to move left before }
  128.     { a match can be found with the right right-sub-string   }
  129.     { can be found again. the right sub-string starts with   }
  130.     { the caracter immediately to the right of the current   }
  131.     { position in the search string.                         }
  132.     {                                                        }
  133.     {   example: abcabcde                                    }
  134.     {                                                        }
  135.     { if a miss occurs on the "E" and we are at position 10  }
  136.     { in the text then we can move only one caracter to the  }
  137.     { right since all we know is that the caracter at        }
  138.     { position 10 is not an "E".                             }
  139.     {                                                        }
  140.     { if the miss occurs on the "D" then we can move 8       }
  141.     { positions to the right since we now know that the "E"  }
  142.     { matched but there are no more "E"'s in the search      }
  143.     { string. all positions to the left of "D" would also    }
  144.     { generate a move of 8 positions since the substring     }
  145.     { "DE" does not repeat either nor does "CDE" then "BCDE" }
  146.     { etc... since any string in this case is a superset of  }
  147.     { it's right substrings                                  }
  148.     {                                                        }
  149.     { if the search string had been:                         }
  150.     {                                                        }
  151.     {     kfgabcabc                                          }
  152.     {                                                        }
  153.     { then a miss on the first "C" from the left would       }
  154.     { generate a move of only three since we would then know }
  155.     { that the text matched "ABC" and what miss-matched with }
  156.     { the first "C" might be a "G".    both values are used  }
  157.     { when a miss occurs, the greatest of the two values is  }
  158.     { then used to move the search string forward            }
  159.     {--------------------------------------------------------}
  160.  
  161.  
  162.     {--------------------------------------------------------}
  163.     { since we want the right-most position of the           }
  164.     { sub-string, set a new string that is a reverse of the  }
  165.     { original.                                              }
  166.     {--------------------------------------------------------}
  167.  
  168.     l_table2 := target;
  169.     reverse := target;
  170.  
  171.     {--------------------------------------------------------}
  172.     { now reverse l_table2 into reverse                      }
  173.     {--------------------------------------------------------}
  174.     for i := 0 to length(target) -1 do
  175.       if casesensitive then reverse[i+1] := target[ length(target) - i] else
  176.         reverse[i+1] := upcase(target[ length(target) -i]);
  177.  
  178.     {--------------------------------------------------------}
  179.     { now compute sub-string positions, as soon as we get a  }
  180.     { max-length for any sub-string, all subsequent          }
  181.     { sub-string are also max-length                         }
  182.     {--------------------------------------------------------}
  183.  
  184.     for i := length(target)-1 downto 1 do begin
  185.       if pos(copy(reverse, 1, length(target)-i), copy(reverse,2,300))>0 then
  186.         l_table2[i] := chr(pos(copy(reverse, 1, length(target)-i),
  187.           copy(reverse,2,300))
  188.         ) else l_table2[i] := chr(length(target));
  189.     end;
  190.  
  191.     {--------------------------------------------------------}
  192.     { last position is allways a move of at most 1 position  }
  193.     {--------------------------------------------------------}
  194.  
  195.     l_table2[length(target)] := chr(1);
  196.  
  197.   end; { make_boyer_moore_table }
  198.  
  199.  
  200.  
  201.   function boyer_moore_search;
  202.   var
  203.     l_text_array : array[1..maxbuffer] of char absolute text_array;
  204.     i,j, offset  :                                            word;
  205.     match, found :                                         boolean;
  206.     distance,
  207.     distance1,
  208.     distance2    :                                            byte;
  209.     l_table1     :             array[char] of byte absolute table1;
  210.     l_table2     : record
  211.       dummy      : byte;
  212.       distance   : array[1..255] of byte;
  213.     end absolute table2;
  214.  
  215.   begin { boyer_moore_search }
  216.     i := start; found := false; offset := 0; distance := 0;
  217.     j := length(target);
  218.     while ((i+distance) < text_length-length(target)) and not found do begin
  219.       inc(i, distance-(length(target)-j));
  220.       j := length(target); match := true;
  221.       while (j > 0) and match do begin
  222.         if not casesensitive then match :=
  223.           (target[j] = upcase(l_text_array[i+j])) else
  224.           match := (target[j] = l_text_array[i+j]);
  225.         if match then dec(j);
  226.       end;
  227.       found := match;
  228.       if not found then begin
  229.         distance1 := l_table1[l_text_array[i+j]];
  230.         distance2 := l_table2.distance[j];
  231.       end;
  232.       if distance1 < distance2 then distance := distance2 else
  233.         distance := distance1;
  234.     end;
  235.     boyer_moore_search := ord(found) * (i);
  236.   end; { boyer_moore_search }
  237.  
  238.  
  239.  
  240. {happy}end. { unit }
  241.  
  242.  
  243. {
  244.  
  245. msg # 1700
  246. date: 22 dec 91 21:55:00
  247. from: mark ouellet
  248.   to: rich veraa
  249. subj: boyer-moore search (1/4)
  250. ____________________________________________________________________________
  251.  
  252. area:pascal
  253. eid:534f 1796af2c 4d453220
  254.  here is part one, to be saved in boyermko.pas
  255.  
  256.  boyermko.pas (22 december 1991) (mark ouellet)
  257.  
  258.     this unit provides facilities for searching a text for
  259.      a target using the boyer-moore search method.
  260.  
  261.   only peculiarity, the second skip structure is actually a
  262.   string, this made sens since the second table has a 1:1
  263.   ratio with the target length
  264. }
  265.  
  266.