You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
2.2 KiB

//
// NotQuery.cc
//
// NotQuery: 'not' query operator (n-ary not!)
// i.e. not(a, b, c, d...) == a except (b or c or d or...)
//
// Part of the ht://Dig package <http://www.htdig.org/>
// 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: NotQuery.cc,v 1.4 2004/05/28 13:15:24 lha Exp $
//
#include "NotQuery.h"
//
// l r not
// -------------------------
// 0 0 0
// 0 b 0
// 0 x 0
// a 0 a
// a b diff(a,b)
// a x a
// x 0 x
// x b x
// x x x
//
// note l is the first operand, r is the rest
// i.e. l = 0 => not = 0
// l = x => not = x
// r = 0 => not = l
// r = x => not = l
// subtract otherwise
//
ResultList *
NotQuery::Evaluate()
{
operands.Start_Get();
Query *operand = (Query *) operands.Get_Next();
ResultList *result = 0;
ResultList *positive = operand->GetResults();
if(positive)
{
List negative;
if(!positive->IsIgnore())
{
operand = (Query *) operands.Get_Next();
while(operand)
{
ResultList *next = operand->GetResults();
if(next && !next->IsIgnore())
{
negative.Add(next);
}
operand = (Query *) operands.Get_Next();
}
}
if(negative.Count())
{
result = Subtract(*positive, negative);
negative.Release();
}
else
{
result = new ResultList(*positive);
}
}
return result;
}
//
// make a result list containing all matches in positive
// with docId absent from negatives
//
ResultList *
NotQuery::Subtract(const ResultList &positive, const List &negatives)
{
ResultList *result = 0;
DictionaryCursor pc;
positive.Start_Get(pc);
DocMatch *match = (DocMatch *)positive.Get_NextElement(pc);
while(match)
{
bool confirm = true;
ListCursor lc;
negatives.Start_Get(lc);
ResultList *negative = (ResultList *)negatives.Get_Next(lc);
while(confirm && negative)
{
if(negative->exists(match->GetId()))
{
confirm = false;
}
negative = (ResultList *)negatives.Get_Next(lc);
}
if(confirm)
{
if(!result)
{
result = new ResultList;
}
result->add(new DocMatch(*match));
}
match = (DocMatch *)positive.Get_NextElement(pc);
}
return result;
}