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 Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Allan Beaufour <allan@beaufour.dk>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or 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 : * Implementation of the |attributes| property of DOM Core's nsIDOMNode object.
41 : */
42 :
43 : #ifndef nsDOMAttributeMap_h___
44 : #define nsDOMAttributeMap_h___
45 :
46 : #include "nsIDOMNamedNodeMap.h"
47 : #include "nsString.h"
48 : #include "nsRefPtrHashtable.h"
49 : #include "nsCycleCollectionParticipant.h"
50 : #include "prbit.h"
51 : #include "nsIDOMNode.h"
52 :
53 : class nsIAtom;
54 : class nsIContent;
55 : class nsDOMAttribute;
56 : class nsINodeInfo;
57 : class nsIDocument;
58 :
59 : namespace mozilla {
60 : namespace dom {
61 : class Element;
62 : } // namespace dom
63 : } // namespace mozilla
64 :
65 : /**
66 : * Structure used as a key for caching nsDOMAttributes in nsDOMAttributeMap's mAttributeCache.
67 : */
68 : class nsAttrKey
69 : {
70 : public:
71 : /**
72 : * The namespace of the attribute
73 : */
74 : PRInt32 mNamespaceID;
75 :
76 : /**
77 : * The atom for attribute, weak ref. is fine as we only use it for the
78 : * hashcode, we never dereference it.
79 : */
80 : nsIAtom* mLocalName;
81 :
82 979 : nsAttrKey(PRInt32 aNs, nsIAtom* aName)
83 979 : : mNamespaceID(aNs), mLocalName(aName) {}
84 :
85 945 : nsAttrKey(const nsAttrKey& aAttr)
86 945 : : mNamespaceID(aAttr.mNamespaceID), mLocalName(aAttr.mLocalName) {}
87 : };
88 :
89 : /**
90 : * PLDHashEntryHdr implementation for nsAttrKey.
91 : */
92 : class nsAttrHashKey : public PLDHashEntryHdr
93 : {
94 : public:
95 : typedef const nsAttrKey& KeyType;
96 : typedef const nsAttrKey* KeyTypePointer;
97 :
98 945 : nsAttrHashKey(KeyTypePointer aKey) : mKey(*aKey) {}
99 : nsAttrHashKey(const nsAttrHashKey& aCopy) : mKey(aCopy.mKey) {}
100 945 : ~nsAttrHashKey() {}
101 :
102 1890 : KeyType GetKey() const { return mKey; }
103 34 : bool KeyEquals(KeyTypePointer aKey) const
104 : {
105 : return mKey.mLocalName == aKey->mLocalName &&
106 34 : mKey.mNamespaceID == aKey->mNamespaceID;
107 : }
108 :
109 1922 : static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
110 1922 : static PLDHashNumber HashKey(KeyTypePointer aKey)
111 : {
112 1922 : if (!aKey)
113 0 : return 0;
114 :
115 1922 : return mozilla::HashGeneric(aKey->mNamespaceID, aKey->mLocalName);
116 : }
117 : enum { ALLOW_MEMMOVE = true };
118 :
119 : private:
120 : nsAttrKey mKey;
121 : };
122 :
123 : // Helper class that implements the nsIDOMNamedNodeMap interface.
124 : class nsDOMAttributeMap : public nsIDOMNamedNodeMap
125 : {
126 : public:
127 : typedef mozilla::dom::Element Element;
128 :
129 : nsDOMAttributeMap(Element *aContent);
130 : virtual ~nsDOMAttributeMap();
131 :
132 : /**
133 : * Initialize the map. Must be called before the map is used.
134 : */
135 : bool Init();
136 :
137 232 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
138 :
139 : // nsIDOMNamedNodeMap interface
140 : NS_DECL_NSIDOMNAMEDNODEMAP
141 :
142 : void DropReference();
143 :
144 5351 : Element* GetContent()
145 : {
146 5351 : return mContent;
147 : }
148 :
149 : /**
150 : * Called when mContent is moved into a new document.
151 : * Updates the nodeinfos of all owned nodes.
152 : */
153 : nsresult SetOwnerDocument(nsIDocument* aDocument);
154 :
155 : /**
156 : * Drop an attribute from the map's cache (does not remove the attribute
157 : * from the node!)
158 : */
159 : void DropAttribute(PRInt32 aNamespaceID, nsIAtom* aLocalName);
160 :
161 : /**
162 : * Returns the number of attribute nodes currently in the map.
163 : * Note: this is just the number of cached attribute nodes, not the number of
164 : * attributes in mContent.
165 : *
166 : * @return The number of attribute nodes in the map.
167 : */
168 : PRUint32 Count() const;
169 :
170 : typedef nsRefPtrHashtable<nsAttrHashKey, nsDOMAttribute> AttrCache;
171 :
172 : /**
173 : * Enumerates over the attribute nodess in the map and calls aFunc for each
174 : * one. If aFunc returns PL_DHASH_STOP we'll stop enumerating at that point.
175 : *
176 : * @return The number of attribute nodes that aFunc was called for.
177 : */
178 : PRUint32 Enumerate(AttrCache::EnumReadFunction aFunc, void *aUserArg) const;
179 :
180 : nsDOMAttribute* GetItemAt(PRUint32 aIndex, nsresult *rv);
181 : nsDOMAttribute* GetNamedItem(const nsAString& aAttrName, nsresult *rv);
182 :
183 0 : static nsDOMAttributeMap* FromSupports(nsISupports* aSupports)
184 : {
185 : #ifdef DEBUG
186 : {
187 0 : nsCOMPtr<nsIDOMNamedNodeMap> map_qi = do_QueryInterface(aSupports);
188 :
189 : // If this assertion fires the QI implementation for the object in
190 : // question doesn't use the nsIDOMNamedNodeMap pointer as the nsISupports
191 : // pointer. That must be fixed, or we'll crash...
192 0 : NS_ASSERTION(map_qi == static_cast<nsIDOMNamedNodeMap*>(aSupports),
193 : "Uh, fix QI!");
194 : }
195 : #endif
196 :
197 0 : return static_cast<nsDOMAttributeMap*>(aSupports);
198 : }
199 :
200 16211 : NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMAttributeMap)
201 :
202 : private:
203 : Element *mContent; // Weak reference
204 :
205 : /**
206 : * Cache of nsDOMAttributes.
207 : */
208 : AttrCache mAttributeCache;
209 :
210 : /**
211 : * SetNamedItem() (aWithNS = false) and SetNamedItemNS() (aWithNS =
212 : * true) implementation.
213 : */
214 : nsresult SetNamedItemInternal(nsIDOMNode *aNode,
215 : nsIDOMNode **aReturn,
216 : bool aWithNS);
217 :
218 : /**
219 : * GetNamedItemNS() implementation taking |aRemove| for GetAttribute(),
220 : * which is used by RemoveNamedItemNS().
221 : */
222 : nsresult GetNamedItemNSInternal(const nsAString& aNamespaceURI,
223 : const nsAString& aLocalName,
224 : nsIDOMNode** aReturn,
225 : bool aRemove = false);
226 :
227 : nsDOMAttribute* GetAttribute(nsINodeInfo* aNodeInfo, bool aNsAware);
228 :
229 : /**
230 : * Remove an attribute, returns the removed node.
231 : */
232 : nsresult RemoveAttribute(nsINodeInfo* aNodeInfo,
233 : nsIDOMNode** aReturn);
234 : };
235 :
236 :
237 : #endif /* nsDOMAttributeMap_h___ */
|