Sourcemeta Core 0.0.0
Loading...
Searching...
No Matches
jsonpointer_token.h
1#ifndef SOURCEMETA_CORE_JSONPOINTER_TOKEN_H_
2#define SOURCEMETA_CORE_JSONPOINTER_TOKEN_H_
3
4#include <sourcemeta/core/json.h>
5
6#include <cassert> // assert
7
8namespace sourcemeta::core {
9
13template <typename PropertyT, typename Hash> class GenericToken {
14public:
16 using Value = JSON;
18 using Property = PropertyT;
20 using Index = typename Value::Array::size_type;
21
25 GenericToken(Property value, const typename Hash::hash_type property_hash)
26 : as_property{true}, property{std::move(value)}, hash{property_hash},
27 index{0} {}
28
38 GenericToken(const Property &value) : GenericToken{value, hasher(value)} {}
39
51 : as_property{true}, property{std::move(value)}, hash{hasher(property)},
52 index{0} {}
53
63 GenericToken(const JSON::Char *const value)
64 : GenericToken{value, hasher(value)} {}
65
76 : GenericToken{Property{value}, hasher(Property{value})} {}
77
87 GenericToken(const Index value)
88 : as_property{false}, property{DEFAULT_PROPERTY}, hash{0}, index{value} {}
89
99 GenericToken(const int value)
100 : as_property{false}, property{DEFAULT_PROPERTY}, hash{0},
101 index{static_cast<Index>(value)} {
102 assert(value >= 0);
103 }
104
105#if defined(_MSC_VER)
115 GenericToken(const unsigned long value)
116 : as_property{false}, property{DEFAULT_PROPERTY}, hash{0}, index{value} {}
117#endif
118
129 [[nodiscard]] auto is_property() const noexcept -> bool {
130 return this->as_property;
131 }
132
145 [[nodiscard]] auto is_hyphen() const noexcept -> bool {
146 return this->as_property && this->property.size() == 1 &&
147 this->property.front() == '\u002D';
148 }
149
160 [[nodiscard]] auto is_index() const noexcept -> bool {
161 return !this->as_property;
162 }
163
175 [[nodiscard]] auto to_property() const noexcept -> const auto & {
176 assert(this->is_property());
177 if constexpr (requires { this->property.get(); }) {
178 return this->property.get();
179 } else {
180 return this->property;
181 }
182 }
183
195 [[nodiscard]] auto property_hash() const noexcept ->
196 typename Hash::hash_type {
197 assert(this->is_property());
198 return this->hash;
199 }
200
214 [[nodiscard]] auto
216 const typename Hash::hash_type value_hash) const noexcept
217 -> bool {
218 assert(this->is_property());
219 assert(hasher(value.data(), value.size()) == value_hash);
220 if constexpr (requires { hasher.is_perfect(value_hash); }) {
221 // A perfect hash captures the property bytes but not its length, so
222 // two properties that differ only by trailing NUL bytes hash equal.
223 // Comparing sizes disambiguates them without the cost of a full
224 // string comparison
225 return this->hash == value_hash &&
226 (hasher.is_perfect(value_hash)
227 ? this->to_property().size() == value.size()
228 : this->to_property() == value);
229 } else {
230 return this->hash == value_hash && this->to_property() == value;
231 }
232 }
233
245 auto to_property() noexcept -> auto & {
246 assert(this->is_property());
247 if constexpr (requires { this->property.get(); }) {
248 return this->property.get();
249 } else {
250 return this->property;
251 }
252 }
253
265 [[nodiscard]] auto to_index() const noexcept -> Index {
266 assert(this->is_index());
267 return this->index;
268 }
269
286 [[nodiscard]] auto to_json() const -> JSON {
287 if (this->is_property()) {
288 return JSON{this->to_property()};
289 } else {
290 return JSON{this->to_index()};
291 }
292 }
293
295 auto operator==(const GenericToken<PropertyT, Hash> &other) const noexcept
296 -> bool {
297 if (this->as_property != other.as_property) {
298 return false;
299 } else if (this->as_property) {
300 if constexpr (requires { hasher.is_perfect(this->hash); }) {
301 // A perfect hash captures the property bytes but not its length, so
302 // two properties that differ only by trailing NUL bytes hash equal.
303 // Comparing sizes disambiguates them without the cost of a full
304 // string comparison
305 if (hasher.is_perfect(this->hash) && hasher.is_perfect(other.hash)) {
306 return this->hash == other.hash &&
307 this->to_property().size() == other.to_property().size();
308 }
309 }
310
311 return this->hash == other.hash &&
312 this->to_property() == other.to_property();
313 } else {
314 return this->index == other.index;
315 }
316 }
317
320 auto operator<(const GenericToken<PropertyT, Hash> &other) const noexcept
321 -> bool {
322 if (this->as_property && !other.as_property) {
323 return true;
324 } else if (!this->as_property && other.as_property) {
325 return false;
326 } else if (this->as_property) {
327 return this->to_property() < other.to_property();
328 } else {
329 return this->index < other.index;
330 }
331 }
332
333private:
334 // We need this as a member for making WeakPointer work
335 inline static const Value::String DEFAULT_PROPERTY{};
336 inline static const Hash hasher;
337
338 bool as_property;
339 Property property;
340 typename Hash::hash_type hash;
341 Index index;
342};
343
344} // namespace sourcemeta::core
345
346#endif
char Char
The character type used by the JSON document.
Definition json_value.h:42
std::basic_string< Char, CharTraits, Allocator< Char > > String
The string type used by the JSON document.
Definition json_value.h:52
std::basic_string_view< Char, CharTraits > StringView
The string view type used by the JSON document.
Definition json_value.h:54
Definition json_value.h:39
typename Value::Array::size_type Index
The stored type of an array index token.
Definition jsonpointer_token.h:20
auto to_json() const -> JSON
Definition jsonpointer_token.h:286
JSON Value
The JSON value type these tokens convert to.
Definition jsonpointer_token.h:16
GenericToken(const JSON::Char value)
Definition jsonpointer_token.h:75
auto property_equals(const JSON::StringView value, const typename Hash::hash_type value_hash) const noexcept -> bool
Definition jsonpointer_token.h:215
GenericToken(const Index value)
Definition jsonpointer_token.h:87
GenericToken(const int value)
Definition jsonpointer_token.h:99
GenericToken(Property value, const typename Hash::hash_type property_hash)
Definition jsonpointer_token.h:25
auto is_hyphen() const noexcept -> bool
Definition jsonpointer_token.h:145
auto is_index() const noexcept -> bool
Definition jsonpointer_token.h:160
GenericToken(const Property &value)
Definition jsonpointer_token.h:38
auto property_hash() const noexcept -> typename Hash::hash_type
Definition jsonpointer_token.h:195
GenericToken(Property &&value)
Definition jsonpointer_token.h:50
auto to_index() const noexcept -> Index
Definition jsonpointer_token.h:265
auto is_property() const noexcept -> bool
Definition jsonpointer_token.h:129
auto to_property() const noexcept -> const auto &
Definition jsonpointer_token.h:175
GenericToken(const JSON::Char *const value)
Definition jsonpointer_token.h:63
auto to_property() noexcept -> auto &
Definition jsonpointer_token.h:245
PropertyT Property
The stored type of an object property token.
Definition jsonpointer_token.h:18
Definition jsonpointer_token.h:13