layout/base/FramePropertyTable.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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.
    30  * 
    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.
    34  */
    35 struct FramePropertyDescriptor {
    36   /**
    37    * mDestructor will be called if it's non-null.
    38    */
    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.
    47    */
    48   FramePropertyDestructorWithFrame mDestructorWithFrame;
    49   /**
    50    * mDestructor and mDestructorWithFrame may both be null, in which case
    51    * no value destruction is a no-op.
    52    */
    53 };
    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.
    59  * 
    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.
    65  */
    66 class FramePropertyTable {
    67 public:
    68   FramePropertyTable() : mLastFrame(nullptr), mLastEntry(nullptr)
    69   {
    70   }
    71   ~FramePropertyTable()
    72   {
    73     DeleteAll();
    74   }
    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.
    81    */
    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'.
    93    */
    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'.
   106    */
   107   void* Remove(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty,
   108                bool* aFoundResult = nullptr);
   109   /**
   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.
   114    */
   115   void Delete(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty);
   116   /**
   117    * Remove and destroy all property values for a frame. This requires one
   118    * hashtable lookup (using the frame as the key).
   119    */
   120   void DeleteAllFor(nsIFrame* aFrame);
   121   /**
   122    * Remove and destroy all property values for all frames.
   123    */
   124   void DeleteAll();
   126   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   128 protected:
   129   /**
   130    * Stores a property descriptor/value pair. It can also be used to
   131    * store an nsTArray of PropertyValues.
   132    */
   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()
   140     {
   141       NS_ASSERTION(IsArray(), "Must be array");
   142       return reinterpret_cast<nsTArray<PropertyValue>*>(&mValue);
   143     }
   145     void DestroyValueFor(nsIFrame* aFrame) {
   146       if (mProperty->mDestructor) {
   147         mProperty->mDestructor(mValue);
   148       } else if (mProperty->mDestructorWithFrame) {
   149         mProperty->mDestructorWithFrame(aFrame, mValue);
   150       }
   151     }
   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);
   163       }
   164       return n;
   165     }
   167     const FramePropertyDescriptor* mProperty;
   168     void* mValue;
   169   };
   171   /**
   172    * Used with an array of PropertyValues to allow lookups that compare
   173    * only on the FramePropertyDescriptor.
   174    */
   175   class PropertyComparator {
   176   public:
   177     bool Equals(const PropertyValue& a, const PropertyValue& b) const {
   178       return a.mProperty == b.mProperty;
   179     }
   180     bool Equals(const FramePropertyDescriptor* a, const PropertyValue& b) const {
   181       return a == b.mProperty;
   182     }
   183     bool Equals(const PropertyValue& a, const FramePropertyDescriptor* b) const {
   184       return a.mProperty == b;
   185     }
   186   };
   188   /**
   189    * Our hashtable entry. The key is an nsIFrame*, the value is a
   190    * PropertyValue representing one or more property/value pairs.
   191    */
   192   class Entry : public nsPtrHashKey<nsIFrame>
   193   {
   194   public:
   195     Entry(KeyTypePointer aKey) : nsPtrHashKey<nsIFrame>(aKey) {}
   196     Entry(const Entry &toCopy) :
   197       nsPtrHashKey<nsIFrame>(toCopy), mProp(toCopy.mProp) {}
   199     PropertyValue mProp;
   200   };
   202   static void DeleteAllForEntry(Entry* aEntry);
   203   static PLDHashOperator DeleteEnumerator(Entry* aEntry, void* aArg);
   205   static size_t SizeOfPropertyTableEntryExcludingThis(Entry* aEntry,
   206                   mozilla::MallocSizeOf aMallocSizeOf, void *);
   208   nsTHashtable<Entry> mEntries;
   209   nsIFrame* mLastFrame;
   210   Entry* mLastEntry;
   211 };
   213 /**
   214  * This class encapsulates the properties of a frame.
   215  */
   216 class FrameProperties {
   217 public:
   218   FrameProperties(FramePropertyTable* aTable, nsIFrame* aFrame)
   219     : mTable(aTable), mFrame(aFrame) {}
   220   FrameProperties(FramePropertyTable* aTable, const nsIFrame* aFrame)
   221     : mTable(aTable), mFrame(const_cast<nsIFrame*>(aFrame)) {}
   223   void Set(const FramePropertyDescriptor* aProperty, void* aValue) const
   224   {
   225     mTable->Set(mFrame, aProperty, aValue);
   226   }
   227   void* Get(const FramePropertyDescriptor* aProperty,
   228             bool* aFoundResult = nullptr) const
   229   {
   230     return mTable->Get(mFrame, aProperty, aFoundResult);
   231   }
   232   void* Remove(const FramePropertyDescriptor* aProperty,
   233                bool* aFoundResult = nullptr) const
   234   {
   235     return mTable->Remove(mFrame, aProperty, aFoundResult);
   236   }
   237   void Delete(const FramePropertyDescriptor* aProperty)
   238   {
   239     mTable->Delete(mFrame, aProperty);
   240   }
   242 private:
   243   FramePropertyTable* mTable;
   244   nsIFrame* mFrame;
   245 };
   247 }
   249 #endif /* FRAMEPROPERTYTABLE_H_ */

mercurial