1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/src/nsAttrValue.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,505 @@ 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 struct that represents the value (type and actual data) of an 1.11 + * attribute. 1.12 + */ 1.13 + 1.14 +#ifndef nsAttrValue_h___ 1.15 +#define nsAttrValue_h___ 1.16 + 1.17 +#include "nscore.h" 1.18 +#include "nsStringGlue.h" 1.19 +#include "nsStringBuffer.h" 1.20 +#include "nsColor.h" 1.21 +#include "nsCaseTreatment.h" 1.22 +#include "nsMargin.h" 1.23 +#include "nsCOMPtr.h" 1.24 +#include "SVGAttrValueWrapper.h" 1.25 +#include "nsTArrayForwardDeclare.h" 1.26 +#include "nsIAtom.h" 1.27 +#include "mozilla/MemoryReporting.h" 1.28 +#include "mozilla/dom/BindingDeclarations.h" 1.29 + 1.30 +class nsAString; 1.31 +class nsIDocument; 1.32 +class nsStyledElementNotElementCSSInlineStyle; 1.33 +struct MiscContainer; 1.34 + 1.35 +namespace mozilla { 1.36 +namespace css { 1.37 +class StyleRule; 1.38 +struct URLValue; 1.39 +struct ImageValue; 1.40 +} 1.41 +} 1.42 + 1.43 +#define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12 1.44 + 1.45 +#define NS_ATTRVALUE_BASETYPE_MASK (uintptr_t(3)) 1.46 +#define NS_ATTRVALUE_POINTERVALUE_MASK (~NS_ATTRVALUE_BASETYPE_MASK) 1.47 + 1.48 +#define NS_ATTRVALUE_INTEGERTYPE_BITS 4 1.49 +#define NS_ATTRVALUE_INTEGERTYPE_MASK (uintptr_t((1 << NS_ATTRVALUE_INTEGERTYPE_BITS) - 1)) 1.50 +#define NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER (1 << NS_ATTRVALUE_INTEGERTYPE_BITS) 1.51 +#define NS_ATTRVALUE_INTEGERTYPE_MAXVALUE ((1 << (31 - NS_ATTRVALUE_INTEGERTYPE_BITS)) - 1) 1.52 +#define NS_ATTRVALUE_INTEGERTYPE_MINVALUE (-NS_ATTRVALUE_INTEGERTYPE_MAXVALUE - 1) 1.53 + 1.54 +#define NS_ATTRVALUE_ENUMTABLEINDEX_BITS (32 - 16 - NS_ATTRVALUE_INTEGERTYPE_BITS) 1.55 +#define NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER (1 << (NS_ATTRVALUE_ENUMTABLEINDEX_BITS - 1)) 1.56 +#define NS_ATTRVALUE_ENUMTABLEINDEX_MAXVALUE (NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER - 1) 1.57 +#define NS_ATTRVALUE_ENUMTABLEINDEX_MASK \ 1.58 + (uintptr_t((((1 << NS_ATTRVALUE_ENUMTABLEINDEX_BITS) - 1) &~ NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER))) 1.59 + 1.60 +/** 1.61 + * A class used to construct a nsString from a nsStringBuffer (we might 1.62 + * want to move this to nsString at some point). 1.63 + * 1.64 + * WARNING: Note that nsCheapString doesn't take an explicit length -- it 1.65 + * assumes the string is maximally large, given the nsStringBuffer's storage 1.66 + * size. This means the given string buffer *must* be sized exactly correctly 1.67 + * for the string it contains (including one byte for a null terminator). If 1.68 + * it has any unused storage space, then that will result in bogus characters 1.69 + * at the end of our nsCheapString. 1.70 + */ 1.71 +class nsCheapString : public nsString { 1.72 +public: 1.73 + nsCheapString(nsStringBuffer* aBuf) 1.74 + { 1.75 + if (aBuf) 1.76 + aBuf->ToString(aBuf->StorageSize()/sizeof(char16_t) - 1, *this); 1.77 + } 1.78 +}; 1.79 + 1.80 +class nsAttrValue { 1.81 + friend struct MiscContainer; 1.82 +public: 1.83 + typedef nsTArray< nsCOMPtr<nsIAtom> > AtomArray; 1.84 + 1.85 + // This has to be the same as in ValueBaseType 1.86 + enum ValueType { 1.87 + eString = 0x00, // 00 1.88 + // 01 this value indicates an 'misc' struct 1.89 + eAtom = 0x02, // 10 1.90 + eInteger = 0x03, // 0011 1.91 + eColor = 0x07, // 0111 1.92 + eEnum = 0x0B, // 1011 This should eventually die 1.93 + ePercent = 0x0F, // 1111 1.94 + // Values below here won't matter, they'll be always stored in the 'misc' 1.95 + // struct. 1.96 + eCSSStyleRule = 0x10 1.97 + ,eURL = 0x11 1.98 + ,eImage = 0x12 1.99 + ,eAtomArray = 0x13 1.100 + ,eDoubleValue = 0x14 1.101 + ,eIntMarginValue = 0x15 1.102 + ,eSVGAngle = 0x16 1.103 + ,eSVGTypesBegin = eSVGAngle 1.104 + ,eSVGIntegerPair = 0x17 1.105 + ,eSVGLength = 0x18 1.106 + ,eSVGLengthList = 0x19 1.107 + ,eSVGNumberList = 0x1A 1.108 + ,eSVGNumberPair = 0x1B 1.109 + ,eSVGPathData = 0x1C 1.110 + ,eSVGPointList = 0x1D 1.111 + ,eSVGPreserveAspectRatio = 0x1E 1.112 + ,eSVGStringList = 0x1F 1.113 + ,eSVGTransformList = 0x20 1.114 + ,eSVGViewBox = 0x21 1.115 + ,eSVGTypesEnd = eSVGViewBox 1.116 + }; 1.117 + 1.118 + nsAttrValue(); 1.119 + nsAttrValue(const nsAttrValue& aOther); 1.120 + explicit nsAttrValue(const nsAString& aValue); 1.121 + explicit nsAttrValue(nsIAtom* aValue); 1.122 + nsAttrValue(mozilla::css::StyleRule* aValue, const nsAString* aSerialized); 1.123 + explicit nsAttrValue(const nsIntMargin& aValue); 1.124 + ~nsAttrValue(); 1.125 + 1.126 + inline const nsAttrValue& operator=(const nsAttrValue& aOther); 1.127 + 1.128 + static nsresult Init(); 1.129 + static void Shutdown(); 1.130 + 1.131 + ValueType Type() const; 1.132 + 1.133 + void Reset(); 1.134 + 1.135 + void SetTo(const nsAttrValue& aOther); 1.136 + void SetTo(const nsAString& aValue); 1.137 + void SetTo(nsIAtom* aValue); 1.138 + void SetTo(int16_t aInt); 1.139 + void SetTo(int32_t aInt, const nsAString* aSerialized); 1.140 + void SetTo(double aValue, const nsAString* aSerialized); 1.141 + void SetTo(mozilla::css::StyleRule* aValue, const nsAString* aSerialized); 1.142 + void SetTo(mozilla::css::URLValue* aValue, const nsAString* aSerialized); 1.143 + void SetTo(const nsIntMargin& aValue); 1.144 + void SetTo(const nsSVGAngle& aValue, const nsAString* aSerialized); 1.145 + void SetTo(const nsSVGIntegerPair& aValue, const nsAString* aSerialized); 1.146 + void SetTo(const nsSVGLength2& aValue, const nsAString* aSerialized); 1.147 + void SetTo(const mozilla::SVGLengthList& aValue, 1.148 + const nsAString* aSerialized); 1.149 + void SetTo(const mozilla::SVGNumberList& aValue, 1.150 + const nsAString* aSerialized); 1.151 + void SetTo(const nsSVGNumberPair& aValue, const nsAString* aSerialized); 1.152 + void SetTo(const mozilla::SVGPathData& aValue, const nsAString* aSerialized); 1.153 + void SetTo(const mozilla::SVGPointList& aValue, const nsAString* aSerialized); 1.154 + void SetTo(const mozilla::SVGAnimatedPreserveAspectRatio& aValue, 1.155 + const nsAString* aSerialized); 1.156 + void SetTo(const mozilla::SVGStringList& aValue, 1.157 + const nsAString* aSerialized); 1.158 + void SetTo(const mozilla::SVGTransformList& aValue, 1.159 + const nsAString* aSerialized); 1.160 + void SetTo(const nsSVGViewBox& aValue, const nsAString* aSerialized); 1.161 + 1.162 + /** 1.163 + * Sets this object with the string or atom representation of aValue. 1.164 + * 1.165 + * After calling this method, this object will have type eString unless the 1.166 + * type of aValue is eAtom, in which case this object will also have type 1.167 + * eAtom. 1.168 + */ 1.169 + void SetToSerialized(const nsAttrValue& aValue); 1.170 + 1.171 + void SwapValueWith(nsAttrValue& aOther); 1.172 + 1.173 + void ToString(nsAString& aResult) const; 1.174 + inline void ToString(mozilla::dom::DOMString& aResult) const; 1.175 + 1.176 + /** 1.177 + * Returns the value of this object as an atom. If necessary, the value will 1.178 + * first be serialised using ToString before converting to an atom. 1.179 + */ 1.180 + already_AddRefed<nsIAtom> GetAsAtom() const; 1.181 + 1.182 + // Methods to get value. These methods do not convert so only use them 1.183 + // to retrieve the datatype that this nsAttrValue has. 1.184 + inline bool IsEmptyString() const; 1.185 + const nsCheapString GetStringValue() const; 1.186 + inline nsIAtom* GetAtomValue() const; 1.187 + inline int32_t GetIntegerValue() const; 1.188 + bool GetColorValue(nscolor& aColor) const; 1.189 + inline int16_t GetEnumValue() const; 1.190 + inline float GetPercentValue() const; 1.191 + inline AtomArray* GetAtomArrayValue() const; 1.192 + inline mozilla::css::StyleRule* GetCSSStyleRuleValue() const; 1.193 + inline mozilla::css::URLValue* GetURLValue() const; 1.194 + inline mozilla::css::ImageValue* GetImageValue() const; 1.195 + inline double GetDoubleValue() const; 1.196 + bool GetIntMarginValue(nsIntMargin& aMargin) const; 1.197 + 1.198 + /** 1.199 + * Returns the string corresponding to the stored enum value. 1.200 + * 1.201 + * @param aResult the string representing the enum tag 1.202 + * @param aRealTag wheter we want to have the real tag or the saved one 1.203 + */ 1.204 + void GetEnumString(nsAString& aResult, bool aRealTag) const; 1.205 + 1.206 + // Methods to get access to atoms we may have 1.207 + // Returns the number of atoms we have; 0 if we have none. It's OK 1.208 + // to call this without checking the type first; it handles that. 1.209 + uint32_t GetAtomCount() const; 1.210 + // Returns the atom at aIndex (0-based). Do not call this with 1.211 + // aIndex >= GetAtomCount(). 1.212 + nsIAtom* AtomAt(int32_t aIndex) const; 1.213 + 1.214 + uint32_t HashValue() const; 1.215 + bool Equals(const nsAttrValue& aOther) const; 1.216 + // aCaseSensitive == eIgnoreCase means ASCII case-insenstive matching 1.217 + bool Equals(const nsAString& aValue, nsCaseTreatment aCaseSensitive) const; 1.218 + bool Equals(nsIAtom* aValue, nsCaseTreatment aCaseSensitive) const; 1.219 + 1.220 + /** 1.221 + * Compares this object with aOther according to their string representation. 1.222 + * 1.223 + * For example, when called on an object with type eInteger and value 4, and 1.224 + * given aOther of type eString and value "4", EqualsAsStrings will return 1.225 + * true (while Equals will return false). 1.226 + */ 1.227 + bool EqualsAsStrings(const nsAttrValue& aOther) const; 1.228 + 1.229 + /** 1.230 + * Returns true if this AttrValue is equal to the given atom, or is an 1.231 + * array which contains the given atom. 1.232 + */ 1.233 + bool Contains(nsIAtom* aValue, nsCaseTreatment aCaseSensitive) const; 1.234 + /** 1.235 + * Returns true if this AttrValue is an atom equal to the given 1.236 + * string, or is an array of atoms which contains the given string. 1.237 + * This always does a case-sensitive comparison. 1.238 + */ 1.239 + bool Contains(const nsAString& aValue) const; 1.240 + 1.241 + void ParseAtom(const nsAString& aValue); 1.242 + void ParseAtomArray(const nsAString& aValue); 1.243 + void ParseStringOrAtom(const nsAString& aValue); 1.244 + 1.245 + /** 1.246 + * Structure for a mapping from int (enum) values to strings. When you use 1.247 + * it you generally create an array of them. 1.248 + * Instantiate like this: 1.249 + * EnumTable myTable[] = { 1.250 + * { "string1", 1 }, 1.251 + * { "string2", 2 }, 1.252 + * { 0 } 1.253 + * } 1.254 + */ 1.255 + struct EnumTable { 1.256 + /** The string the value maps to */ 1.257 + const char* tag; 1.258 + /** The enum value that maps to this string */ 1.259 + int16_t value; 1.260 + }; 1.261 + 1.262 + /** 1.263 + * Parse into an enum value. 1.264 + * 1.265 + * @param aValue the string to find the value for 1.266 + * @param aTable the enumeration to map with 1.267 + * @param aCaseSensitive specify if the parsing has to be case sensitive 1.268 + * @param aDefaultValue if non-null, this function will always return true. 1.269 + * Failure to parse aValue as one of the values in aTable will just 1.270 + * cause aDefaultValue->value to be stored as the enumeration value. 1.271 + * @return whether the enum value was found or not 1.272 + */ 1.273 + bool ParseEnumValue(const nsAString& aValue, 1.274 + const EnumTable* aTable, 1.275 + bool aCaseSensitive, 1.276 + const EnumTable* aDefaultValue = nullptr); 1.277 + 1.278 + /** 1.279 + * Parse a string into an integer. Can optionally parse percent (n%). 1.280 + * This method explicitly sets a lower bound of zero on the element, 1.281 + * whether it be percent or raw integer. 1.282 + * 1.283 + * @param aString the string to parse 1.284 + * @return whether the value could be parsed 1.285 + * 1.286 + * @see http://www.whatwg.org/html/#rules-for-parsing-dimension-values 1.287 + */ 1.288 + bool ParseSpecialIntValue(const nsAString& aString); 1.289 + 1.290 + 1.291 + /** 1.292 + * Parse a string value into an integer. 1.293 + * 1.294 + * @param aString the string to parse 1.295 + * @return whether the value could be parsed 1.296 + */ 1.297 + bool ParseIntValue(const nsAString& aString) { 1.298 + return ParseIntWithBounds(aString, INT32_MIN, INT32_MAX); 1.299 + } 1.300 + 1.301 + /** 1.302 + * Parse a string value into an integer with minimum value and maximum value. 1.303 + * 1.304 + * @param aString the string to parse 1.305 + * @param aMin the minimum value (if value is less it will be bumped up) 1.306 + * @param aMax the maximum value (if value is greater it will be chopped down) 1.307 + * @return whether the value could be parsed 1.308 + */ 1.309 + bool ParseIntWithBounds(const nsAString& aString, int32_t aMin, 1.310 + int32_t aMax = INT32_MAX); 1.311 + 1.312 + /** 1.313 + * Parse a string value into a non-negative integer. 1.314 + * This method follows the rules for parsing non-negative integer from: 1.315 + * http://dev.w3.org/html5/spec/infrastructure.html#rules-for-parsing-non-negative-integers 1.316 + * 1.317 + * @param aString the string to parse 1.318 + * @return whether the value is valid 1.319 + */ 1.320 + bool ParseNonNegativeIntValue(const nsAString& aString); 1.321 + 1.322 + /** 1.323 + * Parse a string value into a positive integer. 1.324 + * This method follows the rules for parsing non-negative integer from: 1.325 + * http://dev.w3.org/html5/spec/infrastructure.html#rules-for-parsing-non-negative-integers 1.326 + * In addition of these rules, the value has to be greater than zero. 1.327 + * 1.328 + * This is generally used for parsing content attributes which reflecting IDL 1.329 + * attributes are limited to only non-negative numbers greater than zero, see: 1.330 + * http://dev.w3.org/html5/spec/common-dom-interfaces.html#limited-to-only-non-negative-numbers-greater-than-zero 1.331 + * 1.332 + * @param aString the string to parse 1.333 + * @return whether the value was valid 1.334 + */ 1.335 + bool ParsePositiveIntValue(const nsAString& aString); 1.336 + 1.337 + /** 1.338 + * Parse a string into a color. This implements what HTML5 calls the 1.339 + * "rules for parsing a legacy color value". 1.340 + * 1.341 + * @param aString the string to parse 1.342 + * @return whether the value could be parsed 1.343 + */ 1.344 + bool ParseColor(const nsAString& aString); 1.345 + 1.346 + /** 1.347 + * Parse a string value into a double-precision floating point value. 1.348 + * 1.349 + * @param aString the string to parse 1.350 + * @return whether the value could be parsed 1.351 + */ 1.352 + bool ParseDoubleValue(const nsAString& aString); 1.353 + 1.354 + /** 1.355 + * Parse a lazy URI. This just sets up the storage for the URI; it 1.356 + * doesn't actually allocate it. 1.357 + */ 1.358 + bool ParseLazyURIValue(const nsAString& aString); 1.359 + 1.360 + /** 1.361 + * Parse a margin string of format 'top, right, bottom, left' into 1.362 + * an nsIntMargin. 1.363 + * 1.364 + * @param aString the string to parse 1.365 + * @return whether the value could be parsed 1.366 + */ 1.367 + bool ParseIntMarginValue(const nsAString& aString); 1.368 + 1.369 + /** 1.370 + * Convert a URL nsAttrValue to an Image nsAttrValue. 1.371 + * 1.372 + * @param aDocument the document this nsAttrValue belongs to. 1.373 + */ 1.374 + void LoadImage(nsIDocument* aDocument); 1.375 + 1.376 + /** 1.377 + * Parse a string into a CSS style rule. 1.378 + * 1.379 + * @param aString the style attribute value to be parsed. 1.380 + * @param aElement the element the attribute is set on. 1.381 + */ 1.382 + bool ParseStyleAttribute(const nsAString& aString, 1.383 + nsStyledElementNotElementCSSInlineStyle* aElement); 1.384 + 1.385 + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 1.386 + 1.387 +private: 1.388 + // These have to be the same as in ValueType 1.389 + enum ValueBaseType { 1.390 + eStringBase = eString, // 00 1.391 + eOtherBase = 0x01, // 01 1.392 + eAtomBase = eAtom, // 10 1.393 + eIntegerBase = 0x03 // 11 1.394 + }; 1.395 + 1.396 + inline ValueBaseType BaseType() const; 1.397 + inline bool IsSVGType(ValueType aType) const; 1.398 + 1.399 + /** 1.400 + * Get the index of an EnumTable in the sEnumTableArray. 1.401 + * If the EnumTable is not in the sEnumTableArray, it is added. 1.402 + * 1.403 + * @param aTable the EnumTable to get the index of. 1.404 + * @return the index of the EnumTable. 1.405 + */ 1.406 + int16_t GetEnumTableIndex(const EnumTable* aTable); 1.407 + 1.408 + inline void SetPtrValueAndType(void* aValue, ValueBaseType aType); 1.409 + void SetIntValueAndType(int32_t aValue, ValueType aType, 1.410 + const nsAString* aStringValue); 1.411 + void SetColorValue(nscolor aColor, const nsAString& aString); 1.412 + void SetMiscAtomOrString(const nsAString* aValue); 1.413 + void ResetMiscAtomOrString(); 1.414 + void SetSVGType(ValueType aType, const void* aValue, 1.415 + const nsAString* aSerialized); 1.416 + inline void ResetIfSet(); 1.417 + 1.418 + inline void* GetPtr() const; 1.419 + inline MiscContainer* GetMiscContainer() const; 1.420 + inline int32_t GetIntInternal() const; 1.421 + 1.422 + // Clears the current MiscContainer. This will return null if there is no 1.423 + // existing container. 1.424 + MiscContainer* ClearMiscContainer(); 1.425 + // Like ClearMiscContainer, except allocates a new container if one does not 1.426 + // exist already. 1.427 + MiscContainer* EnsureEmptyMiscContainer(); 1.428 + bool EnsureEmptyAtomArray(); 1.429 + already_AddRefed<nsStringBuffer> 1.430 + GetStringBuffer(const nsAString& aValue) const; 1.431 + // aStrict is set true if stringifying the return value equals with 1.432 + // aValue. 1.433 + int32_t StringToInteger(const nsAString& aValue, 1.434 + bool* aStrict, 1.435 + nsresult* aErrorCode, 1.436 + bool aCanBePercent = false, 1.437 + bool* aIsPercent = nullptr) const; 1.438 + // Given an enum table and a particular entry in that table, return 1.439 + // the actual integer value we should store. 1.440 + int32_t EnumTableEntryToValue(const EnumTable* aEnumTable, 1.441 + const EnumTable* aTableEntry); 1.442 + 1.443 + static nsTArray<const EnumTable*>* sEnumTableArray; 1.444 + 1.445 + uintptr_t mBits; 1.446 +}; 1.447 + 1.448 +inline const nsAttrValue& 1.449 +nsAttrValue::operator=(const nsAttrValue& aOther) 1.450 +{ 1.451 + SetTo(aOther); 1.452 + return *this; 1.453 +} 1.454 + 1.455 +inline nsIAtom* 1.456 +nsAttrValue::GetAtomValue() const 1.457 +{ 1.458 + NS_PRECONDITION(Type() == eAtom, "wrong type"); 1.459 + return reinterpret_cast<nsIAtom*>(GetPtr()); 1.460 +} 1.461 + 1.462 +inline nsAttrValue::ValueBaseType 1.463 +nsAttrValue::BaseType() const 1.464 +{ 1.465 + return static_cast<ValueBaseType>(mBits & NS_ATTRVALUE_BASETYPE_MASK); 1.466 +} 1.467 + 1.468 +inline void* 1.469 +nsAttrValue::GetPtr() const 1.470 +{ 1.471 + NS_ASSERTION(BaseType() != eIntegerBase, 1.472 + "getting pointer from non-pointer"); 1.473 + return reinterpret_cast<void*>(mBits & NS_ATTRVALUE_POINTERVALUE_MASK); 1.474 +} 1.475 + 1.476 +inline bool 1.477 +nsAttrValue::IsEmptyString() const 1.478 +{ 1.479 + return !mBits; 1.480 +} 1.481 + 1.482 +inline void 1.483 +nsAttrValue::ToString(mozilla::dom::DOMString& aResult) const 1.484 +{ 1.485 + switch (Type()) { 1.486 + case eString: 1.487 + { 1.488 + nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr()); 1.489 + if (str) { 1.490 + aResult.SetStringBuffer(str, str->StorageSize()/sizeof(char16_t) - 1); 1.491 + } 1.492 + // else aResult is already empty 1.493 + return; 1.494 + } 1.495 + case eAtom: 1.496 + { 1.497 + nsIAtom *atom = static_cast<nsIAtom*>(GetPtr()); 1.498 + aResult.SetStringBuffer(atom->GetStringBuffer(), atom->GetLength()); 1.499 + break; 1.500 + } 1.501 + default: 1.502 + { 1.503 + ToString(aResult.AsAString()); 1.504 + } 1.505 + } 1.506 +} 1.507 + 1.508 +#endif