1/*
2 * Copyright (C) 2016 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include <wtf/Optional.h>
29#include <wtf/TriState.h>
30
31namespace JSC {
32
33class DefinePropertyAttributes {
34public:
35 static_assert(FalseTriState == 0, "FalseTriState is 0.");
36 static_assert(TrueTriState == 1, "TrueTriState is 1.");
37 static_assert(MixedTriState == 2, "MixedTriState is 2.");
38
39 static const unsigned ConfigurableShift = 0;
40 static const unsigned EnumerableShift = 2;
41 static const unsigned WritableShift = 4;
42 static const unsigned ValueShift = 6;
43 static const unsigned GetShift = 7;
44 static const unsigned SetShift = 8;
45
46 DefinePropertyAttributes()
47 : m_attributes(
48 (MixedTriState << ConfigurableShift)
49 | (MixedTriState << EnumerableShift)
50 | (MixedTriState << WritableShift)
51 | (0 << ValueShift)
52 | (0 << GetShift)
53 | (0 << SetShift))
54 {
55 }
56
57 explicit DefinePropertyAttributes(unsigned attributes)
58 : m_attributes(attributes)
59 {
60 }
61
62 unsigned rawRepresentation() const
63 {
64 return m_attributes;
65 }
66
67 bool hasValue() const
68 {
69 return m_attributes & (0b1 << ValueShift);
70 }
71
72 void setValue()
73 {
74 m_attributes = m_attributes | (0b1 << ValueShift);
75 }
76
77 bool hasGet() const
78 {
79 return m_attributes & (0b1 << GetShift);
80 }
81
82 void setGet()
83 {
84 m_attributes = m_attributes | (0b1 << GetShift);
85 }
86
87 bool hasSet() const
88 {
89 return m_attributes & (0b1 << SetShift);
90 }
91
92 void setSet()
93 {
94 m_attributes = m_attributes | (0b1 << SetShift);
95 }
96
97 bool hasWritable() const
98 {
99 return extractTriState(WritableShift) != MixedTriState;
100 }
101
102 Optional<bool> writable() const
103 {
104 if (!hasWritable())
105 return WTF::nullopt;
106 return extractTriState(WritableShift) == TrueTriState;
107 }
108
109 bool hasConfigurable() const
110 {
111 return extractTriState(ConfigurableShift) != MixedTriState;
112 }
113
114 Optional<bool> configurable() const
115 {
116 if (!hasConfigurable())
117 return WTF::nullopt;
118 return extractTriState(ConfigurableShift) == TrueTriState;
119 }
120
121 bool hasEnumerable() const
122 {
123 return extractTriState(EnumerableShift) != MixedTriState;
124 }
125
126 Optional<bool> enumerable() const
127 {
128 if (!hasEnumerable())
129 return WTF::nullopt;
130 return extractTriState(EnumerableShift) == TrueTriState;
131 }
132
133 void setWritable(bool value)
134 {
135 fillWithTriState(value ? TrueTriState : FalseTriState, WritableShift);
136 }
137
138 void setConfigurable(bool value)
139 {
140 fillWithTriState(value ? TrueTriState : FalseTriState, ConfigurableShift);
141 }
142
143 void setEnumerable(bool value)
144 {
145 fillWithTriState(value ? TrueTriState : FalseTriState, EnumerableShift);
146 }
147
148private:
149 void fillWithTriState(TriState state, unsigned shift)
150 {
151 unsigned mask = 0b11 << shift;
152 m_attributes = (m_attributes & ~mask) | (state << shift);
153 }
154
155 TriState extractTriState(unsigned shift) const
156 {
157 return static_cast<TriState>((m_attributes >> shift) & 0b11);
158 }
159
160 unsigned m_attributes;
161};
162
163
164} // namespace JSC
165