1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef __nsCheapSets_h__
8 #define __nsCheapSets_h__
10 #include "nsTHashtable.h"
13 enum nsCheapSetOperator
{
14 OpNext
= 0, // enumerator says continue
15 OpRemove
= 1, // enumerator says remove and continue
19 * A set that takes up minimal size when there are 0 or 1 entries in the set.
20 * Use for cases where sizes of 0 and 1 are even slightly common.
22 template <typename EntryType
>
25 typedef typename
EntryType::KeyType KeyType
;
26 typedef nsCheapSetOperator (*Enumerator
)(EntryType
* aEntry
, void* userArg
);
28 nsCheapSet() : mState(ZERO
) { mUnion
.table
= nullptr; }
29 ~nsCheapSet() { Clear(); }
39 GetSingleEntry()->~EntryType();
45 MOZ_ASSERT_UNREACHABLE("bogus state");
51 void Put(const KeyType aVal
);
53 void Remove(const KeyType aVal
);
55 bool Contains(const KeyType aVal
) {
60 return GetSingleEntry()->KeyEquals(EntryType::KeyToPointer(aVal
));
62 return !!mUnion
.table
->GetEntry(aVal
);
64 MOZ_ASSERT_UNREACHABLE("bogus state");
69 uint32_t EnumerateEntries(Enumerator aEnumFunc
, void* aUserArg
) {
74 if (aEnumFunc(GetSingleEntry(), aUserArg
) == OpRemove
) {
75 GetSingleEntry()->~EntryType();
80 uint32_t n
= mUnion
.table
->Count();
81 for (auto iter
= mUnion
.table
->Iter(); !iter
.Done(); iter
.Next()) {
82 auto entry
= static_cast<EntryType
*>(iter
.Get());
83 if (aEnumFunc(entry
, aUserArg
) == OpRemove
) {
90 MOZ_ASSERT_UNREACHABLE("bogus state");
96 EntryType
* GetSingleEntry() {
97 return reinterpret_cast<EntryType
*>(&mUnion
.singleEntry
[0]);
100 enum SetState
{ ZERO
, ONE
, MANY
};
103 nsTHashtable
<EntryType
>* table
;
104 char singleEntry
[sizeof(EntryType
)];
106 enum SetState mState
;
109 template <typename EntryType
>
110 void nsCheapSet
<EntryType
>::Put(const KeyType aVal
) {
113 new (GetSingleEntry()) EntryType(EntryType::KeyToPointer(aVal
));
117 nsTHashtable
<EntryType
>* table
= new nsTHashtable
<EntryType
>();
118 EntryType
* entry
= GetSingleEntry();
119 table
->PutEntry(entry
->GetKey());
121 mUnion
.table
= table
;
127 mUnion
.table
->PutEntry(aVal
);
130 MOZ_ASSERT_UNREACHABLE("bogus state");
135 template <typename EntryType
>
136 void nsCheapSet
<EntryType
>::Remove(const KeyType aVal
) {
141 if (Contains(aVal
)) {
142 GetSingleEntry()->~EntryType();
147 mUnion
.table
->RemoveEntry(aVal
);
150 MOZ_ASSERT_UNREACHABLE("bogus state");