nsAttrName.h (5218B)
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 /* 8 * Class that represents the name (nodeinfo or atom) of an attribute; 9 * using nodeinfos all the time is too slow, so we use atoms when we 10 * can. 11 */ 12 13 #ifndef nsAttrName_h___ 14 #define nsAttrName_h___ 15 16 #include "mozilla/dom/NodeInfo.h" 17 #include "nsAtom.h" 18 #include "nsDOMString.h" 19 20 #define NS_ATTRNAME_NODEINFO_BIT 1 21 class nsAttrName { 22 public: 23 nsAttrName(const nsAttrName& aOther) : mBits(aOther.mBits) { 24 AddRefInternalName(); 25 } 26 27 explicit nsAttrName(nsAtom* aAtom) 28 : mBits(reinterpret_cast<uintptr_t>(aAtom)) { 29 NS_ASSERTION(aAtom, "null atom-name in nsAttrName"); 30 NS_ADDREF(aAtom); 31 } 32 33 explicit nsAttrName(mozilla::dom::NodeInfo* aNodeInfo) { 34 NS_ASSERTION(aNodeInfo, "null nodeinfo-name in nsAttrName"); 35 if (aNodeInfo->NamespaceEquals(kNameSpaceID_None)) { 36 mBits = reinterpret_cast<uintptr_t>(aNodeInfo->NameAtom()); 37 NS_ADDREF(aNodeInfo->NameAtom()); 38 } else { 39 mBits = reinterpret_cast<uintptr_t>(aNodeInfo) | NS_ATTRNAME_NODEINFO_BIT; 40 NS_ADDREF(aNodeInfo); 41 } 42 } 43 44 ~nsAttrName() { ReleaseInternalName(); } 45 46 void SetTo(mozilla::dom::NodeInfo* aNodeInfo) { 47 NS_ASSERTION(aNodeInfo, "null nodeinfo-name in nsAttrName"); 48 49 ReleaseInternalName(); 50 if (aNodeInfo->NamespaceEquals(kNameSpaceID_None)) { 51 mBits = reinterpret_cast<uintptr_t>(aNodeInfo->NameAtom()); 52 NS_ADDREF(aNodeInfo->NameAtom()); 53 } else { 54 mBits = reinterpret_cast<uintptr_t>(aNodeInfo) | NS_ATTRNAME_NODEINFO_BIT; 55 NS_ADDREF(aNodeInfo); 56 } 57 } 58 59 void SetTo(nsAtom* aAtom) { 60 NS_ASSERTION(aAtom, "null atom-name in nsAttrName"); 61 62 ReleaseInternalName(); 63 mBits = reinterpret_cast<uintptr_t>(aAtom); 64 NS_ADDREF(aAtom); 65 } 66 67 bool IsAtom() const { return !(mBits & NS_ATTRNAME_NODEINFO_BIT); } 68 69 mozilla::dom::NodeInfo* NodeInfo() const { 70 NS_ASSERTION(!IsAtom(), "getting nodeinfo-value of atom-name"); 71 return reinterpret_cast<mozilla::dom::NodeInfo*>(mBits & 72 ~NS_ATTRNAME_NODEINFO_BIT); 73 } 74 75 nsAtom* Atom() const { 76 NS_ASSERTION(IsAtom(), "getting atom-value of nodeinfo-name"); 77 return reinterpret_cast<nsAtom*>(mBits); 78 } 79 80 bool Equals(const nsAttrName& aOther) const { return mBits == aOther.mBits; } 81 82 // Faster comparison in the case we know the namespace is null 83 // Note that some callers such as AttrArray::IndexOfAttr() will 84 // call this function on nsAttrName structs with 0 mBits, so no attempt 85 // must be made to do anything with mBits besides comparing it with the 86 // incoming aAtom argument. 87 bool Equals(const nsAtom* aAtom) const { 88 return reinterpret_cast<uintptr_t>(aAtom) == mBits; 89 } 90 91 // And the same but without forcing callers to atomize 92 bool Equals(const nsAString& aLocalName) const { 93 return IsAtom() && Atom()->Equals(aLocalName); 94 } 95 96 bool Equals(const nsAtom* aLocalName, int32_t aNamespaceID) const { 97 if (aNamespaceID == kNameSpaceID_None) { 98 return Equals(aLocalName); 99 } 100 return !IsAtom() && NodeInfo()->Equals(aLocalName, aNamespaceID); 101 } 102 103 bool Equals(mozilla::dom::NodeInfo* aNodeInfo) const { 104 return Equals(aNodeInfo->NameAtom(), aNodeInfo->NamespaceID()); 105 } 106 107 int32_t NamespaceID() const { 108 return IsAtom() ? kNameSpaceID_None : NodeInfo()->NamespaceID(); 109 } 110 111 int32_t NamespaceEquals(int32_t aNamespaceID) const { 112 return aNamespaceID == kNameSpaceID_None 113 ? IsAtom() 114 : (!IsAtom() && NodeInfo()->NamespaceEquals(aNamespaceID)); 115 } 116 117 nsAtom* LocalName() const { 118 return IsAtom() ? Atom() : NodeInfo()->NameAtom(); 119 } 120 121 nsAtom* GetPrefix() const { 122 return IsAtom() ? nullptr : NodeInfo()->GetPrefixAtom(); 123 } 124 125 bool QualifiedNameEquals(const nsAString& aName) const { 126 return IsAtom() ? Atom()->Equals(aName) 127 : NodeInfo()->QualifiedNameEquals(aName); 128 } 129 130 void GetQualifiedName(nsAString& aStr) const { 131 if (IsAtom()) { 132 Atom()->ToString(aStr); 133 } else { 134 aStr = NodeInfo()->QualifiedName(); 135 } 136 } 137 138 #ifdef MOZILLA_INTERNAL_API 139 void GetPrefix(nsAString& aStr) const { 140 if (IsAtom()) { 141 SetDOMStringToNull(aStr); 142 } else { 143 NodeInfo()->GetPrefix(aStr); 144 } 145 } 146 #endif 147 148 uint32_t HashValue() const { 149 // mBits and uint32_t might have different size. This should silence 150 // any warnings or compile-errors. This is what the implementation of 151 // NS_PTR_TO_INT32 does to take care of the same problem. 152 return mBits - 0; 153 } 154 155 bool IsSmaller(const nsAtom* aOther) const { 156 return mBits < reinterpret_cast<uintptr_t>(aOther); 157 } 158 159 private: 160 void AddRefInternalName() { 161 if (IsAtom()) { 162 NS_ADDREF(Atom()); 163 } else { 164 NS_ADDREF(NodeInfo()); 165 } 166 } 167 168 void ReleaseInternalName() { 169 if (IsAtom()) { 170 Atom()->Release(); 171 } else { 172 NodeInfo()->Release(); 173 } 174 } 175 176 uintptr_t mBits; 177 }; 178 179 #endif