/*------------------------------------------------------------------------------ * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team * * Distributable under the terms of either the Apache License (Version 2.0) or * the GNU Lesser General Public License, as specified in the COPYING file. ------------------------------------------------------------------------------*/ #include "CLucene/StdHeader.h" #include "RangeFilter.h" CL_NS_DEF(search) CL_NS_USE(index) CL_NS_USE(util) CL_NS_USE(document) RangeFilter::RangeFilter( const TCHAR* fieldName, const TCHAR* lowerTerm, const TCHAR* upperTerm, bool includeLower, bool includeUpper ) { this->field = STRDUP_TtoT(fieldName); if ( lowerTerm != NULL ) this->lowerValue = STRDUP_TtoT(lowerTerm); else this->lowerValue = NULL; if ( upperValue != NULL ) this->upperValue = STRDUP_TtoT(upperTerm); else this->upperValue = NULL; this->includeLower = includeLower; this->includeUpper = includeUpper; } /** * Constructs a filter for field fieldName matching * less than or equal to upperTerm. */ RangeFilter* RangeFilter::Less( TCHAR* fieldName, TCHAR* upperTerm ) { return new RangeFilter( fieldName, NULL, upperTerm, false, true ); } /** * Constructs a filter for field fieldName matching * more than or equal to lowerTerm. */ RangeFilter* RangeFilter::More( TCHAR* fieldName, TCHAR* lowerTerm ) { return new RangeFilter( fieldName, lowerTerm, NULL, true, false ); } RangeFilter::~RangeFilter() { _CLDELETE_CARRAY( lowerValue ); _CLDELETE_CARRAY( field ); _CLDELETE_CARRAY( upperValue ); } RangeFilter::RangeFilter( const RangeFilter& copy ) : field( STRDUP_TtoT(copy.field) ), lowerValue( STRDUP_TtoT(copy.lowerValue) ), upperValue( STRDUP_TtoT(copy.upperValue) ), includeLower( copy.includeLower ), includeUpper( copy.includeUpper ) { } Filter* RangeFilter::clone() const { return _CLNEW RangeFilter(*this ); } TCHAR* RangeFilter::toString() { size_t len = (field ? _tcslen(field) : 0) + (lowerValue ? _tcslen(lowerValue) : 0) + (upperValue ? _tcslen(upperValue) : 0) + 8; TCHAR* ret = _CL_NEWARRAY( TCHAR, len ); ret[0] = 0; _sntprintf( ret, len, _T("%s: [%s-%s]"), field, (lowerValue?lowerValue:_T("")), (upperValue?upperValue:_T("")) ); return ret; } /** Returns a BitSet with true for documents which should be permitted in search results, and false for those that should not. */ BitSet* RangeFilter::bits( IndexReader* reader ) { BitSet* bts = _CLNEW BitSet( reader->maxDoc() ); Term* term = NULL; Term* t = _CLNEW Term( field, (lowerValue ? lowerValue : _T("")), false ); TermEnum* enumerator = reader->terms( t ); // get enumeration of all terms after lowerValue _CLDECDELETE( t ); if( enumerator->term(false) == NULL ) { _CLDELETE( enumerator ); return bts; } bool checkLower = false; if( !includeLower ) // make adjustments to set to exclusive checkLower = true; TermDocs* termDocs = reader->termDocs(); try { do { term = enumerator->term(); if( term == NULL || _tcscmp(term->field(), field) ) break; if( !checkLower || lowerValue == NULL || _tcscmp(term->text(), lowerValue) > 0 ) { checkLower = false; if( upperValue != NULL ) { int compare = _tcscmp( upperValue, term->text() ); /* if beyond the upper term, or is exclusive and * this is equal to the upper term, break out */ if( (compare < 0) || (!includeUpper && compare == 0) ) break; } termDocs->seek( enumerator->term(false) ); while( termDocs->next() ) { bts->set( termDocs->doc() ); } } _CLDECDELETE( term ); } while( enumerator->next() ); } _CLFINALLY ( _CLDECDELETE( term ); termDocs->close(); _CLVDELETE( termDocs ); enumerator->close(); _CLDELETE( enumerator ); ); return bts; } CL_NS_END