|
9 | 9 |
|
10 | 10 | #include <folly/Conv.h> |
11 | 11 | #include <react/renderer/animationbackend/AnimatedPropsSerializer.h> |
| 12 | +#include <array> |
12 | 13 | #include <numbers> |
13 | 14 | #include <optional> |
| 15 | +#include <span> |
14 | 16 | #include <string_view> |
15 | 17 | #include <unordered_map> |
| 18 | +#include <utility> |
16 | 19 |
|
17 | 20 | namespace facebook::react { |
18 | 21 |
|
@@ -87,74 +90,110 @@ constexpr int CMD_TRANSFORM_PERSPECTIVE = 112; |
87 | 90 | constexpr int CMD_UNIT_PX = 202; |
88 | 91 | constexpr int CMD_UNIT_PERCENT = 203; |
89 | 92 |
|
| 93 | +using CommandEntry = std::pair<std::string_view, int>; |
| 94 | + |
| 95 | +// Group by name length so lookup only scans a small set of candidates. |
| 96 | +template <size_t MaxLength> |
| 97 | +constexpr auto indexCommandLengths(std::span<const CommandEntry> entries) { |
| 98 | + std::array<std::span<const CommandEntry>, MaxLength + 1> index{}; |
| 99 | + size_t start = 0; |
| 100 | + for (size_t length = 0; length < index.size(); ++length) { |
| 101 | + auto end = start; |
| 102 | + while (end < entries.size() && entries[end].first.size() == length) { |
| 103 | + ++end; |
| 104 | + } |
| 105 | + index[length] = entries.subspan(start, end - start); |
| 106 | + start = end; |
| 107 | + } |
| 108 | + return index; |
| 109 | +} |
| 110 | + |
| 111 | +std::optional<int> findCommand( |
| 112 | + std::string_view name, |
| 113 | + std::span<const std::span<const CommandEntry>> index) { |
| 114 | + if (name.size() >= index.size()) { |
| 115 | + return std::nullopt; |
| 116 | + } |
| 117 | + for (const auto& [key, command] : index[name.size()]) { |
| 118 | + if (key == name) { |
| 119 | + return command; |
| 120 | + } |
| 121 | + } |
| 122 | + return std::nullopt; |
| 123 | +} |
| 124 | + |
90 | 125 | std::optional<int> propNameToCommand(const std::string& name) { |
91 | | - static const std::unordered_map<std::string_view, int> kMap = { |
| 126 | + static constexpr std::array<CommandEntry, 37> kMap{{ |
| 127 | + {"color", CMD_COLOR}, |
| 128 | + {"zIndex", CMD_Z_INDEX}, |
92 | 129 | {"opacity", CMD_OPACITY}, |
93 | 130 | {"elevation", CMD_ELEVATION}, |
94 | | - {"zIndex", CMD_Z_INDEX}, |
95 | | - {"shadowOpacity", CMD_SHADOW_OPACITY}, |
96 | | - {"shadowRadius", CMD_SHADOW_RADIUS}, |
97 | | - {"backgroundColor", CMD_BACKGROUND_COLOR}, |
98 | | - {"color", CMD_COLOR}, |
99 | 131 | {"tintColor", CMD_TINT_COLOR}, |
100 | | - {"placeholderTextColor", CMD_PLACEHOLDER_TEXT_COLOR}, |
| 132 | + {"transform", CMD_START_OF_TRANSFORM}, |
| 133 | + {"borderColor", CMD_BORDER_COLOR}, |
101 | 134 | {"shadowColor", CMD_SHADOW_COLOR}, |
102 | 135 | {"borderRadius", CMD_BORDER_RADIUS}, |
| 136 | + {"outlineColor", CMD_OUTLINE_COLOR}, |
| 137 | + {"outlineWidth", CMD_OUTLINE_WIDTH}, |
| 138 | + {"shadowRadius", CMD_SHADOW_RADIUS}, |
| 139 | + {"outlineOffset", CMD_OUTLINE_OFFSET}, |
| 140 | + {"shadowOpacity", CMD_SHADOW_OPACITY}, |
| 141 | + {"borderEndColor", CMD_BORDER_END_COLOR}, |
| 142 | + {"borderTopColor", CMD_BORDER_TOP_COLOR}, |
| 143 | + {"backgroundColor", CMD_BACKGROUND_COLOR}, |
| 144 | + {"borderLeftColor", CMD_BORDER_LEFT_COLOR}, |
| 145 | + {"borderBlockColor", CMD_BORDER_BLOCK_COLOR}, |
| 146 | + {"borderRightColor", CMD_BORDER_RIGHT_COLOR}, |
| 147 | + {"borderStartColor", CMD_BORDER_START_COLOR}, |
| 148 | + {"borderBottomColor", CMD_BORDER_BOTTOM_COLOR}, |
| 149 | + {"borderEndEndRadius", CMD_BORDER_END_END_RADIUS}, |
| 150 | + {"borderTopEndRadius", CMD_BORDER_TOP_END_RADIUS}, |
| 151 | + {"borderBlockEndColor", CMD_BORDER_BLOCK_END_COLOR}, |
103 | 152 | {"borderTopLeftRadius", CMD_BORDER_TOP_LEFT_RADIUS}, |
| 153 | + {"borderEndStartRadius", CMD_BORDER_END_START_RADIUS}, |
| 154 | + {"borderStartEndRadius", CMD_BORDER_START_END_RADIUS}, |
104 | 155 | {"borderTopRightRadius", CMD_BORDER_TOP_RIGHT_RADIUS}, |
105 | 156 | {"borderTopStartRadius", CMD_BORDER_TOP_START_RADIUS}, |
106 | | - {"borderTopEndRadius", CMD_BORDER_TOP_END_RADIUS}, |
| 157 | + {"placeholderTextColor", CMD_PLACEHOLDER_TEXT_COLOR}, |
| 158 | + {"borderBlockStartColor", CMD_BORDER_BLOCK_START_COLOR}, |
| 159 | + {"borderBottomEndRadius", CMD_BORDER_BOTTOM_END_RADIUS}, |
107 | 160 | {"borderBottomLeftRadius", CMD_BORDER_BOTTOM_LEFT_RADIUS}, |
| 161 | + {"borderStartStartRadius", CMD_BORDER_START_START_RADIUS}, |
108 | 162 | {"borderBottomRightRadius", CMD_BORDER_BOTTOM_RIGHT_RADIUS}, |
109 | 163 | {"borderBottomStartRadius", CMD_BORDER_BOTTOM_START_RADIUS}, |
110 | | - {"borderBottomEndRadius", CMD_BORDER_BOTTOM_END_RADIUS}, |
111 | | - {"borderStartStartRadius", CMD_BORDER_START_START_RADIUS}, |
112 | | - {"borderStartEndRadius", CMD_BORDER_START_END_RADIUS}, |
113 | | - {"borderEndStartRadius", CMD_BORDER_END_START_RADIUS}, |
114 | | - {"borderEndEndRadius", CMD_BORDER_END_END_RADIUS}, |
115 | | - {"borderColor", CMD_BORDER_COLOR}, |
116 | | - {"borderTopColor", CMD_BORDER_TOP_COLOR}, |
117 | | - {"borderBottomColor", CMD_BORDER_BOTTOM_COLOR}, |
118 | | - {"borderLeftColor", CMD_BORDER_LEFT_COLOR}, |
119 | | - {"borderRightColor", CMD_BORDER_RIGHT_COLOR}, |
120 | | - {"borderStartColor", CMD_BORDER_START_COLOR}, |
121 | | - {"borderEndColor", CMD_BORDER_END_COLOR}, |
122 | | - {"borderBlockColor", CMD_BORDER_BLOCK_COLOR}, |
123 | | - {"borderBlockStartColor", CMD_BORDER_BLOCK_START_COLOR}, |
124 | | - {"borderBlockEndColor", CMD_BORDER_BLOCK_END_COLOR}, |
125 | | - {"outlineColor", CMD_OUTLINE_COLOR}, |
126 | | - {"outlineOffset", CMD_OUTLINE_OFFSET}, |
127 | | - {"outlineWidth", CMD_OUTLINE_WIDTH}, |
128 | | - {"transform", CMD_START_OF_TRANSFORM}, |
129 | | - }; |
130 | | - auto it = kMap.find(name); |
131 | | - if (it == kMap.end()) { |
132 | | - return std::nullopt; |
133 | | - } |
134 | | - return it->second; |
| 164 | + }}; |
| 165 | + static constexpr auto kIndex = |
| 166 | + indexCommandLengths<kMap.back().first.size()>(kMap); |
| 167 | + static_assert( |
| 168 | + kIndex.back().data() == |
| 169 | + std::span<const CommandEntry>{kMap}.last(kIndex.back().size()).data(), |
| 170 | + "Command entries must be sorted by name length"); |
| 171 | + return findCommand(name, kIndex); |
135 | 172 | } |
136 | 173 |
|
137 | 174 | std::optional<int> transformNameToCommand(const std::string& name) { |
138 | | - static const std::unordered_map<std::string_view, int> kMap = { |
139 | | - {"translateX", CMD_TRANSFORM_TRANSLATE_X}, |
140 | | - {"translateY", CMD_TRANSFORM_TRANSLATE_Y}, |
| 175 | + static constexpr std::array<CommandEntry, 13> kMap{{ |
141 | 176 | {"scale", CMD_TRANSFORM_SCALE}, |
| 177 | + {"skewX", CMD_TRANSFORM_SKEW_X}, |
| 178 | + {"skewY", CMD_TRANSFORM_SKEW_Y}, |
| 179 | + {"matrix", CMD_TRANSFORM_MATRIX}, |
| 180 | + {"rotate", CMD_TRANSFORM_ROTATE}, |
142 | 181 | {"scaleX", CMD_TRANSFORM_SCALE_X}, |
143 | 182 | {"scaleY", CMD_TRANSFORM_SCALE_Y}, |
144 | | - {"rotate", CMD_TRANSFORM_ROTATE}, |
145 | 183 | {"rotateX", CMD_TRANSFORM_ROTATE_X}, |
146 | 184 | {"rotateY", CMD_TRANSFORM_ROTATE_Y}, |
147 | 185 | {"rotateZ", CMD_TRANSFORM_ROTATE_Z}, |
148 | | - {"skewX", CMD_TRANSFORM_SKEW_X}, |
149 | | - {"skewY", CMD_TRANSFORM_SKEW_Y}, |
150 | | - {"matrix", CMD_TRANSFORM_MATRIX}, |
| 186 | + {"translateX", CMD_TRANSFORM_TRANSLATE_X}, |
| 187 | + {"translateY", CMD_TRANSFORM_TRANSLATE_Y}, |
151 | 188 | {"perspective", CMD_TRANSFORM_PERSPECTIVE}, |
152 | | - }; |
153 | | - auto it = kMap.find(name); |
154 | | - if (it == kMap.end()) { |
155 | | - return std::nullopt; |
156 | | - } |
157 | | - return it->second; |
| 189 | + }}; |
| 190 | + static constexpr auto kIndex = |
| 191 | + indexCommandLengths<kMap.back().first.size()>(kMap); |
| 192 | + static_assert( |
| 193 | + kIndex.back().data() == |
| 194 | + std::span<const CommandEntry>{kMap}.last(kIndex.back().size()).data(), |
| 195 | + "Command entries must be sorted by name length"); |
| 196 | + return findCommand(name, kIndex); |
158 | 197 | } |
159 | 198 |
|
160 | 199 | bool packLength( |
|
0 commit comments