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. nsIDOMSVGLength). 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 {
25 public:
26 #ifdef DEBUG
~nsSVGAttrTearoffTable()27   ~nsSVGAttrTearoffTable()
28   {
29     MOZ_ASSERT(!mTable, "Tear-off objects remain in hashtable at shutdown.");
30   }
31 #endif
32 
33   TearoffType* GetTearoff(SimpleType* aSimple);
34 
35   void AddTearoff(SimpleType* aSimple, TearoffType* aTearoff);
36 
37   void RemoveTearoff(SimpleType* aSimple);
38 
39 private:
40   typedef nsPtrHashKey<SimpleType> SimpleTypePtrKey;
41   typedef nsDataHashtable<SimpleTypePtrKey, TearoffType* > TearoffTable;
42 
43   TearoffTable* mTable;
44 };
45 
46 template<class SimpleType, class TearoffType>
47 TearoffType*
GetTearoff(SimpleType * aSimple)48 nsSVGAttrTearoffTable<SimpleType, TearoffType>::GetTearoff(SimpleType* aSimple)
49 {
50   if (!mTable)
51     return nullptr;
52 
53   TearoffType *tearoff = nullptr;
54 
55 #ifdef DEBUG
56   bool found =
57 #endif
58     mTable->Get(aSimple, &tearoff);
59   MOZ_ASSERT(!found || tearoff,
60              "null pointer stored in attribute tear-off map");
61 
62   return tearoff;
63 }
64 
65 template<class SimpleType, class TearoffType>
66 void
AddTearoff(SimpleType * aSimple,TearoffType * aTearoff)67 nsSVGAttrTearoffTable<SimpleType, TearoffType>::AddTearoff(SimpleType* aSimple,
68                                                           TearoffType* aTearoff)
69 {
70   if (!mTable) {
71     mTable = new TearoffTable;
72   }
73 
74   // We shouldn't be adding a tear-off if there already is one. If that happens,
75   // something is wrong.
76   if (mTable->Get(aSimple, nullptr)) {
77     MOZ_ASSERT(false, "There is already a tear-off for this object.");
78     return;
79   }
80 
81   mTable->Put(aSimple, aTearoff);
82 }
83 
84 template<class SimpleType, class TearoffType>
85 void
RemoveTearoff(SimpleType * aSimple)86 nsSVGAttrTearoffTable<SimpleType, TearoffType>::RemoveTearoff(
87     SimpleType* aSimple)
88 {
89   if (!mTable) {
90     // Perhaps something happened in between creating the SimpleType object and
91     // registering it
92     return;
93   }
94 
95   mTable->Remove(aSimple);
96   if (mTable->Count() == 0) {
97     delete mTable;
98     mTable = nullptr;
99   }
100 }
101 
102 #endif // NS_SVGATTRTEAROFFTABLE_H_
103