~ubuntu-branches/debian/sid/chessx/sid

« back to all changes in this revision

Viewing changes to src/database/query.cpp

  • Committer: Package Import Robot
  • Author(s): Niklas Fiekas
  • Date: 2013-10-31 17:02:37 UTC
  • Revision ID: package-import@ubuntu.com-20131031170237-wghf5j9jlv28gmls
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   (C) 2005 William Hoggarth <whoggarth@users.sourceforge.net>           *
 
3
 *   (C) 2005-2006 Marius Roets <roets.marius@gmail.com>                   *
 
4
 *   (C) 2006-2009 Michal Rudolf <mrudolf@kdewebdev.org>                   *
 
5
 *                                                                         *
 
6
 *   This program is free software; you can redistribute it and/or modify  *
 
7
 *   it under the terms of the GNU General Public License as published by  *
 
8
 *   the Free Software Foundation; either version 2 of the License, or     *
 
9
 *   (at your option) any later version.                                   *
 
10
 ***************************************************************************/
 
11
 
 
12
#include "query.h"
 
13
 
 
14
Query::Query()
 
15
{
 
16
    clear();
 
17
}
 
18
 
 
19
Query::~Query()
 
20
{
 
21
    while(!m_search.isEmpty())
 
22
    {
 
23
        delete m_search.takeFirst();
 
24
    }
 
25
    clear();
 
26
}
 
27
 
 
28
Search::Operator Query::searchOperator(int index) const
 
29
{
 
30
    if(!isValidIndex(index))
 
31
    {
 
32
        return Search::NullOperator;
 
33
    }
 
34
    int i = m_operatorMap.indexOf(index);
 
35
    if(i >= 0)
 
36
    {
 
37
        return m_operator.at(i);
 
38
    }
 
39
    else
 
40
    {
 
41
        return Search::NullOperator;
 
42
    }
 
43
}
 
44
 
 
45
Search* Query::search(int index)
 
46
{
 
47
    if(!isValidIndex(index))
 
48
    {
 
49
        return NULL;
 
50
    }
 
51
    int i = m_searchMap.indexOf(index);
 
52
    if(i >= 0)
 
53
    {
 
54
        return m_search.at(i);
 
55
    }
 
56
    else
 
57
    {
 
58
        return NULL;
 
59
    }
 
60
}
 
61
 
 
62
int Query::count() const
 
63
{
 
64
    return m_elementType.count();
 
65
}
 
66
 
 
67
int Query::countOperators() const
 
68
{
 
69
    return m_operatorMap.count();
 
70
}
 
71
 
 
72
int Query::countOperands() const
 
73
{
 
74
    return m_searchMap.count();
 
75
}
 
76
 
 
77
bool Query::isElementSearch(int index) const
 
78
{
 
79
    if(!isValidIndex(index))
 
80
    {
 
81
        return false;
 
82
    }
 
83
    if(m_elementType[index] == SearchElement)
 
84
    {
 
85
        return true;
 
86
    }
 
87
    else
 
88
    {
 
89
        return false;
 
90
    }
 
91
}
 
92
 
 
93
bool Query::isElementOperator(int index) const
 
94
{
 
95
    if(!isValidIndex(index))
 
96
    {
 
97
        return false;
 
98
    }
 
99
    if(m_elementType[index] == OperatorElement)
 
100
    {
 
101
        return true;
 
102
    }
 
103
    else
 
104
    {
 
105
        return false;
 
106
    }
 
107
}
 
108
 
 
109
bool Query::isValid()
 
110
{
 
111
    int i;
 
112
    if(!internalCheck())
 
113
    {
 
114
        return false;
 
115
    }
 
116
    // Check if there are enough operands for the operators
 
117
    int operandCount = 0;
 
118
    Search::Operator op;
 
119
    ElementTypeList::iterator elementIter;
 
120
    for(elementIter = m_elementType.begin(), i = 0; elementIter != m_elementType.end(); ++elementIter, ++i)
 
121
    {
 
122
        switch(*elementIter)
 
123
        {
 
124
        case SearchElement :
 
125
            ++operandCount;
 
126
            break;
 
127
        case OperatorElement :
 
128
            op = searchOperator(i);
 
129
            switch(op)
 
130
            {
 
131
            case Search::And :
 
132
            case Search::Or :
 
133
            case Search::Remove :
 
134
                // These operators need 2 operands, and leaves one answer on the stack
 
135
                if(operandCount < 2)
 
136
                {
 
137
                    return false;
 
138
                }
 
139
                --operandCount;
 
140
                break;
 
141
            case Search::Not :
 
142
                //Not needs one operand, and it leaves one answer on the stack
 
143
                if(operandCount < 1)
 
144
                {
 
145
                    return false;
 
146
                }
 
147
                break;
 
148
            case Search::NullOperator :
 
149
                // Not sure if this is valid or not
 
150
                break;
 
151
            default :
 
152
                // Undefined operator
 
153
                return false;
 
154
            }
 
155
            break;
 
156
        default :
 
157
            // Undefined element
 
158
            return false;
 
159
        }
 
160
    }
 
161
    if(operandCount != 1)
 
162
    {
 
163
        qDebug("Warning: Not enough operators to evaluate all operands");
 
164
    }
 
165
 
 
166
    return true;
 
167
}
 
168
 
 
169
void Query::append(Search::Operator op)
 
170
{
 
171
    m_operator.append(op);
 
172
    m_operatorMap.append(m_elementType.count());
 
173
    m_elementType.append(OperatorElement);
 
174
}
 
175
 
 
176
void Query::append(const Search& search)
 
177
{
 
178
    m_search.append(search.clone());
 
179
    m_searchMap.append(m_elementType.count());
 
180
    m_elementType.append(SearchElement);
 
181
}
 
182
 
 
183
bool Query::set(int index, Search::Operator op)
 
184
{
 
185
    if(!isValidIndex(index))
 
186
    {
 
187
        return false;
 
188
    }
 
189
    int subindex = m_operatorMap.indexOf(index);
 
190
    if(subindex >= 0)
 
191
    {
 
192
        // In this case the given index is already an operator, so we just replace it
 
193
        m_operator[subindex] = op;
 
194
        return true;
 
195
    }
 
196
    else
 
197
    {
 
198
        subindex = m_searchMap.indexOf(index);
 
199
        if(subindex >= 0)
 
200
        {
 
201
            // Here the given index is a search, so we have to remove the search,
 
202
            // and add a operator at that position. If autodelete is set, the memory
 
203
            // for the search will be deallocated.
 
204
            m_searchMap.removeAt(m_searchMap.at(subindex));
 
205
            delete m_search.at(subindex);
 
206
            m_search.removeAt(subindex);
 
207
            m_operator.append(op);
 
208
            m_operatorMap.append(index);
 
209
            m_elementType[index] = OperatorElement;
 
210
            return true;
 
211
        }
 
212
        else
 
213
        {
 
214
            // The index could not be found in the search or operator lists. Strange!?
 
215
            return false;
 
216
        }
 
217
    }
 
218
}
 
219
 
 
220
bool Query::set(int index, const Search& search)
 
221
{
 
222
    if(!isValidIndex(index))
 
223
    {
 
224
        return false;
 
225
    }
 
226
    int subindex = m_searchMap.indexOf(index);
 
227
    if(subindex >= 0)
 
228
    {
 
229
        delete m_search.at(subindex);
 
230
        m_search.replace(subindex, search.clone());
 
231
        return true;
 
232
    }
 
233
    else
 
234
    {
 
235
        subindex = m_operatorMap.indexOf(index);
 
236
        if(subindex >= 0)
 
237
        {
 
238
            // Here the given index is a operator, so we have to remove the operator,
 
239
            // and add a search at that position
 
240
            m_operatorMap.removeAt(m_operatorMap.at(subindex));
 
241
            m_operator.removeAt(m_operator.at(subindex));
 
242
            m_search.append(search.clone());
 
243
            m_searchMap.append(index);
 
244
            m_elementType[index] = SearchElement;
 
245
            return true;
 
246
        }
 
247
        else
 
248
        {
 
249
            // The index could not be found in the operator or search lists
 
250
            return false;
 
251
        }
 
252
    }
 
253
}
 
254
 
 
255
bool Query::remove(int index)
 
256
{
 
257
    int indexToRemove;
 
258
    IntList::iterator intIt;
 
259
    if(!isValidIndex(index))
 
260
    {
 
261
        return false;
 
262
    }
 
263
 
 
264
    switch(m_elementType[index])
 
265
    {
 
266
    case OperatorElement:
 
267
        indexToRemove = m_operatorMap.indexOf(index);
 
268
        if(indexToRemove >= 0)
 
269
        {
 
270
            m_operatorMap.removeAt(m_operatorMap.at(indexToRemove));
 
271
            m_operator.removeAt(m_operator.at(indexToRemove));
 
272
        }
 
273
        else
 
274
        {
 
275
            // Element type does not match actual element
 
276
            return false;
 
277
        }
 
278
        break;
 
279
    case SearchElement:
 
280
        indexToRemove = m_searchMap.indexOf(index);
 
281
        if(indexToRemove >= 0)
 
282
        {
 
283
            m_searchMap.removeAt(m_searchMap.at(indexToRemove));
 
284
            delete m_search.at(indexToRemove);
 
285
            m_search.removeAt(indexToRemove);
 
286
        }
 
287
        else
 
288
        {
 
289
            // Element type does not match actual element
 
290
            return false;
 
291
        }
 
292
        break;
 
293
    default :
 
294
        // Undefined element
 
295
        return false;
 
296
    }
 
297
    m_elementType.removeAt(m_elementType.at(index));
 
298
    // Reduces index for elements after the element being remove, moving them
 
299
    // up in the virtual list.
 
300
    for(intIt = m_operatorMap.begin(); intIt != m_operatorMap.end(); ++intIt)
 
301
    {
 
302
        if((*intIt) > index)
 
303
        {
 
304
            (*intIt)--;
 
305
        }
 
306
    }
 
307
    for(intIt = m_searchMap.begin(); intIt != m_searchMap.end(); ++intIt)
 
308
    {
 
309
        if((*intIt) > index)
 
310
        {
 
311
            (*intIt)--;
 
312
        }
 
313
    }
 
314
    return true;
 
315
}
 
316
 
 
317
void Query::clear()
 
318
{
 
319
    while(!m_search.isEmpty())
 
320
    {
 
321
        delete m_search.takeFirst();
 
322
    }
 
323
    m_search.clear();
 
324
    m_operator.clear();
 
325
    m_searchMap.clear();
 
326
    m_operatorMap.clear();
 
327
    m_elementType.clear();
 
328
}
 
329
 
 
330
bool Query::isValidIndex(unsigned int index) const
 
331
{
 
332
    if((int)index > (int)(m_elementType.count() - 1))
 
333
    {
 
334
        return false;
 
335
    }
 
336
    return true;
 
337
}
 
338
 
 
339
bool Query::internalCheck()
 
340
{
 
341
    int i;
 
342
    Search::Operator op;
 
343
    Search *s = NULL;
 
344
    ElementTypeList::iterator elementIter;
 
345
 
 
346
    if(count() != (countOperands() + countOperators()))
 
347
    {
 
348
        return false;
 
349
    }
 
350
 
 
351
    for(elementIter = m_elementType.begin(), i = 0; elementIter != m_elementType.end(); ++elementIter, ++i)
 
352
    {
 
353
        switch(*elementIter)
 
354
        {
 
355
        case SearchElement :
 
356
            s = search(i);
 
357
            if(s == NULL)
 
358
            {
 
359
                return false;
 
360
            }
 
361
            switch(s->type())
 
362
            {
 
363
            case Search::NullSearch :
 
364
            case Search::PositionSearch :
 
365
            case Search::EloSearch :
 
366
                break;
 
367
            default :
 
368
                // undefined search
 
369
                return false;
 
370
            }
 
371
            break;
 
372
        case OperatorElement :
 
373
            op = searchOperator(i);
 
374
            switch(op)
 
375
            {
 
376
            case Search::And :
 
377
            case Search::Or :
 
378
            case Search::Remove :
 
379
            case Search::Not :
 
380
            case Search::NullOperator :
 
381
                break;
 
382
            default :
 
383
                // Undefined operator
 
384
                return false;
 
385
            }
 
386
            break;
 
387
        default :
 
388
            // Undefined element
 
389
            return false;
 
390
        }
 
391
    }
 
392
    return true;
 
393
}