Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /* |
michael@0 | 7 | * representation of a declaration block (or style attribute) in a CSS |
michael@0 | 8 | * stylesheet |
michael@0 | 9 | */ |
michael@0 | 10 | |
michael@0 | 11 | #ifndef mozilla_css_Declaration_h |
michael@0 | 12 | #define mozilla_css_Declaration_h |
michael@0 | 13 | |
michael@0 | 14 | // This header is in EXPORTS because it's used in several places in content/, |
michael@0 | 15 | // but it's not really a public interface. |
michael@0 | 16 | #ifndef MOZILLA_INTERNAL_API |
michael@0 | 17 | #error "This file should only be included within libxul" |
michael@0 | 18 | #endif |
michael@0 | 19 | |
michael@0 | 20 | #include "mozilla/Attributes.h" |
michael@0 | 21 | #include "mozilla/MemoryReporting.h" |
michael@0 | 22 | #include "CSSVariableDeclarations.h" |
michael@0 | 23 | #include "nsCSSDataBlock.h" |
michael@0 | 24 | #include "nsCSSProperty.h" |
michael@0 | 25 | #include "nsCSSProps.h" |
michael@0 | 26 | #include "nsStringFwd.h" |
michael@0 | 27 | #include "nsTArray.h" |
michael@0 | 28 | #include <stdio.h> |
michael@0 | 29 | |
michael@0 | 30 | namespace mozilla { |
michael@0 | 31 | namespace css { |
michael@0 | 32 | |
michael@0 | 33 | // Declaration objects have unusual lifetime rules. Every declaration |
michael@0 | 34 | // begins life in an invalid state which ends when InitializeEmpty or |
michael@0 | 35 | // CompressFrom is called upon it. After that, it can be attached to |
michael@0 | 36 | // exactly one style rule, and will be destroyed when that style rule |
michael@0 | 37 | // is destroyed. A declaration becomes immutable when its style rule's |
michael@0 | 38 | // |RuleMatched| method is called; after that, it must be copied before |
michael@0 | 39 | // it can be modified, which is taken care of by |EnsureMutable|. |
michael@0 | 40 | |
michael@0 | 41 | class Declaration { |
michael@0 | 42 | public: |
michael@0 | 43 | /** |
michael@0 | 44 | * Construct an |Declaration| that is in an invalid state (null |
michael@0 | 45 | * |mData|) and cannot be used until its |CompressFrom| method or |
michael@0 | 46 | * |InitializeEmpty| method is called. |
michael@0 | 47 | */ |
michael@0 | 48 | Declaration(); |
michael@0 | 49 | |
michael@0 | 50 | Declaration(const Declaration& aCopy); |
michael@0 | 51 | |
michael@0 | 52 | ~Declaration(); |
michael@0 | 53 | |
michael@0 | 54 | /** |
michael@0 | 55 | * |ValueAppended| must be called to maintain this declaration's |
michael@0 | 56 | * |mOrder| whenever a property is parsed into an expanded data block |
michael@0 | 57 | * for this declaration. aProperty must not be a shorthand. |
michael@0 | 58 | */ |
michael@0 | 59 | void ValueAppended(nsCSSProperty aProperty); |
michael@0 | 60 | |
michael@0 | 61 | void RemoveProperty(nsCSSProperty aProperty); |
michael@0 | 62 | |
michael@0 | 63 | bool HasProperty(nsCSSProperty aProperty) const; |
michael@0 | 64 | |
michael@0 | 65 | void GetValue(nsCSSProperty aProperty, nsAString& aValue) const; |
michael@0 | 66 | void GetAuthoredValue(nsCSSProperty aProperty, nsAString& aValue) const; |
michael@0 | 67 | |
michael@0 | 68 | bool HasImportantData() const { |
michael@0 | 69 | return mImportantData || mImportantVariables; |
michael@0 | 70 | } |
michael@0 | 71 | bool GetValueIsImportant(nsCSSProperty aProperty) const; |
michael@0 | 72 | bool GetValueIsImportant(const nsAString& aProperty) const; |
michael@0 | 73 | |
michael@0 | 74 | /** |
michael@0 | 75 | * Adds a custom property declaration to this object. |
michael@0 | 76 | * |
michael@0 | 77 | * @param aName The variable name (i.e., without the "--" prefix). |
michael@0 | 78 | * @param aType The type of value the variable has. |
michael@0 | 79 | * @param aValue The value of the variable, if aType is |
michael@0 | 80 | * CSSVariableDeclarations::eTokenStream. |
michael@0 | 81 | * @param aIsImportant Whether the declaration is !important. |
michael@0 | 82 | * @param aOverrideImportant When aIsImportant is false, whether an |
michael@0 | 83 | * existing !important declaration will be overridden. |
michael@0 | 84 | */ |
michael@0 | 85 | void AddVariableDeclaration(const nsAString& aName, |
michael@0 | 86 | CSSVariableDeclarations::Type aType, |
michael@0 | 87 | const nsString& aValue, |
michael@0 | 88 | bool aIsImportant, |
michael@0 | 89 | bool aOverrideImportant); |
michael@0 | 90 | |
michael@0 | 91 | /** |
michael@0 | 92 | * Removes a custom property declaration from this object. |
michael@0 | 93 | * |
michael@0 | 94 | * @param aName The variable name (i.e., without the "--" prefix). |
michael@0 | 95 | */ |
michael@0 | 96 | void RemoveVariableDeclaration(const nsAString& aName); |
michael@0 | 97 | |
michael@0 | 98 | /** |
michael@0 | 99 | * Returns whether a custom property declaration for a variable with |
michael@0 | 100 | * a given name exists on this object. |
michael@0 | 101 | * |
michael@0 | 102 | * @param aName The variable name (i.e., without the "--" prefix). |
michael@0 | 103 | */ |
michael@0 | 104 | bool HasVariableDeclaration(const nsAString& aName) const; |
michael@0 | 105 | |
michael@0 | 106 | /** |
michael@0 | 107 | * Gets the string value for a custom property declaration of a variable |
michael@0 | 108 | * with a given name. |
michael@0 | 109 | * |
michael@0 | 110 | * @param aName The variable name (i.e., without the "--" prefix). |
michael@0 | 111 | * @param aValue Out parameter into which the variable's value will be |
michael@0 | 112 | * stored. If the value is 'initial' or 'inherit', that exact string |
michael@0 | 113 | * will be stored in aValue. |
michael@0 | 114 | */ |
michael@0 | 115 | void GetVariableDeclaration(const nsAString& aName, nsAString& aValue) const; |
michael@0 | 116 | |
michael@0 | 117 | /** |
michael@0 | 118 | * Returns whether the custom property declaration for a variable with |
michael@0 | 119 | * the given name was !important. |
michael@0 | 120 | */ |
michael@0 | 121 | bool GetVariableValueIsImportant(const nsAString& aName) const; |
michael@0 | 122 | |
michael@0 | 123 | uint32_t Count() const { |
michael@0 | 124 | return mOrder.Length(); |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | // Returns whether we actually had a property at aIndex |
michael@0 | 128 | bool GetNthProperty(uint32_t aIndex, nsAString& aReturn) const; |
michael@0 | 129 | |
michael@0 | 130 | void ToString(nsAString& aString) const; |
michael@0 | 131 | |
michael@0 | 132 | nsCSSCompressedDataBlock* GetNormalBlock() const { return mData; } |
michael@0 | 133 | nsCSSCompressedDataBlock* GetImportantBlock() const { return mImportantData; } |
michael@0 | 134 | |
michael@0 | 135 | /** |
michael@0 | 136 | * Initialize this declaration as holding no data. Cannot fail. |
michael@0 | 137 | */ |
michael@0 | 138 | void InitializeEmpty(); |
michael@0 | 139 | |
michael@0 | 140 | /** |
michael@0 | 141 | * Transfer all of the state from |aExpandedData| into this declaration. |
michael@0 | 142 | * After calling, |aExpandedData| should be in its initial state. |
michael@0 | 143 | * Callers must make sure mOrder is updated as necessary. |
michael@0 | 144 | */ |
michael@0 | 145 | void CompressFrom(nsCSSExpandedDataBlock *aExpandedData) { |
michael@0 | 146 | NS_ABORT_IF_FALSE(!mData, "oops"); |
michael@0 | 147 | NS_ABORT_IF_FALSE(!mImportantData, "oops"); |
michael@0 | 148 | aExpandedData->Compress(getter_Transfers(mData), |
michael@0 | 149 | getter_Transfers(mImportantData)); |
michael@0 | 150 | aExpandedData->AssertInitialState(); |
michael@0 | 151 | } |
michael@0 | 152 | |
michael@0 | 153 | /** |
michael@0 | 154 | * Transfer all of the state from this declaration into |
michael@0 | 155 | * |aExpandedData| and put this declaration temporarily into an |
michael@0 | 156 | * invalid state (ended by |CompressFrom| or |InitializeEmpty|) that |
michael@0 | 157 | * should last only during parsing. During this time only |
michael@0 | 158 | * |ValueAppended| should be called. |
michael@0 | 159 | */ |
michael@0 | 160 | void ExpandTo(nsCSSExpandedDataBlock *aExpandedData) { |
michael@0 | 161 | AssertMutable(); |
michael@0 | 162 | aExpandedData->AssertInitialState(); |
michael@0 | 163 | |
michael@0 | 164 | NS_ABORT_IF_FALSE(mData, "oops"); |
michael@0 | 165 | aExpandedData->Expand(mData.forget(), mImportantData.forget()); |
michael@0 | 166 | } |
michael@0 | 167 | |
michael@0 | 168 | /** |
michael@0 | 169 | * Do what |nsIStyleRule::MapRuleInfoInto| needs to do for a style |
michael@0 | 170 | * rule using this declaration for storage. |
michael@0 | 171 | */ |
michael@0 | 172 | void MapNormalRuleInfoInto(nsRuleData *aRuleData) const { |
michael@0 | 173 | NS_ABORT_IF_FALSE(mData, "called while expanded"); |
michael@0 | 174 | mData->MapRuleInfoInto(aRuleData); |
michael@0 | 175 | if (mVariables) { |
michael@0 | 176 | mVariables->MapRuleInfoInto(aRuleData); |
michael@0 | 177 | } |
michael@0 | 178 | } |
michael@0 | 179 | void MapImportantRuleInfoInto(nsRuleData *aRuleData) const { |
michael@0 | 180 | NS_ABORT_IF_FALSE(mData, "called while expanded"); |
michael@0 | 181 | NS_ABORT_IF_FALSE(mImportantData || mImportantVariables, |
michael@0 | 182 | "must have important data or variables"); |
michael@0 | 183 | if (mImportantData) { |
michael@0 | 184 | mImportantData->MapRuleInfoInto(aRuleData); |
michael@0 | 185 | } |
michael@0 | 186 | if (mImportantVariables) { |
michael@0 | 187 | mImportantVariables->MapRuleInfoInto(aRuleData); |
michael@0 | 188 | } |
michael@0 | 189 | } |
michael@0 | 190 | |
michael@0 | 191 | /** |
michael@0 | 192 | * Attempt to replace the value for |aProperty| stored in this |
michael@0 | 193 | * declaration with the matching value from |aFromBlock|. |
michael@0 | 194 | * This method may only be called on a mutable declaration. |
michael@0 | 195 | * It will fail (returning false) if |aProperty| is shorthand, |
michael@0 | 196 | * is not already in this declaration, or does not have the indicated |
michael@0 | 197 | * importance level. If it returns true, it erases the value in |
michael@0 | 198 | * |aFromBlock|. |aChanged| is set to true if the declaration |
michael@0 | 199 | * changed as a result of the call, and to false otherwise. |
michael@0 | 200 | */ |
michael@0 | 201 | bool TryReplaceValue(nsCSSProperty aProperty, bool aIsImportant, |
michael@0 | 202 | nsCSSExpandedDataBlock& aFromBlock, |
michael@0 | 203 | bool* aChanged) |
michael@0 | 204 | { |
michael@0 | 205 | AssertMutable(); |
michael@0 | 206 | NS_ABORT_IF_FALSE(mData, "called while expanded"); |
michael@0 | 207 | |
michael@0 | 208 | if (nsCSSProps::IsShorthand(aProperty)) { |
michael@0 | 209 | *aChanged = false; |
michael@0 | 210 | return false; |
michael@0 | 211 | } |
michael@0 | 212 | nsCSSCompressedDataBlock *block = aIsImportant ? mImportantData : mData; |
michael@0 | 213 | // mImportantData might be null |
michael@0 | 214 | if (!block) { |
michael@0 | 215 | *aChanged = false; |
michael@0 | 216 | return false; |
michael@0 | 217 | } |
michael@0 | 218 | |
michael@0 | 219 | #ifdef DEBUG |
michael@0 | 220 | { |
michael@0 | 221 | nsCSSCompressedDataBlock *other = aIsImportant ? mData : mImportantData; |
michael@0 | 222 | NS_ABORT_IF_FALSE(!other || !other->ValueFor(aProperty) || |
michael@0 | 223 | !block->ValueFor(aProperty), |
michael@0 | 224 | "Property both important and not?"); |
michael@0 | 225 | } |
michael@0 | 226 | #endif |
michael@0 | 227 | return block->TryReplaceValue(aProperty, aFromBlock, aChanged); |
michael@0 | 228 | } |
michael@0 | 229 | |
michael@0 | 230 | bool HasNonImportantValueFor(nsCSSProperty aProperty) const { |
michael@0 | 231 | NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aProperty), "must be longhand"); |
michael@0 | 232 | return !!mData->ValueFor(aProperty); |
michael@0 | 233 | } |
michael@0 | 234 | |
michael@0 | 235 | /** |
michael@0 | 236 | * Return whether |this| may be modified. |
michael@0 | 237 | */ |
michael@0 | 238 | bool IsMutable() const { |
michael@0 | 239 | return !mImmutable; |
michael@0 | 240 | } |
michael@0 | 241 | |
michael@0 | 242 | /** |
michael@0 | 243 | * Copy |this|, if necessary to ensure that it can be modified. |
michael@0 | 244 | */ |
michael@0 | 245 | Declaration* EnsureMutable(); |
michael@0 | 246 | |
michael@0 | 247 | /** |
michael@0 | 248 | * Crash if |this| cannot be modified. |
michael@0 | 249 | */ |
michael@0 | 250 | void AssertMutable() const { |
michael@0 | 251 | NS_ABORT_IF_FALSE(IsMutable(), "someone forgot to call EnsureMutable"); |
michael@0 | 252 | } |
michael@0 | 253 | |
michael@0 | 254 | /** |
michael@0 | 255 | * Mark this declaration as unmodifiable. It's 'const' so it can |
michael@0 | 256 | * be called from ToString. |
michael@0 | 257 | */ |
michael@0 | 258 | void SetImmutable() const { mImmutable = true; } |
michael@0 | 259 | |
michael@0 | 260 | /** |
michael@0 | 261 | * Clear the data, in preparation for its replacement with entirely |
michael@0 | 262 | * new data by a call to |CompressFrom|. |
michael@0 | 263 | */ |
michael@0 | 264 | void ClearData() { |
michael@0 | 265 | AssertMutable(); |
michael@0 | 266 | mData = nullptr; |
michael@0 | 267 | mImportantData = nullptr; |
michael@0 | 268 | mVariables = nullptr; |
michael@0 | 269 | mImportantVariables = nullptr; |
michael@0 | 270 | mOrder.Clear(); |
michael@0 | 271 | mVariableOrder.Clear(); |
michael@0 | 272 | } |
michael@0 | 273 | |
michael@0 | 274 | #ifdef DEBUG |
michael@0 | 275 | void List(FILE* out = stdout, int32_t aIndent = 0) const; |
michael@0 | 276 | #endif |
michael@0 | 277 | |
michael@0 | 278 | private: |
michael@0 | 279 | Declaration& operator=(const Declaration& aCopy) MOZ_DELETE; |
michael@0 | 280 | bool operator==(const Declaration& aCopy) const MOZ_DELETE; |
michael@0 | 281 | |
michael@0 | 282 | void GetValue(nsCSSProperty aProperty, nsAString& aValue, |
michael@0 | 283 | nsCSSValue::Serialization aValueSerialization) const; |
michael@0 | 284 | |
michael@0 | 285 | static void AppendImportanceToString(bool aIsImportant, nsAString& aString); |
michael@0 | 286 | // return whether there was a value in |aValue| (i.e., it had a non-null unit) |
michael@0 | 287 | bool AppendValueToString(nsCSSProperty aProperty, nsAString& aResult) const; |
michael@0 | 288 | bool AppendValueToString(nsCSSProperty aProperty, nsAString& aResult, |
michael@0 | 289 | nsCSSValue::Serialization aValueSerialization) const; |
michael@0 | 290 | // Helper for ToString with strange semantics regarding aValue. |
michael@0 | 291 | void AppendPropertyAndValueToString(nsCSSProperty aProperty, |
michael@0 | 292 | nsAutoString& aValue, |
michael@0 | 293 | nsAString& aResult) const; |
michael@0 | 294 | // helper for ToString that serializes a custom property declaration for |
michael@0 | 295 | // a variable with the specified name |
michael@0 | 296 | void AppendVariableAndValueToString(const nsAString& aName, |
michael@0 | 297 | nsAString& aResult) const; |
michael@0 | 298 | |
michael@0 | 299 | public: |
michael@0 | 300 | /** |
michael@0 | 301 | * Returns the property at the given index in the ordered list of |
michael@0 | 302 | * declarations. For custom properties, eCSSPropertyExtra_variable |
michael@0 | 303 | * is returned. |
michael@0 | 304 | */ |
michael@0 | 305 | nsCSSProperty GetPropertyAt(uint32_t aIndex) const { |
michael@0 | 306 | uint32_t value = mOrder[aIndex]; |
michael@0 | 307 | if (value >= eCSSProperty_COUNT) { |
michael@0 | 308 | return eCSSPropertyExtra_variable; |
michael@0 | 309 | } |
michael@0 | 310 | return nsCSSProperty(value); |
michael@0 | 311 | } |
michael@0 | 312 | |
michael@0 | 313 | /** |
michael@0 | 314 | * Gets the name of the custom property at the given index in the ordered |
michael@0 | 315 | * list of declarations. |
michael@0 | 316 | */ |
michael@0 | 317 | void GetCustomPropertyNameAt(uint32_t aIndex, nsAString& aResult) const { |
michael@0 | 318 | MOZ_ASSERT(mOrder[aIndex] >= eCSSProperty_COUNT); |
michael@0 | 319 | uint32_t variableIndex = mOrder[aIndex] - eCSSProperty_COUNT; |
michael@0 | 320 | aResult.Truncate(); |
michael@0 | 321 | aResult.AppendLiteral("--"); |
michael@0 | 322 | aResult.Append(mVariableOrder[variableIndex]); |
michael@0 | 323 | } |
michael@0 | 324 | |
michael@0 | 325 | size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
michael@0 | 326 | |
michael@0 | 327 | private: |
michael@0 | 328 | // The order of properties in this declaration. Longhand properties are |
michael@0 | 329 | // represented by their nsCSSProperty value, and each custom property (--*) |
michael@0 | 330 | // is represented by a value that begins at eCSSProperty_COUNT. |
michael@0 | 331 | // |
michael@0 | 332 | // Subtracting eCSSProperty_COUNT from those values that represent custom |
michael@0 | 333 | // properties results in an index into mVariableOrder, which identifies the |
michael@0 | 334 | // specific variable the custom property declaration is for. |
michael@0 | 335 | nsAutoTArray<uint32_t, 8> mOrder; |
michael@0 | 336 | |
michael@0 | 337 | // variable names of custom properties found in mOrder |
michael@0 | 338 | nsTArray<nsString> mVariableOrder; |
michael@0 | 339 | |
michael@0 | 340 | // never null, except while expanded, or before the first call to |
michael@0 | 341 | // InitializeEmpty or CompressFrom. |
michael@0 | 342 | nsAutoPtr<nsCSSCompressedDataBlock> mData; |
michael@0 | 343 | |
michael@0 | 344 | // may be null |
michael@0 | 345 | nsAutoPtr<nsCSSCompressedDataBlock> mImportantData; |
michael@0 | 346 | |
michael@0 | 347 | // may be null |
michael@0 | 348 | nsAutoPtr<CSSVariableDeclarations> mVariables; |
michael@0 | 349 | |
michael@0 | 350 | // may be null |
michael@0 | 351 | nsAutoPtr<CSSVariableDeclarations> mImportantVariables; |
michael@0 | 352 | |
michael@0 | 353 | // set by style rules when |RuleMatched| is called; |
michael@0 | 354 | // also by ToString (hence the 'mutable'). |
michael@0 | 355 | mutable bool mImmutable; |
michael@0 | 356 | }; |
michael@0 | 357 | |
michael@0 | 358 | } // namespace css |
michael@0 | 359 | } // namespace mozilla |
michael@0 | 360 | |
michael@0 | 361 | #endif /* mozilla_css_Declaration_h */ |