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
4 : *
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/
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 Corporation code.
16 : *
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.
20 : *
21 : * Contributor(s):
22 : * Robert O'Callahan <robert@ocallahan.org>
23 : *
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.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "FramePropertyTable.h"
39 : #include "prlog.h"
40 :
41 : namespace mozilla {
42 :
43 : void
44 0 : FramePropertyTable::Set(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty,
45 : void* aValue)
46 : {
47 0 : NS_ASSERTION(aFrame, "Null frame?");
48 0 : NS_ASSERTION(aProperty, "Null property?");
49 :
50 0 : if (mLastFrame != aFrame || !mLastEntry) {
51 0 : mLastFrame = aFrame;
52 0 : mLastEntry = mEntries.PutEntry(aFrame);
53 : }
54 0 : Entry* entry = mLastEntry;
55 :
56 0 : if (!entry->mProp.IsArray()) {
57 0 : if (!entry->mProp.mProperty) {
58 : // Empty entry, so we can just store our property in the empty slot
59 0 : entry->mProp.mProperty = aProperty;
60 0 : entry->mProp.mValue = aValue;
61 0 : return;
62 : }
63 0 : if (entry->mProp.mProperty == aProperty) {
64 : // Just overwrite the current value
65 0 : entry->mProp.DestroyValueFor(aFrame);
66 0 : entry->mProp.mValue = aValue;
67 0 : return;
68 : }
69 :
70 : // We need to expand the single current entry to an array
71 0 : PropertyValue current = entry->mProp;
72 0 : entry->mProp.mProperty = nsnull;
73 : PR_STATIC_ASSERT(sizeof(nsTArray<PropertyValue>) <= sizeof(void *));
74 0 : new (&entry->mProp.mValue) nsTArray<PropertyValue>(4);
75 0 : entry->mProp.ToArray()->AppendElement(current);
76 : }
77 :
78 0 : nsTArray<PropertyValue>* array = entry->mProp.ToArray();
79 : nsTArray<PropertyValue>::index_type index =
80 0 : array->IndexOf(aProperty, 0, PropertyComparator());
81 0 : if (index != nsTArray<PropertyValue>::NoIndex) {
82 0 : PropertyValue* pv = &array->ElementAt(index);
83 0 : pv->DestroyValueFor(aFrame);
84 0 : pv->mValue = aValue;
85 0 : return;
86 : }
87 :
88 0 : array->AppendElement(PropertyValue(aProperty, aValue));
89 : }
90 :
91 : void*
92 0 : FramePropertyTable::Get(const nsIFrame* aFrame,
93 : const FramePropertyDescriptor* aProperty,
94 : bool* aFoundResult)
95 : {
96 0 : NS_ASSERTION(aFrame, "Null frame?");
97 0 : NS_ASSERTION(aProperty, "Null property?");
98 :
99 0 : if (aFoundResult) {
100 0 : *aFoundResult = false;
101 : }
102 :
103 0 : if (mLastFrame != aFrame) {
104 0 : mLastFrame = const_cast<nsIFrame*>(aFrame);
105 0 : mLastEntry = mEntries.GetEntry(mLastFrame);
106 : }
107 0 : Entry* entry = mLastEntry;
108 0 : if (!entry)
109 0 : return nsnull;
110 :
111 0 : if (entry->mProp.mProperty == aProperty) {
112 0 : if (aFoundResult) {
113 0 : *aFoundResult = true;
114 : }
115 0 : return entry->mProp.mValue;
116 : }
117 0 : if (!entry->mProp.IsArray()) {
118 : // There's just one property and it's not the one we want, bail
119 0 : return nsnull;
120 : }
121 :
122 0 : nsTArray<PropertyValue>* array = entry->mProp.ToArray();
123 : nsTArray<PropertyValue>::index_type index =
124 0 : array->IndexOf(aProperty, 0, PropertyComparator());
125 0 : if (index == nsTArray<PropertyValue>::NoIndex)
126 0 : return nsnull;
127 :
128 0 : if (aFoundResult) {
129 0 : *aFoundResult = true;
130 : }
131 :
132 0 : return array->ElementAt(index).mValue;
133 : }
134 :
135 : void*
136 0 : FramePropertyTable::Remove(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty,
137 : bool* aFoundResult)
138 : {
139 0 : NS_ASSERTION(aFrame, "Null frame?");
140 0 : NS_ASSERTION(aProperty, "Null property?");
141 :
142 0 : if (aFoundResult) {
143 0 : *aFoundResult = false;
144 : }
145 :
146 0 : if (mLastFrame != aFrame) {
147 0 : mLastFrame = aFrame;
148 0 : mLastEntry = mEntries.GetEntry(aFrame);
149 : }
150 0 : Entry* entry = mLastEntry;
151 0 : if (!entry)
152 0 : return nsnull;
153 :
154 0 : if (entry->mProp.mProperty == aProperty) {
155 : // There's only one entry and it's the one we want
156 0 : void* value = entry->mProp.mValue;
157 0 : mEntries.RawRemoveEntry(entry);
158 0 : mLastEntry = nsnull;
159 0 : if (aFoundResult) {
160 0 : *aFoundResult = true;
161 : }
162 0 : return value;
163 : }
164 0 : if (!entry->mProp.IsArray()) {
165 : // There's just one property and it's not the one we want, bail
166 0 : return nsnull;
167 : }
168 :
169 0 : nsTArray<PropertyValue>* array = entry->mProp.ToArray();
170 : nsTArray<PropertyValue>::index_type index =
171 0 : array->IndexOf(aProperty, 0, PropertyComparator());
172 0 : if (index == nsTArray<PropertyValue>::NoIndex) {
173 : // No such property, bail
174 0 : return nsnull;
175 : }
176 :
177 0 : if (aFoundResult) {
178 0 : *aFoundResult = true;
179 : }
180 :
181 0 : void* result = array->ElementAt(index).mValue;
182 :
183 0 : PRUint32 last = array->Length() - 1;
184 0 : array->ElementAt(index) = array->ElementAt(last);
185 0 : array->RemoveElementAt(last);
186 :
187 0 : if (last == 1) {
188 0 : PropertyValue pv = array->ElementAt(0);
189 0 : array->~nsTArray<PropertyValue>();
190 0 : entry->mProp = pv;
191 : }
192 :
193 0 : return result;
194 : }
195 :
196 : void
197 0 : FramePropertyTable::Delete(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty)
198 : {
199 0 : NS_ASSERTION(aFrame, "Null frame?");
200 0 : NS_ASSERTION(aProperty, "Null property?");
201 :
202 : bool found;
203 0 : void* v = Remove(aFrame, aProperty, &found);
204 0 : if (found) {
205 0 : PropertyValue pv(aProperty, v);
206 0 : pv.DestroyValueFor(aFrame);
207 : }
208 0 : }
209 :
210 : /* static */ void
211 0 : FramePropertyTable::DeleteAllForEntry(Entry* aEntry)
212 : {
213 0 : if (!aEntry->mProp.IsArray()) {
214 0 : aEntry->mProp.DestroyValueFor(aEntry->GetKey());
215 0 : return;
216 : }
217 :
218 0 : nsTArray<PropertyValue>* array = aEntry->mProp.ToArray();
219 0 : for (PRUint32 i = 0; i < array->Length(); ++i) {
220 0 : array->ElementAt(i).DestroyValueFor(aEntry->GetKey());
221 : }
222 0 : array->~nsTArray<PropertyValue>();
223 : }
224 :
225 : void
226 0 : FramePropertyTable::DeleteAllFor(nsIFrame* aFrame)
227 : {
228 0 : NS_ASSERTION(aFrame, "Null frame?");
229 :
230 0 : Entry* entry = mEntries.GetEntry(aFrame);
231 0 : if (!entry)
232 0 : return;
233 :
234 0 : if (mLastFrame == aFrame) {
235 : // Flush cache. We assume DeleteAllForEntry will be called before
236 : // a frame is destroyed.
237 0 : mLastFrame = nsnull;
238 0 : mLastEntry = nsnull;
239 : }
240 :
241 0 : DeleteAllForEntry(entry);
242 0 : mEntries.RawRemoveEntry(entry);
243 : }
244 :
245 : /* static */ PLDHashOperator
246 0 : FramePropertyTable::DeleteEnumerator(Entry* aEntry, void* aArg)
247 : {
248 0 : DeleteAllForEntry(aEntry);
249 0 : return PL_DHASH_REMOVE;
250 : }
251 :
252 : void
253 0 : FramePropertyTable::DeleteAll()
254 : {
255 0 : mLastFrame = nsnull;
256 0 : mLastEntry = nsnull;
257 :
258 0 : mEntries.EnumerateEntries(DeleteEnumerator, nsnull);
259 0 : }
260 :
261 : size_t
262 0 : FramePropertyTable::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
263 : {
264 : return mEntries.SizeOfExcludingThis(SizeOfPropertyTableEntryExcludingThis,
265 0 : aMallocSizeOf);
266 : }
267 :
268 : /* static */ size_t
269 0 : FramePropertyTable::SizeOfPropertyTableEntryExcludingThis(Entry* aEntry,
270 : nsMallocSizeOfFun aMallocSizeOf, void *)
271 : {
272 0 : return aEntry->mProp.SizeOfExcludingThis(aMallocSizeOf);
273 : }
274 :
275 : }
|