1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_NAME_H_
6 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_NAME_H_
7 
8 #include "base/optional.h"
9 #include "third_party/blink/renderer/core/css/css_property_names.h"
10 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
11 #include "third_party/blink/renderer/platform/wtf/vector_traits.h"
12 
13 namespace blink {
14 
15 class ExecutionContext;
16 
17 // This class may be used to represent the name of any valid CSS property,
18 // including custom properties.
19 class CORE_EXPORT CSSPropertyName {
20   DISALLOW_NEW();
21  public:
CSSPropertyName(CSSPropertyID property_id)22   explicit CSSPropertyName(CSSPropertyID property_id)
23       : value_(static_cast<int>(property_id)) {
24     DCHECK_NE(Id(), CSSPropertyID::kInvalid);
25     DCHECK_NE(Id(), CSSPropertyID::kVariable);
26   }
27 
CSSPropertyName(const AtomicString & custom_property_name)28   explicit CSSPropertyName(const AtomicString& custom_property_name)
29       : value_(static_cast<int>(CSSPropertyID::kVariable)),
30         custom_property_name_(custom_property_name) {
31     DCHECK(!custom_property_name.IsNull());
32   }
33 
From(const ExecutionContext * execution_context,const String & value)34   static base::Optional<CSSPropertyName> From(
35       const ExecutionContext* execution_context,
36       const String& value) {
37     const CSSPropertyID property_id = cssPropertyID(execution_context, value);
38     if (property_id == CSSPropertyID::kInvalid)
39       return base::nullopt;
40     if (property_id == CSSPropertyID::kVariable)
41       return base::make_optional(CSSPropertyName(AtomicString(value)));
42     return base::make_optional(CSSPropertyName(property_id));
43   }
44 
45   bool operator==(const CSSPropertyName&) const;
46   bool operator!=(const CSSPropertyName& other) const {
47     return !(*this == other);
48   }
49 
Id()50   CSSPropertyID Id() const {
51     DCHECK(!IsEmptyValue() && !IsDeletedValue());
52     return static_cast<CSSPropertyID>(value_);
53   }
54 
IsCustomProperty()55   bool IsCustomProperty() const { return Id() == CSSPropertyID::kVariable; }
56 
57   AtomicString ToAtomicString() const;
58 
59  private:
60   // For HashTraits::EmptyValue().
61   static constexpr int kEmptyValue = -1;
62   // For HashTraits::ConstructDeletedValue(...).
63   static constexpr int kDeletedValue = -2;
64 
CSSPropertyName(int value)65   explicit CSSPropertyName(int value) : value_(value) {
66     DCHECK(value == kEmptyValue || value == kDeletedValue);
67   }
68 
69   unsigned GetHash() const;
IsEmptyValue()70   bool IsEmptyValue() const { return value_ == kEmptyValue; }
IsDeletedValue()71   bool IsDeletedValue() const { return value_ == kDeletedValue; }
72 
73   // The value_ field is either a CSSPropertyID, kEmptyValue, or
74   // kDeletedValue.
75   int value_;
76   AtomicString custom_property_name_;
77 
78   friend class CSSPropertyNameTest;
79   friend struct ::WTF::DefaultHash<blink::CSSPropertyName>;
80   friend struct ::WTF::HashTraits<blink::CSSPropertyName>;
81 };
82 
83 }  // namespace blink
84 
85 namespace WTF {
86 
87 template <>
88 struct DefaultHash<blink::CSSPropertyName> {
89   struct Hash {
90     STATIC_ONLY(Hash);
91     static unsigned GetHash(const blink::CSSPropertyName& name) {
92       return name.GetHash();
93     }
94 
95     static bool Equal(const blink::CSSPropertyName& a,
96                       const blink::CSSPropertyName& b) {
97       return a == b;
98     }
99 
100     static const bool safe_to_compare_to_empty_or_deleted = true;
101   };
102 };
103 
104 template <>
105 struct HashTraits<blink::CSSPropertyName>
106     : SimpleClassHashTraits<blink::CSSPropertyName> {
107   using CSSPropertyName = blink::CSSPropertyName;
108   static const bool kEmptyValueIsZero = false;
109   static const bool kNeedsDestruction = true;
110   static void ConstructDeletedValue(CSSPropertyName& slot, bool) {
111     new (NotNull, &slot) CSSPropertyName(CSSPropertyName::kDeletedValue);
112   }
113   static bool IsDeletedValue(CSSPropertyName value) {
114     return value.IsDeletedValue();
115   }
116   static blink::CSSPropertyName EmptyValue() {
117     return blink::CSSPropertyName(CSSPropertyName::kEmptyValue);
118   }
119 };
120 
121 }  // namespace WTF
122 
123 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::CSSPropertyName)
124 
125 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_NAME_H_
126