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/. */
6 
7 #ifndef NS_SVGATTRTEAROFFTABLE_H_
8 #define NS_SVGATTRTEAROFFTABLE_H_
9 
10 #include "nsDataHashtable.h"
11 #include "nsDebug.h"
12 #include "nsHashKeys.h"
13 
14 /**
15  * Global hashmap to associate internal SVG data types (e.g. nsSVGLength2) with
16  * DOM tear-off objects (e.g. DOMSVGLength). This allows us to always return
17  * the same object for subsequent requests for DOM objects.
18  *
19  * We don't keep an owning reference to the tear-off objects so they are
20  * responsible for removing themselves from this table when they die.
21  */
22 template <class SimpleType, class TearoffType>
23 class nsSVGAttrTearoffTable {
24  public:
25 #ifdef DEBUG
~nsSVGAttrTearoffTable()26   ~nsSVGAttrTearoffTable() {
27     MOZ_ASSERT(!mTable, "Tear-off objects remain in hashtable at shutdown.");
28   }
29 #endif
30 
31   TearoffType* GetTearoff(SimpleType* aSimple);
32 
33   void AddTearoff(SimpleType* aSimple, TearoffType* aTearoff);
34 
35   void RemoveTearoff(SimpleType* aSimple);
36 
37  private:
38   typedef nsPtrHashKey<SimpleType> SimpleTypePtrKey;
39   typedef nsDataHashtable<SimpleTypePtrKey, TearoffType*> TearoffTable;
40 
41   TearoffTable* mTable;
42 };
43 
44 template <class SimpleType, class TearoffType>
GetTearoff(SimpleType * aSimple)45 TearoffType* nsSVGAttrTearoffTable<SimpleType, TearoffType>::GetTearoff(
46     SimpleType* aSimple) {
47   if (!mTable) return nullptr;
48 
49   TearoffType* tearoff = nullptr;
50 
51 #ifdef DEBUG
52   bool found =
53 #endif
54       mTable->Get(aSimple, &tearoff);
55   MOZ_ASSERT(!found || tearoff,
56              "null pointer stored in attribute tear-off map");
57 
58   return tearoff;
59 }
60 
61 template <class SimpleType, class TearoffType>
AddTearoff(SimpleType * aSimple,TearoffType * aTearoff)62 void nsSVGAttrTearoffTable<SimpleType, TearoffType>::AddTearoff(
63     SimpleType* aSimple, TearoffType* aTearoff) {
64   if (!mTable) {
65     mTable = new TearoffTable;
66   }
67 
68   // We shouldn't be adding a tear-off if there already is one. If that happens,
69   // something is wrong.
70   if (mTable->Get(aSimple, nullptr)) {
71     MOZ_ASSERT(false, "There is already a tear-off for this object.");
72     return;
73   }
74 
75   mTable->Put(aSimple, aTearoff);
76 }
77 
78 template <class SimpleType, class TearoffType>
RemoveTearoff(SimpleType * aSimple)79 void nsSVGAttrTearoffTable<SimpleType, TearoffType>::RemoveTearoff(
80     SimpleType* aSimple) {
81   if (!mTable) {
82     // Perhaps something happened in between creating the SimpleType object and
83     // registering it
84     return;
85   }
86 
87   mTable->Remove(aSimple);
88   if (mTable->Count() == 0) {
89     delete mTable;
90     mTable = nullptr;
91   }
92 }
93 
94 #endif  // NS_SVGATTRTEAROFFTABLE_H_
95