summaryrefslogtreecommitdiffstats
path: root/3rdparty/clucene/src/CLucene/search/FieldDocSortedHitQueue.cpp
blob: 0a5210903cce9ca3d1f27ff14b57ab7d11171289 (plain)
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*------------------------------------------------------------------------------
* 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 "FieldDocSortedHitQueue.h"


CL_NS_USE(util)
CL_NS_DEF(search)


FieldDoc::FieldDoc (int32_t doc, qreal score)
{
	this->scoreDoc.doc = doc;
	this->scoreDoc.score = score;
	fields=NULL;
}

FieldDoc::FieldDoc (int32_t doc, qreal score, CL_NS(util)::Comparable** fields)
{
	this->scoreDoc.doc = doc;
	this->scoreDoc.score = score;
	this->fields = fields;
}

FieldDoc::~FieldDoc(){
    if ( fields != NULL ){
       for ( int i=0;fields[i]!=NULL;i++ )
           _CLDELETE(fields[i]);
       _CLDELETE_ARRAY(fields);
    }
}



FieldDocSortedHitQueue::FieldDocSortedHitQueue (SortField** fields, int32_t size) {
	this->fields = fields;
	_countsize();
	//this->collators = hasCollators (fields);
	initialize (size,true);
}

bool FieldDocSortedHitQueue::lessThan (FieldDoc* docA, FieldDoc* docB) {
	int32_t n = fieldsLen;
	int32_t c = 0;
	qreal f1,f2,r1,r2;
	int32_t i1,i2;
	const TCHAR *s1, *s2;

	for (int32_t i=0; i<n && c==0; ++i) {
		int32_t type = fields[i]->getType();
		if (fields[i]->getReverse()) {
			switch (type) {
				case SortField::DOCSCORE:
					r1 = __REINTERPRET_CAST(Compare::Float*, docA->fields[i])->getValue();
					r2 = __REINTERPRET_CAST(Compare::Float*, docB->fields[i])->getValue();
					if (r1 < r2) c = -1;
					if (r1 > r2) c = 1;
					break;
				case SortField::DOC:
				case SortField::INT:
					i1 = __REINTERPRET_CAST(Compare::Int32*, docA->fields[i])->getValue();
					i2 = __REINTERPRET_CAST(Compare::Int32*, docB->fields[i])->getValue();
					if (i1 > i2) c = -1;
					if (i1 < i2) c = 1;
					break;
				case SortField::STRING:
					s1 = __REINTERPRET_CAST(Compare::TChar*, docA->fields[i])->getValue();
					s2 = __REINTERPRET_CAST(Compare::TChar*, docB->fields[i])->getValue();
					if (s2 == NULL) c = -1;      // could be NULL if there are
					else if (s1 == NULL) c = 1;  // no terms in the given field
					else c = _tcscmp(s2,s1); //else if (fields[i].getLocale() == NULL) {

					/*todo: collators not impl
					} else {
						c = collators[i].compare (s2, s1);
					}*/
					break;
				case SortField::FLOAT:
					f1 = __REINTERPRET_CAST(Compare::Float*, docA->fields[i])->getValue();
					f2 = __REINTERPRET_CAST(Compare::Float*, docB->fields[i])->getValue();
					if (f1 > f2) c = -1;
					if (f1 < f2) c = 1;
					break;
				case SortField::CUSTOM:
					c = docB->fields[i]->compareTo (docA->fields[i]);
					break;
				case SortField::AUTO:
					// we cannot handle this - even if we determine the type of object (qreal or
					// Integer), we don't necessarily know how to compare them (both SCORE and
					// qreal both contain floats, but are sorted opposite of each other). Before
					// we get here, each AUTO should have been replaced with its actual value.
					_CLTHROWA (CL_ERR_Runtime,"FieldDocSortedHitQueue cannot use an AUTO SortField");
				default:
					_CLTHROWA (CL_ERR_Runtime, "invalid SortField type"); //todo: rich error... : "+type);
			}
		} else {
			switch (type) {
				case SortField::DOCSCORE:
					r1 = __REINTERPRET_CAST(Compare::Float*, docA->fields[i])->getValue();
					r2 = __REINTERPRET_CAST(Compare::Float*, docB->fields[i])->getValue();
					if (r1 > r2) c = -1;
					if (r1 < r2) c = 1;
					break;
				case SortField::DOC:
				case SortField::INT:
					i1 = __REINTERPRET_CAST(Compare::Int32*, docA->fields[i])->getValue();
					i2 = __REINTERPRET_CAST(Compare::Int32*, docB->fields[i])->getValue();
					if (i1 < i2) c = -1;
					if (i1 > i2) c = 1;
					break;
				case SortField::STRING:
					s1 = __REINTERPRET_CAST(Compare::TChar*, docA->fields[i])->getValue();
					s2 = __REINTERPRET_CAST(Compare::TChar*, docB->fields[i])->getValue();
					// NULL values need to be sorted first, because of how FieldCache.getStringIndex()
					// works - in that routine, any documents without a value in the given field are
					// put first.
					if (s1 == NULL) c = -1;      // could be NULL if there are
					else if (s2 == NULL) c = 1;  // no terms in the given field
					else c = _tcscmp(s1,s2); //else if (fields[i].getLocale() == NULL) {
					
					/* todo: collators not implemented } else {
						c = collators[i].compare (s1, s2);
					}*/
					break;
				case SortField::FLOAT:
					f1 = __REINTERPRET_CAST(Compare::Float*, docA->fields[i])->getValue();
					f2 = __REINTERPRET_CAST(Compare::Float*, docB->fields[i])->getValue();
					if (f1 < f2) c = -1;
					if (f1 > f2) c = 1;
					break;
				case SortField::CUSTOM:
					c = docA->fields[i]->compareTo (docB->fields[i]);
					break;
				case SortField::AUTO:
					// we cannot handle this - even if we determine the type of object (qreal or
					// Integer), we don't necessarily know how to compare them (both SCORE and
					// qreal both contain floats, but are sorted opposite of each other). Before
					// we get here, each AUTO should have been replaced with its actual value.
					_CLTHROWA (CL_ERR_Runtime,"FieldDocSortedHitQueue cannot use an AUTO SortField");
				default:
					_CLTHROWA (CL_ERR_Runtime,"invalid SortField type"); //todo: rich error... : "+type);
			}
		}
	}
	return c > 0;
}

void FieldDocSortedHitQueue::setFields (SortField** fields) {
	SCOPED_LOCK_MUTEX(THIS_LOCK)
	if (this->fields == NULL) {
		this->fields = fields;
		_countsize();
		//this->collators = hasCollators (fields);
	}else if ( fields == NULL )
		this->fields = NULL;
}

FieldDocSortedHitQueue::~FieldDocSortedHitQueue(){
    if ( fields != NULL ){
       for ( int i=0;fields[i]!=NULL;i++ )
           _CLDELETE(fields[i]);
       _CLDELETE_ARRAY(fields);
    }
}

CL_NS_END