summaryrefslogtreecommitdiffstats
path: root/3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.cpp')
-rw-r--r--3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.cpp212
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