diff options
Diffstat (limited to '3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.cpp')
-rw-r--r-- | 3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.cpp | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.cpp b/3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.cpp new file mode 100644 index 000000000..04f45e931 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.cpp @@ -0,0 +1,212 @@ +/*------------------------------------------------------------------------------ +* 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 "FieldSortedHitQueue.h" +#include "FieldDocSortedHitQueue.h" +#include "Compare.h" + +CL_NS_USE(util) +CL_NS_USE(index) +CL_NS_DEF(search) + +FieldSortedHitQueue::hitqueueCacheType FieldSortedHitQueue::Comparators(false,true); + +FieldSortedHitQueue::FieldSortedHitQueue (IndexReader* reader, SortField** _fields, int32_t size): + fieldsLen(0), + maxscore(1.0f) +{ + while ( _fields[fieldsLen] != 0 ) + fieldsLen++; + + comparators = _CL_NEWARRAY(ScoreDocComparator*,fieldsLen+1); + SortField** tmp = _CL_NEWARRAY(SortField*,fieldsLen+1); + for (int32_t i=0; i<fieldsLen; ++i) { + const TCHAR* fieldname = _fields[i]->getField(); + //todo: fields[i].getLocale(), not implemented + comparators[i] = getCachedComparator (reader, fieldname, _fields[i]->getType(), _fields[i]->getFactory()); + tmp[i] = _CLNEW SortField (fieldname, comparators[i]->sortType(), _fields[i]->getReverse()); + } + comparatorsLen = fieldsLen; + comparators[fieldsLen]=NULL; + tmp[fieldsLen] = NULL; + this->fields = tmp; + + initialize(size,true); +} + + +bool FieldSortedHitQueue::lessThan (FieldDoc* docA, FieldDoc* docB) { + // keep track of maximum score + if (docA->scoreDoc.score > maxscore) maxscore = docA->scoreDoc.score; + if (docB->scoreDoc.score > maxscore) maxscore = docB->scoreDoc.score; + + // run comparators + int32_t c = 0; + for ( int32_t i=0; c==0 && i<comparatorsLen; ++i ) { + c = (fields[i]->getReverse()) ? comparators[i]->compare (&docB->scoreDoc, &docA->scoreDoc) : + comparators[i]->compare (&docA->scoreDoc, &docB->scoreDoc); + } + // avoid random sort order that could lead to duplicates (bug #31241): + if (c == 0) + return docA->scoreDoc.doc > docB->scoreDoc.doc; + return c > 0; +} + + +//static +ScoreDocComparator* FieldSortedHitQueue::comparatorString (IndexReader* reader, const TCHAR* field) { + //const TCHAR* field = CLStringIntern::intern(fieldname CL_FILELINE); + FieldCacheAuto* fa = FieldCache::DEFAULT->getStringIndex (reader, field); + //CLStringIntern::unintern(field); + + CND_PRECONDITION(fa->contentType==FieldCacheAuto::STRING_INDEX,"Content type is incorrect"); + fa->ownContents = false; + return _CLNEW ScoreDocComparators::String(fa->stringIndex, fa->contentLen); +} + +//static +ScoreDocComparator* FieldSortedHitQueue::comparatorInt (IndexReader* reader, const TCHAR* field){ + //const TCHAR* field = CLStringIntern::intern(fieldname CL_FILELINE); + FieldCacheAuto* fa = FieldCache::DEFAULT->getInts (reader, field); + //CLStringIntern::unintern(field); + + CND_PRECONDITION(fa->contentType==FieldCacheAuto::INT_ARRAY,"Content type is incorrect"); + return _CLNEW ScoreDocComparators::Int32(fa->intArray, fa->contentLen); + } + +//static + ScoreDocComparator* FieldSortedHitQueue::comparatorFloat (IndexReader* reader, const TCHAR* field) { + //const TCHAR* field = CLStringIntern::intern(fieldname CL_FILELINE); + FieldCacheAuto* fa = FieldCache::DEFAULT->getFloats (reader, field); + //CLStringIntern::unintern(field); + + CND_PRECONDITION(fa->contentType==FieldCacheAuto::FLOAT_ARRAY,"Content type is incorrect"); + return _CLNEW ScoreDocComparators::Float (fa->floatArray, fa->contentLen); + } +//static + ScoreDocComparator* FieldSortedHitQueue::comparatorAuto (IndexReader* reader, const TCHAR* field){ + //const TCHAR* field = CLStringIntern::intern(fieldname CL_FILELINE); + FieldCacheAuto* fa = FieldCache::DEFAULT->getAuto (reader, field); + //CLStringIntern::unintern(field); + + if (fa->contentType == FieldCacheAuto::STRING_INDEX ) { + return comparatorString (reader, field); + } else if (fa->contentType == FieldCacheAuto::INT_ARRAY) { + return comparatorInt (reader, field); + } else if (fa->contentType == FieldCacheAuto::FLOAT_ARRAY) { + return comparatorFloat (reader, field); + } else if (fa->contentType == FieldCacheAuto::STRING_ARRAY) { + return comparatorString (reader, field); + } else { + _CLTHROWA(CL_ERR_Runtime, "unknown data type in field"); //todo: rich error information: '"+field+"'"); + } + } + + + //todo: Locale locale, not implemented yet + ScoreDocComparator* FieldSortedHitQueue::getCachedComparator (IndexReader* reader, const TCHAR* fieldname, int32_t type, SortComparatorSource* factory){ + if (type == SortField::DOC) + return ScoreDocComparator::INDEXORDER; + if (type == SortField::DOCSCORE) + return ScoreDocComparator::RELEVANCE; + ScoreDocComparator* comparator = lookup (reader, fieldname, type, factory); + if (comparator == NULL) { + switch (type) { + case SortField::AUTO: + comparator = comparatorAuto (reader, fieldname); + break; + case SortField::INT: + comparator = comparatorInt (reader, fieldname); + break; + case SortField::FLOAT: + comparator = comparatorFloat (reader, fieldname); + break; + case SortField::STRING: + //if (locale != NULL) + // comparator = comparatorStringLocale (reader, fieldname, locale); + //else + comparator = comparatorString (reader, fieldname); + break; + case SortField::CUSTOM: + comparator = factory->newComparator (reader, fieldname); + break; + default: + _CLTHROWA(CL_ERR_Runtime,"unknown field type"); + //todo: extend error + //throw _CLNEW RuntimeException ("unknown field type: "+type); + } + store (reader, fieldname, type, factory, comparator); + } + return comparator; + } + + + FieldDoc* FieldSortedHitQueue::fillFields (FieldDoc* doc) const{ + int32_t n = comparatorsLen; + Comparable** fields = _CL_NEWARRAY(Comparable*,n+1); + for (int32_t i=0; i<n; ++i) + fields[i] = comparators[i]->sortValue(&doc->scoreDoc); + fields[n]=NULL; + doc->fields = fields; + if (maxscore > 1.0f) + doc->scoreDoc.score /= maxscore; // normalize scores + return doc; + } + + ScoreDocComparator* FieldSortedHitQueue::lookup (IndexReader* reader, const TCHAR* field, int32_t type, SortComparatorSource* factory) { + ScoreDocComparator* sdc = NULL; + FieldCacheImpl::FileEntry* entry = (factory != NULL) + ? _CLNEW FieldCacheImpl::FileEntry (field, factory) + : _CLNEW FieldCacheImpl::FileEntry (field, type); + + { + SCOPED_LOCK_MUTEX(Comparators.THIS_LOCK) + hitqueueCacheReaderType* readerCache = Comparators.get(reader); + if (readerCache == NULL){ + _CLDELETE(entry); + return NULL; + } + + sdc = readerCache->get (entry); + _CLDELETE(entry); + } + return sdc; + } + + void FieldSortedHitQueue::closeCallback(CL_NS(index)::IndexReader* reader, void*){ + SCOPED_LOCK_MUTEX(Comparators.THIS_LOCK) + Comparators.remove(reader); + } + + //static + void FieldSortedHitQueue::store (IndexReader* reader, const TCHAR* field, int32_t type, SortComparatorSource* factory, ScoreDocComparator* value) { + FieldCacheImpl::FileEntry* entry = (factory != NULL) + ? _CLNEW FieldCacheImpl::FileEntry (field, factory) + : _CLNEW FieldCacheImpl::FileEntry (field, type); + + { + SCOPED_LOCK_MUTEX(Comparators.THIS_LOCK) + hitqueueCacheReaderType* readerCache = Comparators.get(reader); + if (readerCache == NULL) { + readerCache = _CLNEW hitqueueCacheReaderType(true); + Comparators.put(reader,readerCache); + reader->addCloseCallback(FieldSortedHitQueue::closeCallback,NULL); + } + readerCache->put (entry, value); + //return NULL; //supposed to return previous value... + } + } + +FieldSortedHitQueue::~FieldSortedHitQueue(){ + _CLDELETE_ARRAY(comparators); + if ( fields != NULL ){ + for ( int i=0;fields[i]!=NULL;i++ ) + _CLDELETE(fields[i]); + _CLDELETE_ARRAY(fields); + } +} +CL_NS_END |