1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
//
// AndQuery.cc
//
// AndQuery: an operator query that does 'and' combination
//
// Part of the ht://Dig package <https://htdig.sourceforge.net/>
// Copyright (c) 1995-2004 The ht://Dig Group
// For copyright details, see the file COPYING in your distribution
// or the GNU Library General Public License (LGPL) version 2 or later
// <http://www.gnu.org/copyleft/lgpl.html>
//
// $Id: AndQuery.cc,v 1.4 2004/05/28 13:15:24 lha Exp $
//
#include "AndQuery.h"
//
// l r and
// ----------------------
// 0 0 0
// 0 b 0
// 0 x 0
// a 0 0
// a b intersect(a,b)
// a x a
// x 0 0
// x b b
// x x x
//
// i.e. some 0 => 0
// ignores can be left out of intersection
// the shorter of the result lists is put apart for intersection
// this optimises the intersection process
//
ResultList *
AndQuery::Evaluate()
{
ResultList *result = 0;
ResultList *shorter = 0;
operands.Start_Get();
Query *operand = (Query *) operands.Get_Next();
while(operand && !shorter)
{
result = operand->GetResults();
if(!result)
{
break;
}
if(!result->IsIgnore())
{
shorter = result;
}
operand = (Query *) operands.Get_Next();
}
if(shorter)
{
List longer;
while(operand && result)
{
result = operand->GetResults();
if(result && !result->IsIgnore())
{
if(result->Count() < shorter->Count())
{
longer.Add(shorter);
shorter = result;
}
else
{
longer.Add(result);
}
}
operand = (Query *) operands.Get_Next();
}
if(longer.Count())
{
result = Intersection(*shorter, longer);
longer.Release();
}
else
{
result = new ResultList(*shorter);
}
}
return result;
}
//
// return a result list containing only the matches common to
// all input parameters.
//
// l is iterated, matches from l are searched in all elements of rs
//
//
// foreach match in shorter
// confirm the match in each lists
// if confirmed
// copy all matches in result
//
// the shorter of the input lists is assumed to be in the first parameter
// this is a modest optimisation in order to minimise iteration
//
ResultList *
AndQuery::Intersection(const ResultList &shorter, const List &lists)
{
ResultList *result = 0;
DictionaryCursor c;
shorter.Start_Get(c);
DocMatch *match = (DocMatch *)shorter.Get_NextElement(c);
while(match)
{
List confirms;
ListCursor lc;
lists.Start_Get(lc);
ResultList *list = (ResultList *)lists.Get_Next(lc);
while(list)
{
DocMatch *confirm = list->find(match->GetId());
if(confirm)
{
confirms.Add(confirm);
}
list = (ResultList *)lists.Get_Next(lc);
}
if(confirms.Count() == lists.Count())
{
if(!result)
{
result = new ResultList;
}
DocMatch *copy = new DocMatch(*match);
confirms.Start_Get();
DocMatch *confirm = (DocMatch *)confirms.Get_Next();
while(confirm)
{
copy->Merge(*confirm);
confirm = (DocMatch *)confirms.Get_Next();
}
result->add(copy);
}
confirms.Release();
match = (DocMatch *)shorter.Get_NextElement(c);
}
return result;
}
|