1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * IBM Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2003
20 : * IBM Corporation. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * IBM Corporation
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : /*
40 : * Class that represents the name (nodeinfo or atom) of an attribute;
41 : * using nodeinfos all the time is too slow, so we use atoms when we
42 : * can.
43 : */
44 :
45 : #ifndef nsAttrName_h___
46 : #define nsAttrName_h___
47 :
48 : #include "nsINodeInfo.h"
49 : #include "nsIAtom.h"
50 : #include "nsDOMString.h"
51 :
52 : typedef PRUptrdiff PtrBits;
53 :
54 : #define NS_ATTRNAME_NODEINFO_BIT 1
55 : class nsAttrName
56 : {
57 : public:
58 : nsAttrName(const nsAttrName& aOther)
59 : : mBits(aOther.mBits)
60 : {
61 : AddRefInternalName();
62 : }
63 :
64 : explicit nsAttrName(nsIAtom* aAtom)
65 : : mBits(reinterpret_cast<PtrBits>(aAtom))
66 : {
67 : NS_ASSERTION(aAtom, "null atom-name in nsAttrName");
68 : NS_ADDREF(aAtom);
69 : }
70 :
71 : explicit nsAttrName(nsINodeInfo* aNodeInfo)
72 : {
73 : NS_ASSERTION(aNodeInfo, "null nodeinfo-name in nsAttrName");
74 : if (aNodeInfo->NamespaceEquals(kNameSpaceID_None)) {
75 : mBits = reinterpret_cast<PtrBits>(aNodeInfo->NameAtom());
76 : NS_ADDREF(aNodeInfo->NameAtom());
77 : }
78 : else {
79 : mBits = reinterpret_cast<PtrBits>(aNodeInfo) |
80 : NS_ATTRNAME_NODEINFO_BIT;
81 : NS_ADDREF(aNodeInfo);
82 : }
83 : }
84 :
85 : ~nsAttrName()
86 : {
87 : ReleaseInternalName();
88 : }
89 :
90 : void SetTo(nsINodeInfo* aNodeInfo)
91 : {
92 : NS_ASSERTION(aNodeInfo, "null nodeinfo-name in nsAttrName");
93 :
94 : ReleaseInternalName();
95 : if (aNodeInfo->NamespaceEquals(kNameSpaceID_None)) {
96 : mBits = reinterpret_cast<PtrBits>(aNodeInfo->NameAtom());
97 : NS_ADDREF(aNodeInfo->NameAtom());
98 : }
99 : else {
100 : mBits = reinterpret_cast<PtrBits>(aNodeInfo) |
101 : NS_ATTRNAME_NODEINFO_BIT;
102 : NS_ADDREF(aNodeInfo);
103 : }
104 : }
105 :
106 : void SetTo(nsIAtom* aAtom)
107 : {
108 : NS_ASSERTION(aAtom, "null atom-name in nsAttrName");
109 :
110 : ReleaseInternalName();
111 : mBits = reinterpret_cast<PtrBits>(aAtom);
112 : NS_ADDREF(aAtom);
113 : }
114 :
115 0 : bool IsAtom() const
116 : {
117 0 : return !(mBits & NS_ATTRNAME_NODEINFO_BIT);
118 : }
119 :
120 0 : nsINodeInfo* NodeInfo() const
121 : {
122 0 : NS_ASSERTION(!IsAtom(), "getting nodeinfo-value of atom-name");
123 0 : return reinterpret_cast<nsINodeInfo*>(mBits & ~NS_ATTRNAME_NODEINFO_BIT);
124 : }
125 :
126 0 : nsIAtom* Atom() const
127 : {
128 0 : NS_ASSERTION(IsAtom(), "getting atom-value of nodeinfo-name");
129 0 : return reinterpret_cast<nsIAtom*>(mBits);
130 : }
131 :
132 : bool Equals(const nsAttrName& aOther) const
133 : {
134 : return mBits == aOther.mBits;
135 : }
136 :
137 : // Faster comparison in the case we know the namespace is null
138 0 : bool Equals(nsIAtom* aAtom) const
139 : {
140 0 : return reinterpret_cast<PtrBits>(aAtom) == mBits;
141 : }
142 :
143 0 : bool Equals(nsIAtom* aLocalName, PRInt32 aNamespaceID) const
144 : {
145 0 : if (aNamespaceID == kNameSpaceID_None) {
146 0 : return Equals(aLocalName);
147 : }
148 0 : return !IsAtom() && NodeInfo()->Equals(aLocalName, aNamespaceID);
149 : }
150 :
151 : bool Equals(nsINodeInfo* aNodeInfo) const
152 : {
153 : return Equals(aNodeInfo->NameAtom(), aNodeInfo->NamespaceID());
154 : }
155 :
156 0 : PRInt32 NamespaceID() const
157 : {
158 0 : return IsAtom() ? kNameSpaceID_None : NodeInfo()->NamespaceID();
159 : }
160 :
161 0 : PRInt32 NamespaceEquals(PRInt32 aNamespaceID) const
162 : {
163 : return aNamespaceID == kNameSpaceID_None ?
164 0 : IsAtom() :
165 0 : (!IsAtom() && NodeInfo()->NamespaceEquals(aNamespaceID));
166 : }
167 :
168 0 : nsIAtom* LocalName() const
169 : {
170 0 : return IsAtom() ? Atom() : NodeInfo()->NameAtom();
171 : }
172 :
173 0 : nsIAtom* GetPrefix() const
174 : {
175 0 : return IsAtom() ? nsnull : NodeInfo()->GetPrefixAtom();
176 : }
177 :
178 : bool QualifiedNameEquals(const nsAString& aName) const
179 : {
180 : return IsAtom() ? Atom()->Equals(aName) :
181 : NodeInfo()->QualifiedNameEquals(aName);
182 : }
183 :
184 0 : void GetQualifiedName(nsAString& aStr) const
185 : {
186 0 : if (IsAtom()) {
187 0 : Atom()->ToString(aStr);
188 : }
189 : else {
190 0 : aStr = NodeInfo()->QualifiedName();
191 : }
192 0 : }
193 :
194 : void GetPrefix(nsAString& aStr) const
195 : {
196 : if (IsAtom()) {
197 : SetDOMStringToNull(aStr);
198 : }
199 : else {
200 : NodeInfo()->GetPrefix(aStr);
201 : }
202 : }
203 :
204 : PRUint32 HashValue() const
205 : {
206 : // mBits and PRUint32 might have different size. This should silence
207 : // any warnings or compile-errors. This is what the implementation of
208 : // NS_PTR_TO_INT32 does to take care of the same problem.
209 : return mBits - 0;
210 : }
211 :
212 : bool IsSmaller(nsIAtom* aOther) const
213 : {
214 : return mBits < reinterpret_cast<PtrBits>(aOther);
215 : }
216 :
217 : private:
218 :
219 : void AddRefInternalName()
220 : {
221 : // Since both nsINodeInfo and nsIAtom inherit nsISupports as its first
222 : // interface we can safely assume that it's first in the vtable
223 : nsISupports* name = reinterpret_cast<nsISupports *>
224 : (mBits & ~NS_ATTRNAME_NODEINFO_BIT);
225 :
226 : NS_ADDREF(name);
227 : }
228 :
229 : void ReleaseInternalName()
230 : {
231 : // Since both nsINodeInfo and nsIAtom inherit nsISupports as its first
232 : // interface we can safely assume that it's first in the vtable
233 : nsISupports* name = reinterpret_cast<nsISupports *>
234 : (mBits & ~NS_ATTRNAME_NODEINFO_BIT);
235 :
236 : NS_RELEASE(name);
237 : }
238 :
239 : PtrBits mBits;
240 : };
241 :
242 : #endif
|