~ubuntu-branches/ubuntu/oneiric/arora/oneiric

« back to all changes in this revision

Viewing changes to src/cookiejar/networkcookiejar/trie_p.h

  • Committer: Bazaar Package Importer
  • Author(s): Roderick B. Greening
  • Date: 2009-09-10 15:24:04 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090910152404-668k22ux3mfap6g0
Tags: 0.9.0-0ubuntu1
* New upstream release
* Update patches:
  - kubuntu_02_default_bookmarks.diff
* Remove patches:
  - kubuntu_04_startpage_spacing.diff (fixed upstream)
  - kubuntu_05_manpages.diff (fixed upstream)
  - kubuntu_07_adblock.diff (unstable/unsuitable)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
   Copyright (C) 2009, Torch Mobile Inc. and Linden Research, Inc. All rights reserved.
3
 
*/
4
 
 
5
 
/* ***** BEGIN LICENSE BLOCK *****
6
 
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7
 
 *
8
 
 * The contents of this file are subject to the Mozilla Public License Version
9
 
 * 1.1 (the "License"); you may not use this file except in compliance with
10
 
 * the License. You may obtain a copy of the License at
11
 
 * http://www.mozilla.org/MPL/
12
 
 *
13
 
 * Software distributed under the License is distributed on an "AS IS" basis,
14
 
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
15
 
 * for the specific language governing rights and limitations under the
16
 
 * License.
17
 
 *
18
 
 * The Original Code is Torch Mobile Inc. (http://www.torchmobile.com/) code
19
 
 *
20
 
 * The Initial Developer of the Original Code is:
21
 
 *   Benjamin Meyer (benjamin.meyer@torchmobile.com)
22
 
 *
23
 
 * Alternatively, the contents of this file may be used under the terms of
24
 
 * either the GNU General Public License Version 2 or later (the "GPL"), or
25
 
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26
 
 * in which case the provisions of the GPL or the LGPL are applicable instead
27
 
 * of those above. If you wish to allow use of your version of this file only
28
 
 * under the terms of either the GPL or the LGPL, and not to allow others to
29
 
 * use your version of this file under the terms of the MPL, indicate your
30
 
 * decision by deleting the provisions above and replace them with the notice
31
 
 * and other provisions required by the GPL or the LGPL. If you do not delete
32
 
 * the provisions above, a recipient may use your version of this file under
33
 
 * the terms of any one of the MPL, the GPL or the LGPL.
34
 
 *
35
 
 * ***** END LICENSE BLOCK ***** */
36
 
 
37
 
#ifndef TRIE_H
38
 
#define TRIE_H
39
 
 
40
 
//#define TRIE_DEBUG
41
 
 
42
 
#include <qstringlist.h>
43
 
 
44
 
#if defined(TRIE_DEBUG)
45
 
#include <qdebug.h>
46
 
#endif
47
 
 
48
 
/*
49
 
    A Trie tree (prefix tree) where the lookup takes m in the worst case.
50
 
 
51
 
    The key is stored in *reverse* order
52
 
 
53
 
    Example:
54
 
    Keys: x,a y,a
55
 
 
56
 
    Trie:
57
 
    a
58
 
    | \
59
 
    x  y
60
 
*/
61
 
 
62
 
template<class T>
63
 
class Trie {
64
 
public:
65
 
    Trie();
66
 
    ~Trie();
67
 
 
68
 
    void clear();
69
 
    void insert(const QStringList &key, const T &value);
70
 
    bool remove(const QStringList &key, const T &value);
71
 
    QList<T> find(const QStringList &key) const;
72
 
    QList<T> all() const;
73
 
 
74
 
    inline bool contains(const QStringList &key) const;
75
 
    inline bool isEmpty() const { return children.isEmpty() && values.isEmpty(); }
76
 
 
77
 
private:
78
 
    const Trie<T>* walkTo(const QStringList &key) const;
79
 
    Trie<T>* walkTo(const QStringList &key, bool create = false);
80
 
 
81
 
    template<class T1> friend QDataStream &operator<<(QDataStream &, const Trie<T1>&);
82
 
    template<class T1> friend QDataStream &operator>>(QDataStream &, Trie<T1>&);
83
 
 
84
 
    QList<T> values;
85
 
    QStringList childrenKeys;
86
 
    QList<Trie<T> > children;
87
 
};
88
 
 
89
 
template<class T>
90
 
Trie<T>::Trie() {
91
 
}
92
 
 
93
 
template<class T>
94
 
Trie<T>::~Trie() {
95
 
}
96
 
 
97
 
template<class T>
98
 
void Trie<T>::clear() {
99
 
#if defined(TRIE_DEBUG)
100
 
    qDebug() << "Trie::" << __FUNCTION__;
101
 
#endif
102
 
    values.clear();
103
 
    childrenKeys.clear();
104
 
    children.clear();
105
 
}
106
 
 
107
 
template<class T>
108
 
bool Trie<T>::contains(const QStringList &key) const {
109
 
    return walkTo(key);
110
 
}
111
 
 
112
 
template<class T>
113
 
void Trie<T>::insert(const QStringList &key, const T &value) {
114
 
#if defined(TRIE_DEBUG)
115
 
    qDebug() << "Trie::" << __FUNCTION__ << key << value;
116
 
#endif
117
 
    Trie<T> *node = walkTo(key, true);
118
 
    if (node)
119
 
        node->values.append(value);
120
 
}
121
 
 
122
 
template<class T>
123
 
bool Trie<T>::remove(const QStringList &key, const T &value) {
124
 
#if defined(TRIE_DEBUG)
125
 
    qDebug() << "Trie::" << __FUNCTION__ << key << value;
126
 
#endif
127
 
    Trie<T> *node = walkTo(key, true);
128
 
    if (node) {
129
 
        bool removed = node->values.removeOne(value);
130
 
        if (!removed)
131
 
            return false;
132
 
 
133
 
        // A faster implementation of removing nodes up the tree
134
 
        // can be created if profile shows this to be slow
135
 
        QStringList subKey = key;
136
 
        while (node->values.isEmpty()
137
 
               && node->children.isEmpty()
138
 
               && !subKey.isEmpty()) {
139
 
            QString currentLevelKey = subKey.first();
140
 
            QStringList parentKey = subKey.mid(1);
141
 
            Trie<T> *parent = walkTo(parentKey, false);
142
 
            Q_ASSERT(parent);
143
 
            QStringList::iterator iterator;
144
 
            iterator = qBinaryFind(parent->childrenKeys.begin(),
145
 
                                   parent->childrenKeys.end(),
146
 
                                   currentLevelKey);
147
 
            Q_ASSERT(iterator != parent->childrenKeys.end());
148
 
            int index = iterator - parent->childrenKeys.begin();
149
 
            parent->children.removeAt(index);
150
 
            parent->childrenKeys.removeAt(index);
151
 
 
152
 
            node = parent;
153
 
            subKey = parentKey;
154
 
        }
155
 
        return removed;
156
 
    }
157
 
    return false;
158
 
}
159
 
 
160
 
template<class T>
161
 
QList<T> Trie<T>::find(const QStringList &key) const {
162
 
#if defined(TRIE_DEBUG)
163
 
    qDebug() << "Trie::" << __FUNCTION__ << key;
164
 
#endif
165
 
    const Trie<T> *node = walkTo(key);
166
 
    if (node)
167
 
        return node->values;
168
 
    return QList<T>();
169
 
}
170
 
 
171
 
template<class T>
172
 
QList<T> Trie<T>::all() const {
173
 
#if defined(TRIE_DEBUG)
174
 
    qDebug() << "Trie::" << __FUNCTION__;
175
 
#endif
176
 
    QList<T> all = values;
177
 
    for (int i = 0; i < children.count(); ++i)
178
 
        all += children[i].all();
179
 
    return all;
180
 
}
181
 
 
182
 
template<class T>
183
 
QDataStream &operator<<(QDataStream &out, const Trie<T>&trie) {
184
 
    out << trie.values;
185
 
    out << trie.childrenKeys;
186
 
    out << trie.children;
187
 
    Q_ASSERT(trie.childrenKeys.count() == trie.children.count());
188
 
    return out;
189
 
}
190
 
 
191
 
template<class T>
192
 
QDataStream &operator>>(QDataStream &in, Trie<T> &trie) {
193
 
    trie.clear();
194
 
    in >> trie.values;
195
 
    in >> trie.childrenKeys;
196
 
    in >> trie.children;
197
 
    Q_ASSERT(trie.childrenKeys.count() == trie.children.count());
198
 
    return in;
199
 
}
200
 
 
201
 
// Very fast const walk
202
 
template<class T>
203
 
const Trie<T>* Trie<T>::walkTo(const QStringList &key) const {
204
 
    const Trie<T> *node = this;
205
 
    QStringList::const_iterator childIterator;
206
 
    QStringList::const_iterator begin, end;
207
 
 
208
 
    int depth = key.count() - 1;
209
 
    while (depth >= 0) {
210
 
        const QString currentLevelKey = key.at(depth--);
211
 
        begin = node->childrenKeys.constBegin();
212
 
        end = node->childrenKeys.constEnd();
213
 
        childIterator = qBinaryFind(begin, end, currentLevelKey);
214
 
        if (childIterator == end)
215
 
            return 0;
216
 
        node = &node->children.at(childIterator - begin);
217
 
    }
218
 
    return node;
219
 
}
220
 
 
221
 
template<class T>
222
 
Trie<T>* Trie<T>::walkTo(const QStringList &key, bool create) {
223
 
    QStringList::iterator iterator;
224
 
    Trie<T> *node = this;
225
 
    QStringList::iterator begin, end;
226
 
    int depth = key.count() - 1;
227
 
    while (depth >= 0) {
228
 
        const QString currentLevelKey = key.at(depth--);
229
 
        begin = node->childrenKeys.begin();
230
 
        end = node->childrenKeys.end();
231
 
        iterator = qBinaryFind(begin, end, currentLevelKey);
232
 
#if defined(TRIE_DEBUG)
233
 
        qDebug() << "\t" << node << key << currentLevelKey << node->childrenKeys;
234
 
#endif
235
 
        int index = -1;
236
 
        if (iterator == end) {
237
 
            if (!create)
238
 
                return 0;
239
 
            iterator = qLowerBound(begin,
240
 
                                   end,
241
 
                                   currentLevelKey);
242
 
            index = iterator - begin;
243
 
            node->childrenKeys.insert(iterator, currentLevelKey);
244
 
            node->children.insert(index, Trie<T>());
245
 
        } else {
246
 
            index = iterator - begin;
247
 
        }
248
 
        Q_ASSERT(index >= 0 && index < node->children.count());
249
 
        node = &node->children[index];
250
 
    }
251
 
    return node;
252
 
}
253
 
 
254
 
#endif
255