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
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/
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
15
* The Original Code is Mozilla Communicator client code.
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.
23
* Chris Waterson <waterson@netscape.com>
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.
38
* ***** END LICENSE BLOCK ***** */
40
#ifndef nsTemplateMatchSet_h__
41
#define nsTemplateMatchSet_h__
43
#include "nsRuleNetwork.h"
44
#include "nsFixedSizeAllocator.h"
45
#include "nsTemplateMatch.h"
48
class nsTemplateMatchSet {
51
friend class ConstIterator; // so it can see Element
56
Element(nsTemplateMatch* aMatch)
57
: mMatch(aMatch), mNext(nsnull) {}
59
nsTemplateMatch* mMatch;
63
nsFixedSizeAllocator& mPool;
67
nsTemplateMatchSet(nsFixedSizeAllocator& aPool)
68
: mPool(aPool), mHead(nsnull) { MOZ_COUNT_CTOR(nsTemplateMatchSet); }
70
~nsTemplateMatchSet();
74
friend class nsTemplateMatchSet;
78
ConstIterator(Element* aElement)
79
: mCurrent(aElement) {}
82
ConstIterator() : mCurrent(nsnull) {}
84
ConstIterator(const ConstIterator& aIterator)
85
: mCurrent(aIterator.mCurrent) {}
88
operator=(const ConstIterator& aIterator) {
89
mCurrent = aIterator.mCurrent;
94
mCurrent = mCurrent->mNext;
99
ConstIterator tmp(*this);
100
mCurrent = mCurrent->mNext;
103
nsTemplateMatch& operator*() const {
104
return *(mCurrent->mMatch); }
106
nsTemplateMatch* operator->() const {
107
return mCurrent->mMatch; }
110
operator==(const ConstIterator& aIterator) const {
111
return mCurrent == aIterator.mCurrent; }
114
operator!=(const ConstIterator& aIterator) const {
115
return !aIterator.operator==(*this); }
118
ConstIterator First() const { return ConstIterator(mHead); }
120
ConstIterator Last() const { return ConstIterator(nsnull); }
123
Add(nsTemplateMatch* aMatch) {
124
Element* element = new Element(aMatch);
127
element->mMatch = aMatch;
128
element->mNext = mHead;
134
* A set of references nsTemplateMatch objects.
136
class nsTemplateMatchRefSet
140
friend class ConstIterator;
142
nsTemplateMatchRefSet() {
143
MOZ_COUNT_CTOR(nsTemplateMatchRefSet);
146
nsTemplateMatchRefSet(const nsTemplateMatchRefSet& aMatchSet) {
147
MOZ_COUNT_CTOR(nsTemplateMatchRefSet);
149
CopyFrom(aMatchSet); }
151
nsTemplateMatchRefSet&
152
operator=(const nsTemplateMatchRefSet& aMatchSet) {
158
~nsTemplateMatchRefSet() {
160
MOZ_COUNT_DTOR(nsTemplateMatchRefSet); }
164
* Initialize the set. Must be called before the set is used, or
170
* Finish the set, releasing all matches. This must be called to
171
* properly release matches in the set. Yeah, yeah, this sucks.
176
* Copy the set's contents from another match set
178
void CopyFrom(const nsTemplateMatchRefSet& aMatchSet);
181
* Helper routine that adds the match to the hashtable
183
PRBool AddToTable(nsTemplateMatch* aMatch);
186
* Hashtable entry; holds weak reference to a match object.
188
* NOTE: this has to be public for several compilers (see 74725) so
189
* that ConstIterator's union can have access to Entry.
193
friend class ConstIterator;
195
PLDHashEntryHdr mHdr;
196
nsTemplateMatch* mMatch;
200
enum { kMaxInlineMatches = (sizeof(PLDHashTable) / sizeof(void*)) - 1 };
202
struct InlineMatches;
203
friend struct InlineMatches;
204
union _stor_elements;
205
friend union _stor_elements;
208
* If the set is currently
210
struct InlineMatches {
212
nsTemplateMatch* mEntries[kMaxInlineMatches];
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.
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.
230
* Instrumentation (#define NSTEMPLATEMATCHSET_METER) shows that
231
* almost all of the match sets contain fewer than seven elements.
233
union _stor_elements {
235
InlineMatches mInlineMatches;
238
static PLDHashTableOps gOps;
240
static PLDHashNumber PR_CALLBACK
241
HashEntry(PLDHashTable* aTable, const void* aKey);
243
static PRBool PR_CALLBACK
244
MatchEntry(PLDHashTable* aTable, const PLDHashEntryHdr* aHdr, const void* aKey);
248
* An iterator that can be used to enumerate the contents of the
251
class ConstIterator {
253
friend class nsTemplateMatchRefSet;
258
ConstIterator(const nsTemplateMatchRefSet* aSet, Entry* aTableEntry)
259
: mSet(aSet), mTableEntry(aTableEntry) {}
261
ConstIterator(const nsTemplateMatchRefSet* aSet, nsTemplateMatch** aInlineEntry)
262
: mSet(aSet), mInlineEntry(aInlineEntry) {}
264
const nsTemplateMatchRefSet* mSet;
267
nsTemplateMatch** mInlineEntry;
270
nsTemplateMatch* get() const {
271
return mSet->mStorageElements.mInlineMatches.mCount > PRUint32(kMaxInlineMatches)
272
? mTableEntry->mMatch
276
ConstIterator() : mSet(nsnull), mTableEntry(nsnull) {}
278
ConstIterator(const ConstIterator& aConstIterator)
279
: mSet(aConstIterator.mSet),
280
mTableEntry(aConstIterator.mTableEntry) {}
282
ConstIterator& operator=(const ConstIterator& aConstIterator) {
283
mSet = aConstIterator.mSet;
284
mTableEntry = aConstIterator.mTableEntry;
287
ConstIterator& operator++() {
291
ConstIterator operator++(int) {
292
ConstIterator result(*this);
296
ConstIterator& operator--() {
300
ConstIterator operator--(int) {
301
ConstIterator result(*this);
305
/*const*/ nsTemplateMatch& operator*() const {
308
/*const*/ nsTemplateMatch* operator->() const {
311
PRBool operator==(const ConstIterator& aConstIterator) const;
313
PRBool operator!=(const ConstIterator& aConstIterator) const {
314
return ! aConstIterator.operator==(*this); }
318
* Retrieve an iterator that refers to the first element of the
321
ConstIterator First() const;
324
* Retrieve an iterator that refers to ``one past'' the last
327
ConstIterator Last() const;
330
* Return PR_TRUE if the set is empty
332
PRBool Empty() const;
335
* Return PR_TRUE if the set contains aMatch
337
PRBool Contains(const nsTemplateMatch* aMatch) const;
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.
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)
347
PRBool Add(const nsTemplateMatch* aMatch);
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.
354
PRBool Remove(const nsTemplateMatch* aMatch);
357
#endif // nsTemplateMatchSet_h__