~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/content/xul/templates/src/nsTemplateMatchSet.h

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Netscape Public License
 
6
 * Version 1.1 (the "License"); you may not use this file except in
 
7
 * compliance with the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/NPL/
 
9
 *
 
10
 * Software distributed under the License is distributed on an "AS IS" basis,
 
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
 * for the specific language governing rights and limitations under the
 
13
 * License.
 
14
 *
 
15
 * The Original Code is Mozilla Communicator client code.
 
16
 *
 
17
 * The Initial Developer of the Original Code is 
 
18
 * Netscape Communications Corporation.
 
19
 * Portions created by the Initial Developer are Copyright (C) 1998
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *   Chris Waterson <waterson@netscape.com>
 
24
 *
 
25
 *
 
26
 * Alternatively, the contents of this file may be used under the terms of
 
27
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
28
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
29
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
30
 * of those above. If you wish to allow use of your version of this file only
 
31
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
32
 * use your version of this file under the terms of the NPL, indicate your
 
33
 * decision by deleting the provisions above and replace them with the notice
 
34
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
35
 * the provisions above, a recipient may use your version of this file under
 
36
 * the terms of any one of the NPL, the GPL or the LGPL.
 
37
 *
 
38
 * ***** END LICENSE BLOCK ***** */
 
39
 
 
40
#ifndef nsTemplateMatchSet_h__
 
41
#define nsTemplateMatchSet_h__
 
42
 
 
43
#include "nsRuleNetwork.h"
 
44
#include "nsFixedSizeAllocator.h"
 
45
#include "nsTemplateMatch.h"
 
46
#include "pldhash.h"
 
47
 
 
48
class nsTemplateMatchSet {
 
49
public:
 
50
    class ConstIterator;
 
51
    friend class ConstIterator; // so it can see Element
 
52
 
 
53
protected:
 
54
    class Element {
 
55
    public:
 
56
        Element(nsTemplateMatch* aMatch)
 
57
            : mMatch(aMatch), mNext(nsnull) {}
 
58
 
 
59
        nsTemplateMatch* mMatch;
 
60
        Element*         mNext;
 
61
    };
 
62
 
 
63
    nsFixedSizeAllocator& mPool;
 
64
    Element* mHead;
 
65
 
 
66
public:
 
67
    nsTemplateMatchSet(nsFixedSizeAllocator& aPool)
 
68
        : mPool(aPool), mHead(nsnull) { MOZ_COUNT_CTOR(nsTemplateMatchSet); }
 
69
 
 
70
    ~nsTemplateMatchSet();
 
71
 
 
72
    class ConstIterator {
 
73
    protected:
 
74
        friend class nsTemplateMatchSet;
 
75
 
 
76
        Element* mCurrent;
 
77
        
 
78
        ConstIterator(Element* aElement)
 
79
            : mCurrent(aElement) {}
 
80
 
 
81
    public:
 
82
        ConstIterator() : mCurrent(nsnull) {}
 
83
 
 
84
        ConstIterator(const ConstIterator& aIterator)
 
85
            : mCurrent(aIterator.mCurrent) {}
 
86
 
 
87
        ConstIterator&
 
88
        operator=(const ConstIterator& aIterator) {
 
89
            mCurrent = aIterator.mCurrent;
 
90
            return *this; }
 
91
 
 
92
        ConstIterator&
 
93
        operator++() {
 
94
            mCurrent = mCurrent->mNext;
 
95
            return *this; };
 
96
 
 
97
        ConstIterator
 
98
        operator++(int) {
 
99
            ConstIterator tmp(*this);
 
100
            mCurrent = mCurrent->mNext;
 
101
            return tmp; }
 
102
 
 
103
        nsTemplateMatch& operator*() const {
 
104
            return *(mCurrent->mMatch); }
 
105
 
 
106
        nsTemplateMatch* operator->() const {
 
107
            return mCurrent->mMatch; }
 
108
 
 
109
        PRBool
 
110
        operator==(const ConstIterator& aIterator) const {
 
111
            return mCurrent == aIterator.mCurrent; }
 
112
 
 
113
        PRBool
 
114
        operator!=(const ConstIterator& aIterator) const {
 
115
            return !aIterator.operator==(*this); }
 
116
    };
 
117
 
 
118
    ConstIterator First() const { return ConstIterator(mHead); }
 
119
 
 
120
    ConstIterator Last() const { return ConstIterator(nsnull); }
 
121
 
 
122
    void
 
123
    Add(nsTemplateMatch* aMatch) {
 
124
        Element* element = new Element(aMatch);
 
125
        if (element) {
 
126
            aMatch->AddRef();
 
127
            element->mMatch = aMatch;
 
128
            element->mNext = mHead;
 
129
            mHead = element;
 
130
        } }
 
131
};
 
132
 
 
133
/**
 
134
 * A set of references nsTemplateMatch objects.
 
135
 */
 
136
class nsTemplateMatchRefSet
 
137
{
 
138
public:
 
139
    class ConstIterator;
 
140
    friend class ConstIterator;
 
141
 
 
142
    nsTemplateMatchRefSet() {
 
143
        MOZ_COUNT_CTOR(nsTemplateMatchRefSet);
 
144
        Init(); }
 
145
 
 
146
    nsTemplateMatchRefSet(const nsTemplateMatchRefSet& aMatchSet) {
 
147
        MOZ_COUNT_CTOR(nsTemplateMatchRefSet);
 
148
        Init();
 
149
        CopyFrom(aMatchSet); }
 
150
 
 
151
    nsTemplateMatchRefSet&
 
152
    operator=(const nsTemplateMatchRefSet& aMatchSet) {
 
153
        Finish();
 
154
        Init();
 
155
        CopyFrom(aMatchSet);
 
156
        return *this; }
 
157
 
 
158
    ~nsTemplateMatchRefSet() {
 
159
        Finish();
 
160
        MOZ_COUNT_DTOR(nsTemplateMatchRefSet); }
 
161
 
 
162
protected:
 
163
    /**
 
164
     * Initialize the set. Must be called before the set is used, or
 
165
     * after Finish().
 
166
     */
 
167
    void Init();
 
168
 
 
169
    /**
 
170
     * Finish the set, releasing all matches. This must be called to
 
171
     * properly release matches in the set. Yeah, yeah, this sucks.
 
172
     */
 
173
    void Finish();
 
174
 
 
175
    /**
 
176
     * Copy the set's contents from another match set
 
177
     */
 
178
    void CopyFrom(const nsTemplateMatchRefSet& aMatchSet);
 
179
 
 
180
    /**
 
181
     * Helper routine that adds the match to the hashtable
 
182
     */
 
183
    PRBool AddToTable(nsTemplateMatch* aMatch);
 
184
 
 
185
    /**
 
186
     * Hashtable entry; holds weak reference to a match object.
 
187
     *
 
188
     * NOTE: this has to be public for several compilers (see 74725) so
 
189
     *       that ConstIterator's union can have access to Entry.
 
190
     */
 
191
public:
 
192
    struct Entry {
 
193
        friend class ConstIterator;
 
194
 
 
195
        PLDHashEntryHdr  mHdr;
 
196
        nsTemplateMatch* mMatch;
 
197
    };
 
198
protected:
 
199
 
 
200
    enum { kMaxInlineMatches = (sizeof(PLDHashTable) / sizeof(void*)) - 1 };
 
201
 
 
202
    struct InlineMatches;
 
203
    friend struct InlineMatches;
 
204
    union _stor_elements;
 
205
    friend union _stor_elements;
 
206
 
 
207
    /**
 
208
     * If the set is currently
 
209
     */
 
210
    struct InlineMatches {
 
211
        PRUint32         mCount;
 
212
        nsTemplateMatch* mEntries[kMaxInlineMatches];
 
213
    };
 
214
 
 
215
    /**
 
216
     * The set is implemented as a dual datastructure. It is initially
 
217
     * a simple array that holds storage for kMaxInlineMatches
 
218
     * elements. Once that capacity is exceeded, the storage is
 
219
     * re-used for a PLDHashTable header. The hashtable allocates its
 
220
     * entries from the normal malloc() heap.
 
221
     *
 
222
     * the InlineMatches structure is implemented such that its mCount
 
223
     * variable overlaps with the PLDHashTable's `ops' member (which
 
224
     * is a pointer to the hashtable's callback table). On a 32-bit
 
225
     * architecture, we're safe assuming that the value for `ops' will
 
226
     * be larger than kMaxInlineMatches when treated as an unsigned
 
227
     * integer. And we'd have to get pretty unlucky on a 64-bit
 
228
     * system for us to get screwed, I think.
 
229
     *
 
230
     * Instrumentation (#define NSTEMPLATEMATCHSET_METER) shows that
 
231
     * almost all of the match sets contain fewer than seven elements.
 
232
     */
 
233
    union _stor_elements {
 
234
        PLDHashTable  mTable;
 
235
        InlineMatches mInlineMatches;
 
236
    } mStorageElements;
 
237
 
 
238
    static PLDHashTableOps gOps;
 
239
 
 
240
    static PLDHashNumber PR_CALLBACK
 
241
    HashEntry(PLDHashTable* aTable, const void* aKey);
 
242
 
 
243
    static PRBool PR_CALLBACK
 
244
    MatchEntry(PLDHashTable* aTable, const PLDHashEntryHdr* aHdr, const void* aKey);
 
245
 
 
246
public:
 
247
    /**
 
248
     * An iterator that can be used to enumerate the contents of the
 
249
     * set
 
250
     */
 
251
    class ConstIterator {
 
252
    protected:
 
253
        friend class nsTemplateMatchRefSet;
 
254
 
 
255
        void Next();
 
256
        void Prev();
 
257
 
 
258
        ConstIterator(const nsTemplateMatchRefSet* aSet, Entry* aTableEntry)
 
259
            : mSet(aSet), mTableEntry(aTableEntry) {}
 
260
 
 
261
        ConstIterator(const nsTemplateMatchRefSet* aSet, nsTemplateMatch** aInlineEntry)
 
262
            : mSet(aSet), mInlineEntry(aInlineEntry) {}
 
263
 
 
264
        const nsTemplateMatchRefSet* mSet;
 
265
        union {
 
266
            Entry*            mTableEntry;
 
267
            nsTemplateMatch** mInlineEntry;
 
268
        };
 
269
 
 
270
        nsTemplateMatch* get() const {
 
271
            return mSet->mStorageElements.mInlineMatches.mCount > PRUint32(kMaxInlineMatches)
 
272
                ? mTableEntry->mMatch
 
273
                : *mInlineEntry; }
 
274
 
 
275
    public:
 
276
        ConstIterator() : mSet(nsnull), mTableEntry(nsnull) {}
 
277
 
 
278
        ConstIterator(const ConstIterator& aConstIterator)
 
279
            : mSet(aConstIterator.mSet),
 
280
              mTableEntry(aConstIterator.mTableEntry) {}
 
281
 
 
282
        ConstIterator& operator=(const ConstIterator& aConstIterator) {
 
283
            mSet = aConstIterator.mSet;
 
284
            mTableEntry = aConstIterator.mTableEntry;
 
285
            return *this; }
 
286
 
 
287
        ConstIterator& operator++() {
 
288
            Next();
 
289
            return *this; }
 
290
 
 
291
        ConstIterator operator++(int) {
 
292
            ConstIterator result(*this);
 
293
            Next();
 
294
            return result; }
 
295
 
 
296
        ConstIterator& operator--() {
 
297
            Prev();
 
298
            return *this; }
 
299
 
 
300
        ConstIterator operator--(int) {
 
301
            ConstIterator result(*this);
 
302
            Prev();
 
303
            return result; }
 
304
 
 
305
        /*const*/ nsTemplateMatch& operator*() const {
 
306
            return *get(); }
 
307
 
 
308
        /*const*/ nsTemplateMatch* operator->() const {
 
309
            return get(); }
 
310
 
 
311
        PRBool operator==(const ConstIterator& aConstIterator) const;
 
312
 
 
313
        PRBool operator!=(const ConstIterator& aConstIterator) const {
 
314
            return ! aConstIterator.operator==(*this); }
 
315
    };
 
316
 
 
317
    /**
 
318
     * Retrieve an iterator that refers to the first element of the
 
319
     * set
 
320
     */
 
321
    ConstIterator First() const;
 
322
 
 
323
    /**
 
324
     * Retrieve an iterator that refers to ``one past'' the last
 
325
     * element of the set
 
326
     */
 
327
    ConstIterator Last() const;
 
328
 
 
329
    /**
 
330
     * Return PR_TRUE if the set is empty
 
331
     */
 
332
    PRBool Empty() const;
 
333
 
 
334
    /**
 
335
     * Return PR_TRUE if the set contains aMatch
 
336
     */
 
337
    PRBool Contains(const nsTemplateMatch* aMatch) const;
 
338
 
 
339
    /**
 
340
     * Add a match to the set. The set does *not* assume ownership of
 
341
     * the match object: it only holds a weak reference. Duplicate
 
342
     * matches are not added.
 
343
     *
 
344
     * @return PR_TRUE if the match was added to the set; PR_FALSE if it
 
345
     *   already existed (or could not be added for some other reason)
 
346
     */
 
347
    PRBool Add(const nsTemplateMatch* aMatch);
 
348
 
 
349
    /**
 
350
     * Remove a match from the set.
 
351
     * @return PR_TRUE if the match was removed from the set; PR_FALSE
 
352
     *   if the match was not present in the set.
 
353
     */
 
354
    PRBool Remove(const nsTemplateMatch* aMatch);
 
355
};
 
356
 
 
357
#endif // nsTemplateMatchSet_h__