1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/src/nsAttrAndChildArray.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,215 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * Storage of the children and attributes of a DOM node; storage for 1.11 + * the two is unified to minimize footprint. 1.12 + */ 1.13 + 1.14 +#ifndef nsAttrAndChildArray_h___ 1.15 +#define nsAttrAndChildArray_h___ 1.16 + 1.17 +#include "mozilla/Attributes.h" 1.18 +#include "mozilla/MemoryReporting.h" 1.19 + 1.20 +#include "nscore.h" 1.21 +#include "nsAttrName.h" 1.22 +#include "nsAttrValue.h" 1.23 +#include "nsCaseTreatment.h" 1.24 + 1.25 +class nsINode; 1.26 +class nsIContent; 1.27 +class nsMappedAttributes; 1.28 +class nsHTMLStyleSheet; 1.29 +class nsRuleWalker; 1.30 +class nsMappedAttributeElement; 1.31 + 1.32 +#define ATTRCHILD_ARRAY_GROWSIZE 8 1.33 +#define ATTRCHILD_ARRAY_LINEAR_THRESHOLD 32 1.34 + 1.35 +#define ATTRCHILD_ARRAY_ATTR_SLOTS_BITS 10 1.36 + 1.37 +#define ATTRCHILD_ARRAY_MAX_ATTR_COUNT \ 1.38 + ((1 << ATTRCHILD_ARRAY_ATTR_SLOTS_BITS) - 1) 1.39 + 1.40 +#define ATTRCHILD_ARRAY_MAX_CHILD_COUNT \ 1.41 + (~uint32_t(0) >> ATTRCHILD_ARRAY_ATTR_SLOTS_BITS) 1.42 + 1.43 +#define ATTRCHILD_ARRAY_ATTR_SLOTS_COUNT_MASK \ 1.44 + ((1 << ATTRCHILD_ARRAY_ATTR_SLOTS_BITS) - 1) 1.45 + 1.46 + 1.47 +#define ATTRSIZE (sizeof(InternalAttr) / sizeof(void*)) 1.48 + 1.49 +class nsAttrAndChildArray 1.50 +{ 1.51 +public: 1.52 + nsAttrAndChildArray(); 1.53 + ~nsAttrAndChildArray(); 1.54 + 1.55 + uint32_t ChildCount() const 1.56 + { 1.57 + return mImpl ? (mImpl->mAttrAndChildCount >> ATTRCHILD_ARRAY_ATTR_SLOTS_BITS) : 0; 1.58 + } 1.59 + nsIContent* ChildAt(uint32_t aPos) const 1.60 + { 1.61 + NS_ASSERTION(aPos < ChildCount(), "out-of-bounds access in nsAttrAndChildArray"); 1.62 + return reinterpret_cast<nsIContent*>(mImpl->mBuffer[AttrSlotsSize() + aPos]); 1.63 + } 1.64 + nsIContent* GetSafeChildAt(uint32_t aPos) const; 1.65 + nsIContent * const * GetChildArray(uint32_t* aChildCount) const; 1.66 + nsresult AppendChild(nsIContent* aChild) 1.67 + { 1.68 + return InsertChildAt(aChild, ChildCount()); 1.69 + } 1.70 + nsresult InsertChildAt(nsIContent* aChild, uint32_t aPos); 1.71 + void RemoveChildAt(uint32_t aPos); 1.72 + // Like RemoveChildAt but hands the reference to the child being 1.73 + // removed back to the caller instead of just releasing it. 1.74 + already_AddRefed<nsIContent> TakeChildAt(uint32_t aPos); 1.75 + int32_t IndexOfChild(const nsINode* aPossibleChild) const; 1.76 + 1.77 + bool HasAttrs() const 1.78 + { 1.79 + return MappedAttrCount() || (AttrSlotCount() && AttrSlotIsTaken(0)); 1.80 + } 1.81 + 1.82 + uint32_t AttrCount() const; 1.83 + const nsAttrValue* GetAttr(nsIAtom* aLocalName, 1.84 + int32_t aNamespaceID = kNameSpaceID_None) const; 1.85 + // As above but using a string attr name and always using 1.86 + // kNameSpaceID_None. This is always case-sensitive. 1.87 + const nsAttrValue* GetAttr(const nsAString& aName) const; 1.88 + // Get an nsAttrValue by qualified name. Can optionally do 1.89 + // ASCII-case-insensitive name matching. 1.90 + const nsAttrValue* GetAttr(const nsAString& aName, 1.91 + nsCaseTreatment aCaseSensitive) const; 1.92 + const nsAttrValue* AttrAt(uint32_t aPos) const; 1.93 + nsresult SetAndTakeAttr(nsIAtom* aLocalName, nsAttrValue& aValue); 1.94 + nsresult SetAndTakeAttr(nsINodeInfo* aName, nsAttrValue& aValue); 1.95 + 1.96 + // Remove the attr at position aPos. The value of the attr is placed in 1.97 + // aValue; any value that was already in aValue is destroyed. 1.98 + nsresult RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue); 1.99 + 1.100 + // Returns attribute name at given position, *not* out-of-bounds safe 1.101 + const nsAttrName* AttrNameAt(uint32_t aPos) const; 1.102 + 1.103 + // Returns attribute name at given position or null if aPos is out-of-bounds 1.104 + const nsAttrName* GetSafeAttrNameAt(uint32_t aPos) const; 1.105 + 1.106 + const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const; 1.107 + int32_t IndexOfAttr(nsIAtom* aLocalName, int32_t aNamespaceID = kNameSpaceID_None) const; 1.108 + 1.109 + nsresult SetAndTakeMappedAttr(nsIAtom* aLocalName, nsAttrValue& aValue, 1.110 + nsMappedAttributeElement* aContent, 1.111 + nsHTMLStyleSheet* aSheet); 1.112 + nsresult SetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet) { 1.113 + if (!mImpl || !mImpl->mMappedAttrs) { 1.114 + return NS_OK; 1.115 + } 1.116 + return DoSetMappedAttrStyleSheet(aSheet); 1.117 + } 1.118 + void WalkMappedAttributeStyleRules(nsRuleWalker* aRuleWalker); 1.119 + 1.120 + void Compact(); 1.121 + 1.122 + bool CanFitMoreAttrs() const 1.123 + { 1.124 + return AttrSlotCount() < ATTRCHILD_ARRAY_MAX_ATTR_COUNT || 1.125 + !AttrSlotIsTaken(ATTRCHILD_ARRAY_MAX_ATTR_COUNT - 1); 1.126 + } 1.127 + 1.128 + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 1.129 + bool HasMappedAttrs() const 1.130 + { 1.131 + return MappedAttrCount(); 1.132 + } 1.133 + 1.134 +private: 1.135 + nsAttrAndChildArray(const nsAttrAndChildArray& aOther) MOZ_DELETE; 1.136 + nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther) MOZ_DELETE; 1.137 + 1.138 + void Clear(); 1.139 + 1.140 + uint32_t NonMappedAttrCount() const; 1.141 + uint32_t MappedAttrCount() const; 1.142 + 1.143 + // Returns a non-null zero-refcount object. 1.144 + nsMappedAttributes* 1.145 + GetModifiableMapped(nsMappedAttributeElement* aContent, 1.146 + nsHTMLStyleSheet* aSheet, 1.147 + bool aWillAddAttr); 1.148 + nsresult MakeMappedUnique(nsMappedAttributes* aAttributes); 1.149 + 1.150 + uint32_t AttrSlotsSize() const 1.151 + { 1.152 + return AttrSlotCount() * ATTRSIZE; 1.153 + } 1.154 + 1.155 + uint32_t AttrSlotCount() const 1.156 + { 1.157 + return mImpl ? mImpl->mAttrAndChildCount & ATTRCHILD_ARRAY_ATTR_SLOTS_COUNT_MASK : 0; 1.158 + } 1.159 + 1.160 + bool AttrSlotIsTaken(uint32_t aSlot) const 1.161 + { 1.162 + NS_PRECONDITION(aSlot < AttrSlotCount(), "out-of-bounds"); 1.163 + return mImpl->mBuffer[aSlot * ATTRSIZE]; 1.164 + } 1.165 + 1.166 + void SetChildCount(uint32_t aCount) 1.167 + { 1.168 + mImpl->mAttrAndChildCount = 1.169 + (mImpl->mAttrAndChildCount & ATTRCHILD_ARRAY_ATTR_SLOTS_COUNT_MASK) | 1.170 + (aCount << ATTRCHILD_ARRAY_ATTR_SLOTS_BITS); 1.171 + } 1.172 + 1.173 + void SetAttrSlotCount(uint32_t aCount) 1.174 + { 1.175 + mImpl->mAttrAndChildCount = 1.176 + (mImpl->mAttrAndChildCount & ~ATTRCHILD_ARRAY_ATTR_SLOTS_COUNT_MASK) | 1.177 + aCount; 1.178 + } 1.179 + 1.180 + void SetAttrSlotAndChildCount(uint32_t aSlotCount, uint32_t aChildCount) 1.181 + { 1.182 + mImpl->mAttrAndChildCount = aSlotCount | 1.183 + (aChildCount << ATTRCHILD_ARRAY_ATTR_SLOTS_BITS); 1.184 + } 1.185 + 1.186 + bool GrowBy(uint32_t aGrowSize); 1.187 + bool AddAttrSlot(); 1.188 + 1.189 + /** 1.190 + * Set *aPos to aChild and update sibling pointers as needed. aIndex is the 1.191 + * index at which aChild is actually being inserted. aChildCount is the 1.192 + * number of kids we had before the insertion. 1.193 + */ 1.194 + inline void SetChildAtPos(void** aPos, nsIContent* aChild, uint32_t aIndex, 1.195 + uint32_t aChildCount); 1.196 + 1.197 + /** 1.198 + * Guts of SetMappedAttrStyleSheet for the rare case when we have mapped attrs 1.199 + */ 1.200 + nsresult DoSetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet); 1.201 + 1.202 + struct InternalAttr 1.203 + { 1.204 + nsAttrName mName; 1.205 + nsAttrValue mValue; 1.206 + }; 1.207 + 1.208 + struct Impl { 1.209 + uint32_t mAttrAndChildCount; 1.210 + uint32_t mBufferSize; 1.211 + nsMappedAttributes* mMappedAttrs; 1.212 + void* mBuffer[1]; 1.213 + }; 1.214 + 1.215 + Impl* mImpl; 1.216 +}; 1.217 + 1.218 +#endif