1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/src/nsMappedAttributes.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,263 @@ 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 + * A unique per-element set of attributes that is used as an 1.11 + * nsIStyleRule; used to implement presentational attributes. 1.12 + */ 1.13 + 1.14 +#include "nsMappedAttributes.h" 1.15 +#include "nsHTMLStyleSheet.h" 1.16 +#include "nsRuleWalker.h" 1.17 +#include "mozilla/HashFunctions.h" 1.18 +#include "mozilla/MemoryReporting.h" 1.19 + 1.20 +using namespace mozilla; 1.21 + 1.22 +nsMappedAttributes::nsMappedAttributes(nsHTMLStyleSheet* aSheet, 1.23 + nsMapRuleToAttributesFunc aMapRuleFunc) 1.24 + : mAttrCount(0), 1.25 + mSheet(aSheet), 1.26 + mRuleMapper(aMapRuleFunc) 1.27 +{ 1.28 +} 1.29 + 1.30 +nsMappedAttributes::nsMappedAttributes(const nsMappedAttributes& aCopy) 1.31 + : mAttrCount(aCopy.mAttrCount), 1.32 + mSheet(aCopy.mSheet), 1.33 + mRuleMapper(aCopy.mRuleMapper) 1.34 +{ 1.35 + NS_ASSERTION(mBufferSize >= aCopy.mAttrCount, "can't fit attributes"); 1.36 + 1.37 + uint32_t i; 1.38 + for (i = 0; i < mAttrCount; ++i) { 1.39 + new (&Attrs()[i]) InternalAttr(aCopy.Attrs()[i]); 1.40 + } 1.41 +} 1.42 + 1.43 +nsMappedAttributes::~nsMappedAttributes() 1.44 +{ 1.45 + if (mSheet) { 1.46 + mSheet->DropMappedAttributes(this); 1.47 + } 1.48 + 1.49 + uint32_t i; 1.50 + for (i = 0; i < mAttrCount; ++i) { 1.51 + Attrs()[i].~InternalAttr(); 1.52 + } 1.53 +} 1.54 + 1.55 + 1.56 +nsMappedAttributes* 1.57 +nsMappedAttributes::Clone(bool aWillAddAttr) 1.58 +{ 1.59 + uint32_t extra = aWillAddAttr ? 1 : 0; 1.60 + 1.61 + // This will call the overridden operator new 1.62 + return new (mAttrCount + extra) nsMappedAttributes(*this); 1.63 +} 1.64 + 1.65 +void* nsMappedAttributes::operator new(size_t aSize, uint32_t aAttrCount) CPP_THROW_NEW 1.66 +{ 1.67 + NS_ASSERTION(aAttrCount > 0, "zero-attribute nsMappedAttributes requested"); 1.68 + 1.69 + // aSize will include the mAttrs buffer so subtract that. 1.70 + void* newAttrs = ::operator new(aSize - sizeof(void*[1]) + 1.71 + aAttrCount * sizeof(InternalAttr)); 1.72 + 1.73 +#ifdef DEBUG 1.74 + static_cast<nsMappedAttributes*>(newAttrs)->mBufferSize = aAttrCount; 1.75 +#endif 1.76 + 1.77 + return newAttrs; 1.78 +} 1.79 + 1.80 +NS_IMPL_ISUPPORTS(nsMappedAttributes, 1.81 + nsIStyleRule) 1.82 + 1.83 +void 1.84 +nsMappedAttributes::SetAndTakeAttr(nsIAtom* aAttrName, nsAttrValue& aValue) 1.85 +{ 1.86 + NS_PRECONDITION(aAttrName, "null name"); 1.87 + 1.88 + uint32_t i; 1.89 + for (i = 0; i < mAttrCount && !Attrs()[i].mName.IsSmaller(aAttrName); ++i) { 1.90 + if (Attrs()[i].mName.Equals(aAttrName)) { 1.91 + Attrs()[i].mValue.Reset(); 1.92 + Attrs()[i].mValue.SwapValueWith(aValue); 1.93 + return; 1.94 + } 1.95 + } 1.96 + 1.97 + NS_ASSERTION(mBufferSize >= mAttrCount + 1, "can't fit attributes"); 1.98 + 1.99 + if (mAttrCount != i) { 1.100 + memmove(&Attrs()[i + 1], &Attrs()[i], (mAttrCount - i) * sizeof(InternalAttr)); 1.101 + } 1.102 + 1.103 + new (&Attrs()[i].mName) nsAttrName(aAttrName); 1.104 + new (&Attrs()[i].mValue) nsAttrValue(); 1.105 + Attrs()[i].mValue.SwapValueWith(aValue); 1.106 + ++mAttrCount; 1.107 +} 1.108 + 1.109 +const nsAttrValue* 1.110 +nsMappedAttributes::GetAttr(nsIAtom* aAttrName) const 1.111 +{ 1.112 + NS_PRECONDITION(aAttrName, "null name"); 1.113 + 1.114 + for (uint32_t i = 0; i < mAttrCount; ++i) { 1.115 + if (Attrs()[i].mName.Equals(aAttrName)) { 1.116 + return &Attrs()[i].mValue; 1.117 + } 1.118 + } 1.119 + 1.120 + return nullptr; 1.121 +} 1.122 + 1.123 +const nsAttrValue* 1.124 +nsMappedAttributes::GetAttr(const nsAString& aAttrName) const 1.125 +{ 1.126 + for (uint32_t i = 0; i < mAttrCount; ++i) { 1.127 + if (Attrs()[i].mName.Atom()->Equals(aAttrName)) { 1.128 + return &Attrs()[i].mValue; 1.129 + } 1.130 + } 1.131 + 1.132 + return nullptr; 1.133 +} 1.134 + 1.135 +bool 1.136 +nsMappedAttributes::Equals(const nsMappedAttributes* aOther) const 1.137 +{ 1.138 + if (this == aOther) { 1.139 + return true; 1.140 + } 1.141 + 1.142 + if (mRuleMapper != aOther->mRuleMapper || mAttrCount != aOther->mAttrCount) { 1.143 + return false; 1.144 + } 1.145 + 1.146 + uint32_t i; 1.147 + for (i = 0; i < mAttrCount; ++i) { 1.148 + if (!Attrs()[i].mName.Equals(aOther->Attrs()[i].mName) || 1.149 + !Attrs()[i].mValue.Equals(aOther->Attrs()[i].mValue)) { 1.150 + return false; 1.151 + } 1.152 + } 1.153 + 1.154 + return true; 1.155 +} 1.156 + 1.157 +uint32_t 1.158 +nsMappedAttributes::HashValue() const 1.159 +{ 1.160 + uint32_t hash = HashGeneric(mRuleMapper); 1.161 + 1.162 + uint32_t i; 1.163 + for (i = 0; i < mAttrCount; ++i) { 1.164 + hash = AddToHash(hash, 1.165 + Attrs()[i].mName.HashValue(), 1.166 + Attrs()[i].mValue.HashValue()); 1.167 + } 1.168 + 1.169 + return hash; 1.170 +} 1.171 + 1.172 +void 1.173 +nsMappedAttributes::SetStyleSheet(nsHTMLStyleSheet* aSheet) 1.174 +{ 1.175 + if (mSheet) { 1.176 + mSheet->DropMappedAttributes(this); 1.177 + } 1.178 + mSheet = aSheet; // not ref counted 1.179 +} 1.180 + 1.181 +/* virtual */ void 1.182 +nsMappedAttributes::MapRuleInfoInto(nsRuleData* aRuleData) 1.183 +{ 1.184 + if (mRuleMapper) { 1.185 + (*mRuleMapper)(this, aRuleData); 1.186 + } 1.187 +} 1.188 + 1.189 +#ifdef DEBUG 1.190 +/* virtual */ void 1.191 +nsMappedAttributes::List(FILE* out, int32_t aIndent) const 1.192 +{ 1.193 + nsAutoString buffer; 1.194 + uint32_t i; 1.195 + 1.196 + for (i = 0; i < mAttrCount; ++i) { 1.197 + int32_t indent; 1.198 + for (indent = aIndent; indent > 0; --indent) 1.199 + fputs(" ", out); 1.200 + 1.201 + Attrs()[i].mName.GetQualifiedName(buffer); 1.202 + fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out); 1.203 + 1.204 + Attrs()[i].mValue.ToString(buffer); 1.205 + fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out); 1.206 + fputs("\n", out); 1.207 + } 1.208 +} 1.209 +#endif 1.210 + 1.211 +void 1.212 +nsMappedAttributes::RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue) 1.213 +{ 1.214 + Attrs()[aPos].mValue.SwapValueWith(aValue); 1.215 + Attrs()[aPos].~InternalAttr(); 1.216 + memmove(&Attrs()[aPos], &Attrs()[aPos + 1], 1.217 + (mAttrCount - aPos - 1) * sizeof(InternalAttr)); 1.218 + mAttrCount--; 1.219 +} 1.220 + 1.221 +const nsAttrName* 1.222 +nsMappedAttributes::GetExistingAttrNameFromQName(const nsAString& aName) const 1.223 +{ 1.224 + uint32_t i; 1.225 + for (i = 0; i < mAttrCount; ++i) { 1.226 + if (Attrs()[i].mName.IsAtom()) { 1.227 + if (Attrs()[i].mName.Atom()->Equals(aName)) { 1.228 + return &Attrs()[i].mName; 1.229 + } 1.230 + } 1.231 + else { 1.232 + if (Attrs()[i].mName.NodeInfo()->QualifiedNameEquals(aName)) { 1.233 + return &Attrs()[i].mName; 1.234 + } 1.235 + } 1.236 + } 1.237 + 1.238 + return nullptr; 1.239 +} 1.240 + 1.241 +int32_t 1.242 +nsMappedAttributes::IndexOfAttr(nsIAtom* aLocalName) const 1.243 +{ 1.244 + uint32_t i; 1.245 + for (i = 0; i < mAttrCount; ++i) { 1.246 + if (Attrs()[i].mName.Equals(aLocalName)) { 1.247 + return i; 1.248 + } 1.249 + } 1.250 + 1.251 + return -1; 1.252 +} 1.253 + 1.254 +size_t 1.255 +nsMappedAttributes::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const 1.256 +{ 1.257 + NS_ASSERTION(mAttrCount == mBufferSize, 1.258 + "mBufferSize and mAttrCount are expected to be the same."); 1.259 + 1.260 + size_t n = aMallocSizeOf(this); 1.261 + for (uint16_t i = 0; i < mAttrCount; ++i) { 1.262 + n += Attrs()[i].mValue.SizeOfExcludingThis(aMallocSizeOf); 1.263 + } 1.264 + return n; 1.265 +} 1.266 +