|
1 /* -*- Mode: C++; tab-width: 2; 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/. */ |
|
5 |
|
6 /* |
|
7 * Class that represents the name (nodeinfo or atom) of an attribute; |
|
8 * using nodeinfos all the time is too slow, so we use atoms when we |
|
9 * can. |
|
10 */ |
|
11 |
|
12 #ifndef nsAttrName_h___ |
|
13 #define nsAttrName_h___ |
|
14 |
|
15 #include "nsINodeInfo.h" |
|
16 #include "nsIAtom.h" |
|
17 #include "nsDOMString.h" |
|
18 |
|
19 #define NS_ATTRNAME_NODEINFO_BIT 1 |
|
20 class nsAttrName |
|
21 { |
|
22 public: |
|
23 nsAttrName(const nsAttrName& aOther) |
|
24 : mBits(aOther.mBits) |
|
25 { |
|
26 AddRefInternalName(); |
|
27 } |
|
28 |
|
29 explicit nsAttrName(nsIAtom* aAtom) |
|
30 : mBits(reinterpret_cast<uintptr_t>(aAtom)) |
|
31 { |
|
32 NS_ASSERTION(aAtom, "null atom-name in nsAttrName"); |
|
33 NS_ADDREF(aAtom); |
|
34 } |
|
35 |
|
36 explicit nsAttrName(nsINodeInfo* aNodeInfo) |
|
37 { |
|
38 NS_ASSERTION(aNodeInfo, "null nodeinfo-name in nsAttrName"); |
|
39 if (aNodeInfo->NamespaceEquals(kNameSpaceID_None)) { |
|
40 mBits = reinterpret_cast<uintptr_t>(aNodeInfo->NameAtom()); |
|
41 NS_ADDREF(aNodeInfo->NameAtom()); |
|
42 } |
|
43 else { |
|
44 mBits = reinterpret_cast<uintptr_t>(aNodeInfo) | |
|
45 NS_ATTRNAME_NODEINFO_BIT; |
|
46 NS_ADDREF(aNodeInfo); |
|
47 } |
|
48 } |
|
49 |
|
50 ~nsAttrName() |
|
51 { |
|
52 ReleaseInternalName(); |
|
53 } |
|
54 |
|
55 void SetTo(nsINodeInfo* aNodeInfo) |
|
56 { |
|
57 NS_ASSERTION(aNodeInfo, "null nodeinfo-name in nsAttrName"); |
|
58 |
|
59 ReleaseInternalName(); |
|
60 if (aNodeInfo->NamespaceEquals(kNameSpaceID_None)) { |
|
61 mBits = reinterpret_cast<uintptr_t>(aNodeInfo->NameAtom()); |
|
62 NS_ADDREF(aNodeInfo->NameAtom()); |
|
63 } |
|
64 else { |
|
65 mBits = reinterpret_cast<uintptr_t>(aNodeInfo) | |
|
66 NS_ATTRNAME_NODEINFO_BIT; |
|
67 NS_ADDREF(aNodeInfo); |
|
68 } |
|
69 } |
|
70 |
|
71 void SetTo(nsIAtom* aAtom) |
|
72 { |
|
73 NS_ASSERTION(aAtom, "null atom-name in nsAttrName"); |
|
74 |
|
75 ReleaseInternalName(); |
|
76 mBits = reinterpret_cast<uintptr_t>(aAtom); |
|
77 NS_ADDREF(aAtom); |
|
78 } |
|
79 |
|
80 bool IsAtom() const |
|
81 { |
|
82 return !(mBits & NS_ATTRNAME_NODEINFO_BIT); |
|
83 } |
|
84 |
|
85 nsINodeInfo* NodeInfo() const |
|
86 { |
|
87 NS_ASSERTION(!IsAtom(), "getting nodeinfo-value of atom-name"); |
|
88 return reinterpret_cast<nsINodeInfo*>(mBits & ~NS_ATTRNAME_NODEINFO_BIT); |
|
89 } |
|
90 |
|
91 nsIAtom* Atom() const |
|
92 { |
|
93 NS_ASSERTION(IsAtom(), "getting atom-value of nodeinfo-name"); |
|
94 return reinterpret_cast<nsIAtom*>(mBits); |
|
95 } |
|
96 |
|
97 bool Equals(const nsAttrName& aOther) const |
|
98 { |
|
99 return mBits == aOther.mBits; |
|
100 } |
|
101 |
|
102 // Faster comparison in the case we know the namespace is null |
|
103 bool Equals(nsIAtom* aAtom) const |
|
104 { |
|
105 return reinterpret_cast<uintptr_t>(aAtom) == mBits; |
|
106 } |
|
107 |
|
108 // And the same but without forcing callers to atomize |
|
109 bool Equals(const nsAString& aLocalName) const |
|
110 { |
|
111 return IsAtom() && Atom()->Equals(aLocalName); |
|
112 } |
|
113 |
|
114 bool Equals(nsIAtom* aLocalName, int32_t aNamespaceID) const |
|
115 { |
|
116 if (aNamespaceID == kNameSpaceID_None) { |
|
117 return Equals(aLocalName); |
|
118 } |
|
119 return !IsAtom() && NodeInfo()->Equals(aLocalName, aNamespaceID); |
|
120 } |
|
121 |
|
122 bool Equals(nsINodeInfo* aNodeInfo) const |
|
123 { |
|
124 return Equals(aNodeInfo->NameAtom(), aNodeInfo->NamespaceID()); |
|
125 } |
|
126 |
|
127 int32_t NamespaceID() const |
|
128 { |
|
129 return IsAtom() ? kNameSpaceID_None : NodeInfo()->NamespaceID(); |
|
130 } |
|
131 |
|
132 int32_t NamespaceEquals(int32_t aNamespaceID) const |
|
133 { |
|
134 return aNamespaceID == kNameSpaceID_None ? |
|
135 IsAtom() : |
|
136 (!IsAtom() && NodeInfo()->NamespaceEquals(aNamespaceID)); |
|
137 } |
|
138 |
|
139 nsIAtom* LocalName() const |
|
140 { |
|
141 return IsAtom() ? Atom() : NodeInfo()->NameAtom(); |
|
142 } |
|
143 |
|
144 nsIAtom* GetPrefix() const |
|
145 { |
|
146 return IsAtom() ? nullptr : NodeInfo()->GetPrefixAtom(); |
|
147 } |
|
148 |
|
149 bool QualifiedNameEquals(const nsAString& aName) const |
|
150 { |
|
151 return IsAtom() ? Atom()->Equals(aName) : |
|
152 NodeInfo()->QualifiedNameEquals(aName); |
|
153 } |
|
154 |
|
155 void GetQualifiedName(nsAString& aStr) const |
|
156 { |
|
157 if (IsAtom()) { |
|
158 Atom()->ToString(aStr); |
|
159 } |
|
160 else { |
|
161 aStr = NodeInfo()->QualifiedName(); |
|
162 } |
|
163 } |
|
164 |
|
165 #ifdef MOZILLA_INTERNAL_API |
|
166 void GetPrefix(nsAString& aStr) const |
|
167 { |
|
168 if (IsAtom()) { |
|
169 SetDOMStringToNull(aStr); |
|
170 } |
|
171 else { |
|
172 NodeInfo()->GetPrefix(aStr); |
|
173 } |
|
174 } |
|
175 #endif |
|
176 |
|
177 uint32_t HashValue() const |
|
178 { |
|
179 // mBits and uint32_t might have different size. This should silence |
|
180 // any warnings or compile-errors. This is what the implementation of |
|
181 // NS_PTR_TO_INT32 does to take care of the same problem. |
|
182 return mBits - 0; |
|
183 } |
|
184 |
|
185 bool IsSmaller(nsIAtom* aOther) const |
|
186 { |
|
187 return mBits < reinterpret_cast<uintptr_t>(aOther); |
|
188 } |
|
189 |
|
190 private: |
|
191 |
|
192 void AddRefInternalName() |
|
193 { |
|
194 // Since both nsINodeInfo and nsIAtom inherit nsISupports as its first |
|
195 // interface we can safely assume that it's first in the vtable |
|
196 nsISupports* name = reinterpret_cast<nsISupports *> |
|
197 (mBits & ~NS_ATTRNAME_NODEINFO_BIT); |
|
198 |
|
199 NS_ADDREF(name); |
|
200 } |
|
201 |
|
202 void ReleaseInternalName() |
|
203 { |
|
204 // Since both nsINodeInfo and nsIAtom inherit nsISupports as its first |
|
205 // interface we can safely assume that it's first in the vtable |
|
206 nsISupports* name = reinterpret_cast<nsISupports *> |
|
207 (mBits & ~NS_ATTRNAME_NODEINFO_BIT); |
|
208 |
|
209 NS_RELEASE(name); |
|
210 } |
|
211 |
|
212 uintptr_t mBits; |
|
213 }; |
|
214 |
|
215 #endif |