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