1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
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 Corporation code.
17 * The Initial Developer of the Original Code is Mozilla Foundation.
18 * Portions created by the Initial Developer are Copyright (C) 2010
19 * the Initial Developer. All Rights Reserved.
22 * Robert O'Callahan <robert@ocallahan.org>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "FramePropertyTable.h"
44 FramePropertyTable::Set(nsIFrame
* aFrame
, const FramePropertyDescriptor
* aProperty
,
47 NS_ASSERTION(aFrame
, "Null frame?");
48 NS_ASSERTION(aProperty
, "Null property?");
50 if (mLastFrame
!= aFrame
|| !mLastEntry
) {
52 mLastEntry
= mEntries
.PutEntry(aFrame
);
54 Entry
* entry
= mLastEntry
;
56 if (!entry
->mProp
.IsArray()) {
57 if (!entry
->mProp
.mProperty
) {
58 // Empty entry, so we can just store our property in the empty slot
59 entry
->mProp
.mProperty
= aProperty
;
60 entry
->mProp
.mValue
= aValue
;
63 if (entry
->mProp
.mProperty
== aProperty
) {
64 // Just overwrite the current value
65 entry
->mProp
.DestroyValueFor(aFrame
);
66 entry
->mProp
.mValue
= aValue
;
70 // We need to expand the single current entry to an array
71 PropertyValue current
= entry
->mProp
;
72 entry
->mProp
.mProperty
= nsnull
;
73 PR_STATIC_ASSERT(sizeof(nsTArray
<PropertyValue
>) <= sizeof(void *));
74 new (&entry
->mProp
.mValue
) nsTArray
<PropertyValue
>(4);
75 entry
->mProp
.ToArray()->AppendElement(current
);
78 nsTArray
<PropertyValue
>* array
= entry
->mProp
.ToArray();
79 nsTArray
<PropertyValue
>::index_type index
=
80 array
->IndexOf(aProperty
, 0, PropertyComparator());
81 if (index
!= nsTArray
<PropertyValue
>::NoIndex
) {
82 PropertyValue
* pv
= &array
->ElementAt(index
);
83 pv
->DestroyValueFor(aFrame
);
88 array
->AppendElement(PropertyValue(aProperty
, aValue
));
92 FramePropertyTable::Get(const nsIFrame
* aFrame
,
93 const FramePropertyDescriptor
* aProperty
,
96 NS_ASSERTION(aFrame
, "Null frame?");
97 NS_ASSERTION(aProperty
, "Null property?");
100 *aFoundResult
= PR_FALSE
;
103 if (mLastFrame
!= aFrame
) {
104 mLastFrame
= const_cast<nsIFrame
*>(aFrame
);
105 mLastEntry
= mEntries
.GetEntry(mLastFrame
);
107 Entry
* entry
= mLastEntry
;
111 if (entry
->mProp
.mProperty
== aProperty
) {
113 *aFoundResult
= PR_TRUE
;
115 return entry
->mProp
.mValue
;
117 if (!entry
->mProp
.IsArray()) {
118 // There's just one property and it's not the one we want, bail
122 nsTArray
<PropertyValue
>* array
= entry
->mProp
.ToArray();
123 nsTArray
<PropertyValue
>::index_type index
=
124 array
->IndexOf(aProperty
, 0, PropertyComparator());
125 if (index
== nsTArray
<PropertyValue
>::NoIndex
)
129 *aFoundResult
= PR_TRUE
;
132 return array
->ElementAt(index
).mValue
;
136 FramePropertyTable::Remove(nsIFrame
* aFrame
, const FramePropertyDescriptor
* aProperty
,
137 PRBool
* aFoundResult
)
139 NS_ASSERTION(aFrame
, "Null frame?");
140 NS_ASSERTION(aProperty
, "Null property?");
143 *aFoundResult
= PR_FALSE
;
146 if (mLastFrame
!= aFrame
) {
148 mLastEntry
= mEntries
.GetEntry(aFrame
);
150 Entry
* entry
= mLastEntry
;
154 if (entry
->mProp
.mProperty
== aProperty
) {
155 // There's only one entry and it's the one we want
156 void* value
= entry
->mProp
.mValue
;
157 mEntries
.RawRemoveEntry(entry
);
160 *aFoundResult
= PR_TRUE
;
164 if (!entry
->mProp
.IsArray()) {
165 // There's just one property and it's not the one we want, bail
169 nsTArray
<PropertyValue
>* array
= entry
->mProp
.ToArray();
170 nsTArray
<PropertyValue
>::index_type index
=
171 array
->IndexOf(aProperty
, 0, PropertyComparator());
172 if (index
== nsTArray
<PropertyValue
>::NoIndex
) {
173 // No such property, bail
178 *aFoundResult
= PR_TRUE
;
181 void* result
= array
->ElementAt(index
).mValue
;
183 PRUint32 last
= array
->Length() - 1;
184 array
->ElementAt(index
) = array
->ElementAt(last
);
185 array
->RemoveElementAt(last
);
188 PropertyValue pv
= array
->ElementAt(0);
189 array
->~nsTArray
<PropertyValue
>();
197 FramePropertyTable::Delete(nsIFrame
* aFrame
, const FramePropertyDescriptor
* aProperty
)
199 NS_ASSERTION(aFrame
, "Null frame?");
200 NS_ASSERTION(aProperty
, "Null property?");
203 void* v
= Remove(aFrame
, aProperty
, &found
);
205 PropertyValue
pv(aProperty
, v
);
206 pv
.DestroyValueFor(aFrame
);
211 FramePropertyTable::DeleteAllForEntry(Entry
* aEntry
)
213 if (!aEntry
->mProp
.IsArray()) {
214 aEntry
->mProp
.DestroyValueFor(aEntry
->GetKey());
218 nsTArray
<PropertyValue
>* array
= aEntry
->mProp
.ToArray();
219 for (PRUint32 i
= 0; i
< array
->Length(); ++i
) {
220 array
->ElementAt(i
).DestroyValueFor(aEntry
->GetKey());
222 array
->~nsTArray
<PropertyValue
>();
226 FramePropertyTable::DeleteAllFor(nsIFrame
* aFrame
)
228 NS_ASSERTION(aFrame
, "Null frame?");
230 Entry
* entry
= mEntries
.GetEntry(aFrame
);
234 if (mLastFrame
== aFrame
) {
235 // Flush cache. We assume DeleteAllForEntry will be called before
236 // a frame is destroyed.
241 DeleteAllForEntry(entry
);
242 mEntries
.RawRemoveEntry(entry
);
245 /* static */ PLDHashOperator
246 FramePropertyTable::DeleteEnumerator(Entry
* aEntry
, void* aArg
)
248 DeleteAllForEntry(aEntry
);
249 return PL_DHASH_REMOVE
;
253 FramePropertyTable::DeleteAll()
258 mEntries
.EnumerateEntries(DeleteEnumerator
, nsnull
);