Bumping manifests a=b2g-bump
[gecko.git] / layout / base / FramePropertyTable.h
blob739115b35c31290f8312b653163e12429bdc3805
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef FRAMEPROPERTYTABLE_H_
7 #define FRAMEPROPERTYTABLE_H_
9 #include "mozilla/MemoryReporting.h"
10 #include "nsTArray.h"
11 #include "nsTHashtable.h"
12 #include "nsHashKeys.h"
14 class nsIFrame;
16 namespace mozilla {
18 struct FramePropertyDescriptor;
20 typedef void (*FramePropertyDestructor)(void* aPropertyValue);
21 typedef void (*FramePropertyDestructorWithFrame)(nsIFrame* aFrame,
22 void* aPropertyValue);
24 /**
25 * A pointer to a FramePropertyDescriptor serves as a unique property ID.
26 * The FramePropertyDescriptor stores metadata about the property.
27 * Currently the only metadata is a destructor function. The destructor
28 * function is called on property values when they are overwritten or
29 * deleted.
31 * To use this class, declare a global (i.e., file, class or function-scope
32 * static member) FramePropertyDescriptor and pass its address as
33 * aProperty in the FramePropertyTable methods.
35 struct FramePropertyDescriptor {
36 /**
37 * mDestructor will be called if it's non-null.
39 FramePropertyDestructor mDestructor;
40 /**
41 * mDestructorWithFrame will be called if it's non-null and mDestructor
42 * is null. WARNING: The frame passed to mDestructorWithFrame may
43 * be a dangling frame pointer, if this is being called during
44 * presshell teardown. Do not use it except to compare against
45 * other frame pointers. No frame will have been allocated with
46 * the same address yet.
48 FramePropertyDestructorWithFrame mDestructorWithFrame;
49 /**
50 * mDestructor and mDestructorWithFrame may both be null, in which case
51 * no value destruction is a no-op.
55 /**
56 * The FramePropertyTable is optimized for storing 0 or 1 properties on
57 * a given frame. Storing very large numbers of properties on a single
58 * frame will not be efficient.
60 * Property values are passed as void* but do not actually have to be
61 * valid pointers. You can use NS_INT32_TO_PTR/NS_PTR_TO_INT32 to
62 * store int32_t values. Null/zero values can be stored and retrieved.
63 * Of course, the destructor function (if any) must handle such values
64 * correctly.
66 class FramePropertyTable {
67 public:
68 FramePropertyTable() : mLastFrame(nullptr), mLastEntry(nullptr)
71 ~FramePropertyTable()
73 DeleteAll();
76 /**
77 * Set a property value on a frame. This requires one hashtable
78 * lookup (using the frame as the key) and a linear search through
79 * the properties of that frame. Any existing value for the property
80 * is destroyed.
82 void Set(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty,
83 void* aValue);
84 /**
85 * Get a property value for a frame. This requires one hashtable
86 * lookup (using the frame as the key) and a linear search through
87 * the properties of that frame. If the frame has no such property,
88 * returns null.
89 * @param aFoundResult if non-null, receives a value 'true' iff
90 * the frame has a value for the property. This lets callers
91 * disambiguate a null result, which can mean 'no such property' or
92 * 'property value is null'.
94 void* Get(const nsIFrame* aFrame, const FramePropertyDescriptor* aProperty,
95 bool* aFoundResult = nullptr);
96 /**
97 * Remove a property value for a frame. This requires one hashtable
98 * lookup (using the frame as the key) and a linear search through
99 * the properties of that frame. The old property value is returned
100 * (and not destroyed). If the frame has no such property,
101 * returns null.
102 * @param aFoundResult if non-null, receives a value 'true' iff
103 * the frame had a value for the property. This lets callers
104 * disambiguate a null result, which can mean 'no such property' or
105 * 'property value is null'.
107 void* Remove(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty,
108 bool* aFoundResult = nullptr);
110 * Remove and destroy a property value for a frame. This requires one
111 * hashtable lookup (using the frame as the key) and a linear search
112 * through the properties of that frame. If the frame has no such
113 * property, nothing happens.
115 void Delete(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty);
117 * Remove and destroy all property values for a frame. This requires one
118 * hashtable lookup (using the frame as the key).
120 void DeleteAllFor(nsIFrame* aFrame);
122 * Remove and destroy all property values for all frames.
124 void DeleteAll();
126 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
128 protected:
130 * Stores a property descriptor/value pair. It can also be used to
131 * store an nsTArray of PropertyValues.
133 struct PropertyValue {
134 PropertyValue() : mProperty(nullptr), mValue(nullptr) {}
135 PropertyValue(const FramePropertyDescriptor* aProperty, void* aValue)
136 : mProperty(aProperty), mValue(aValue) {}
138 bool IsArray() { return !mProperty && mValue; }
139 nsTArray<PropertyValue>* ToArray()
141 NS_ASSERTION(IsArray(), "Must be array");
142 return reinterpret_cast<nsTArray<PropertyValue>*>(&mValue);
145 void DestroyValueFor(nsIFrame* aFrame) {
146 if (mProperty->mDestructor) {
147 mProperty->mDestructor(mValue);
148 } else if (mProperty->mDestructorWithFrame) {
149 mProperty->mDestructorWithFrame(aFrame, mValue);
153 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) {
154 size_t n = 0;
155 // We don't need to measure mProperty because it always points to static
156 // memory. As for mValue: if it's a single value we can't measure it,
157 // because the type is opaque; if it's an array, we measure the array
158 // storage, but we can't measure the individual values, again because
159 // their types are opaque.
160 if (IsArray()) {
161 nsTArray<PropertyValue>* array = ToArray();
162 n += array->SizeOfExcludingThis(aMallocSizeOf);
164 return n;
167 const FramePropertyDescriptor* mProperty;
168 void* mValue;
172 * Used with an array of PropertyValues to allow lookups that compare
173 * only on the FramePropertyDescriptor.
175 class PropertyComparator {
176 public:
177 bool Equals(const PropertyValue& a, const PropertyValue& b) const {
178 return a.mProperty == b.mProperty;
180 bool Equals(const FramePropertyDescriptor* a, const PropertyValue& b) const {
181 return a == b.mProperty;
183 bool Equals(const PropertyValue& a, const FramePropertyDescriptor* b) const {
184 return a.mProperty == b;
189 * Our hashtable entry. The key is an nsIFrame*, the value is a
190 * PropertyValue representing one or more property/value pairs.
192 class Entry : public nsPtrHashKey<nsIFrame>
194 public:
195 explicit Entry(KeyTypePointer aKey) : nsPtrHashKey<nsIFrame>(aKey) {}
196 Entry(const Entry &toCopy) :
197 nsPtrHashKey<nsIFrame>(toCopy), mProp(toCopy.mProp) {}
199 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) {
200 return mProp.SizeOfExcludingThis(aMallocSizeOf);
203 PropertyValue mProp;
206 static void DeleteAllForEntry(Entry* aEntry);
207 static PLDHashOperator DeleteEnumerator(Entry* aEntry, void* aArg);
209 nsTHashtable<Entry> mEntries;
210 nsIFrame* mLastFrame;
211 Entry* mLastEntry;
215 * This class encapsulates the properties of a frame.
217 class FrameProperties {
218 public:
219 FrameProperties(FramePropertyTable* aTable, nsIFrame* aFrame)
220 : mTable(aTable), mFrame(aFrame) {}
221 FrameProperties(FramePropertyTable* aTable, const nsIFrame* aFrame)
222 : mTable(aTable), mFrame(const_cast<nsIFrame*>(aFrame)) {}
224 void Set(const FramePropertyDescriptor* aProperty, void* aValue) const
226 mTable->Set(mFrame, aProperty, aValue);
228 void* Get(const FramePropertyDescriptor* aProperty,
229 bool* aFoundResult = nullptr) const
231 return mTable->Get(mFrame, aProperty, aFoundResult);
233 void* Remove(const FramePropertyDescriptor* aProperty,
234 bool* aFoundResult = nullptr) const
236 return mTable->Remove(mFrame, aProperty, aFoundResult);
238 void Delete(const FramePropertyDescriptor* aProperty)
240 mTable->Delete(mFrame, aProperty);
243 private:
244 FramePropertyTable* mTable;
245 nsIFrame* mFrame;
250 #endif /* FRAMEPROPERTYTABLE_H_ */