Newer
Older
ubixfs-2 / bSearch.pas
@flameshadow flameshadow on 10 Jun 2005 5 KB UbixFS
program bSearch;
uses lists, dos, strings, debug, math, zentimer;

function lu06(val: Longint): String;
var
  i: Longint;
  s: String;
begin
  Str(val:6,s);
  for i := 1 to 6 do
    if s[i] = ' ' then s[i]:= '0';
  lu06 := s;
end;

procedure ReportTime(count: Longint);
var
  secs: Longint;
begin
  secs := count div 1000000;
  count := count - secs * 1000000;
  Writeln(secs, '.', lu06(count), ' seconds');
end;

type 
  PBTreeArrayPtr = ^PBTreeArray;
  PBTreeArray = array[0..0] of PBTree;

procedure sortTrees(var trees:PBTreeArrayPtr; treeCount:integer);
var
  i, j:integer;
  tmpTree:PBTree;  
begin
  if (trees = NIL) then exit;
  for i := 1 to treeCount-1 do
    for j := 0 to i do
      if (trees^[i]^.getKeyCount < trees^[j]^.getKeyCount) then
        begin
          tmpTree := trees^[j];
          trees^[j] := trees^[i];
          trees^[i] := tmpTree;
        end; 
end; // sortTrees

procedure usage;
begin
  writeln('bSearch usage:');
  writeln;
  writeln('bSearch term1 [term2] [term3] [...]');
  halt;
end;

procedure writeHTMLHeader(var f:text);
var curTerm:integer;
begin
  writeln(f, '<HTML><HEAD>');
  write(f, '<TITLE>Searching for ');
  for curTerm := 1 to paramcount do
    write(f, '``', paramstr(curTerm), ''''' ');
  writeln(f);
  writeln(f, '</TITLE></HEAD>');
  writeln(f, '<BODY>');
end; // writeHTMLHeader

function convertFileName(const filename:string):string;
var 
  s:string;
  i:integer;
begin
  s := 'file:///' + filename;
  for i:=1 to length(s) do
    if s[i] = '\' then s[i] := '/';
  result := s;
end; // convertFileName

var 
  masterBTI:PbTree;
  fileNameDAT:file;
  treeInfo: BTreeSearchRec;  
  filename:string;
  numFound:integer;
  curTerm : integer;
  termsFound:integer;
  wordBTI:PBTreeArrayPtr;
  term:string;
  u:uPtr;
  outputTXTFile:text;
  outputHTMLFile:text;
  found:boolean;

begin
  if (paramcount = 0) then usage;
  LZTimerOn;

  new(masterBTI, init('indicies\master.bti', 1024, BT_STRING, NIL));
  writeln('masterBTI has ', masterBTI^.getKeyCount(), ' keys');
  assign(fileNameDAT, 'indicies\fileName.dat');
  {$I-} reset(fileNameDAT); {$I+}
  if (IOResult <> 0) then 
    begin
      writeln('Could not open fileName.dat');
      halt
    end;
  GetMem(wordBTI, paramcount * sizeof(PBTree));
  for curTerm := 1 to paramcount do
    wordBTI^[curTerm] := NIL;

  assign(outputTXTFile, 'find.txt');
  rewrite(outputTXTFile);
  assign(outputHTMLFile, 'find.html');
  rewrite(outputHTMLFile);

  termsFound := 0;
  for curTerm := 1 to paramcount do
    begin 
      numFound := 0;
      term := lowercase(paramstr(curTerm)); 
      if (masterBTI^.Find(@term, u)) then 
        begin
          new(wordBTI^[termsFound], open('indicies\'+hex(u.u)+'.bti', NIL));
          inc(termsFound);
        end;
    end; // for curTerm

  if (termsFound = paramcount) then
    begin
      // write out the HTML header
      writeHTMLHeader(outputHTMLFile);

      // sort the trees into ascending order by keyCount
      sortTrees(wordBTI, termsFound);  
  
      // Now that the trees are ordered, scan through the first tree looking
      // for matches in all other trees
      if (wordBTI^[0]^.getFirstKey(treeInfo)) then
        repeat
          found := TRUE;
          curTerm := 1;
          while (found) and (curTerm < paramCount) do
            begin
              found := wordBTI^[curTerm]^.Find(treeInfo.key, u);
              inc(curTerm)
            end; // while

          if (found) then 
            begin
              seek(fileNameDAT, int32(treeInfo.key^));
              blockread(fileNameDAT, filename, 1);
              blockread(fileNameDAT, filename[1], length(filename));
              if (fsearch(filename, '') <> '') then 
                begin
                  writeln(outputTXTFile, filename);
                  writeln(outputHTMLFile, '<a href="', convertFileName(filename), '">', filename, '</a><br>');
                end;
              inc(numFound);
            end; // if found
        until not wordBTI^[0]^.findNext(treeInfo);

      write('Found ');
      for curTerm := 1 to paramcount do
        write('``', paramstr(curTerm), ''''' ');
      write('in ', numFound);
      if (numFound = 1) then writeln(' file') else writeln(' files');
      
      writeln(outputHTMLFile, '</BODY></HTML>');
    end
  else
    begin
      writeHTMLHeader(outputHTMLFile);
      writeln(outputHTMLFile, 'No files found contained your term(s)');
      writeln(outputHTMLFile, '</BODY></HTML>');
      writeln('Did not find any files containing the terms:');
      for curTerm := 1 to paramcount do
        write('``', paramstr(curTerm), ''''' ');
      writeln;
    end;
  // delete the trees (note that termsFound might be 0, which means it won't execute the for loop)
  for curTerm := 0 to termsFound-1 do   
    if (wordBTI^[curTerm]) <> NIL then dispose(wordBTI^[curTerm], done);
  FreeMem(wordBTI, paramcount * sizeof(PBTree));
  close(outputHTMLFile);
  close(outputTXTFile);
  dispose(masterBTI, done);
  close(fileNameDAT);

  LZTimerOff;
  write('Search took ');
  reportTime(LZTimerCount);
end.