12 #include <initializer_list>
19 #include <string_view>
20 #include <system_error>
21 #include <type_traits>
22 #include <unordered_map>
26 enum class ResolveResult
: bool
32 template <typename T
> class LazyVec final
37 std::vector
<T
> resolved_values
;
38 explicit Internals(std::vector
<T
> &&resolved_values
)
39 : resolved_values(std::move(resolved_values
))
42 explicit Internals(std::initializer_list
<T
> resolved_values
= {})
43 : resolved_values(resolved_values
)
46 virtual ~Internals() = default;
47 virtual ResolveResult
resolve_more()
49 return ResolveResult::Finished
;
53 typename Iterator
, typename Sentinel
,
54 typename
= std::enable_if_t
<
56 std::input_iterator_tag
,
57 typename
std::iterator_traits
<Iterator
>::iterator_category
> &&
59 const typename
std::iterator_traits
<Iterator
>::value_type
,
61 struct LazyInternalsIter final
: public Internals
67 State(Iterator
&&cur
, Sentinel
&&end
) noexcept
68 : cur(std::move(cur
)), end(std::move(end
))
72 std::optional
<State
> state
;
73 LazyInternalsIter(Iterator
&&cur
, Sentinel
&&end
) noexcept
74 : state(std::in_place
, std::move(cur
), std::move(end
))
76 if (state
->cur
== state
->end
)
81 LazyInternalsIter(const LazyInternalsIter
&) = delete;
82 LazyInternalsIter
&operator=(const LazyInternalsIter
&) = delete;
83 virtual ResolveResult
resolve_more() override
87 return ResolveResult::Finished
;
89 this->resolved_values
.emplace_back(*state
->cur
++);
90 if (state
->cur
== state
->end
)
93 return ResolveResult::Finished
;
95 return ResolveResult::MoreToResolve
;
100 typename Iterator
= decltype(std::begin(std::declval
<Container
>())),
101 typename Sentinel
= decltype(std::end(std::declval
<Container
>())),
102 typename
= decltype(LazyInternalsIter
<Iterator
, Sentinel
>::cur
)>
103 struct LazyInternalsContainer final
: public Internals
108 Iterator cur
; // must come after container
109 Sentinel end
; // must come after container
110 explicit State(Container
&&container
) noexcept
111 : container(std::move(container
)),
112 cur(std::begin(this->container
)),
113 end(std::begin(this->container
))
116 State(const State
&) = delete;
117 State
&operator=(const State
&) = delete;
119 std::optional
<State
> state
;
120 explicit LazyInternalsContainer(Container
&&container
) noexcept
121 : state(std::in_place
, std::move(container
))
123 if (state
->cur
== state
->end
)
125 state
= std::nullopt
;
128 virtual ResolveResult
resolve_more() override
132 return ResolveResult::Finished
;
134 this->resolved_values
.emplace_back(*state
->cur
++);
135 if (state
->cur
== state
->end
)
137 state
= std::nullopt
;
138 return ResolveResult::Finished
;
140 return ResolveResult::MoreToResolve
;
143 template <typename Fn
,
144 typename
= std::enable_if_t
<std::is_convertible_v
<
145 decltype(std::declval
<Fn
&>()()), std::optional
<T
>>>>
146 struct LazyInternalsFn final
: public Internals
148 std::optional
<Fn
> fn
;
149 explicit LazyInternalsFn(Fn
&&fn
) noexcept
150 : fn(std::in_place
, std::move(fn
))
153 virtual ResolveResult
resolve_more() override
157 return ResolveResult::Finished
;
159 if (std::optional
<T
> value
= (*fn
)())
161 this->resolved_values
.emplace_back(std::move(*value
));
162 return ResolveResult::MoreToResolve
;
165 return ResolveResult::Finished
;
168 std::shared_ptr
<Internals
> internals
;
171 LazyVec() noexcept
: internals(std::make_shared
<Internals
>())
174 LazyVec(std::vector
<T
> values
) noexcept
175 : internals(std::make_shared
<Internals
>(std::move(values
)))
178 LazyVec(std::initializer_list
<T
> values
) noexcept
179 : internals(std::make_shared
<Internals
>(values
))
182 template <typename Iterator
, typename Sentinel
,
183 typename
= decltype(LazyInternalsIter
<Iterator
, Sentinel
>::cur
)>
184 LazyVec(Iterator begin
, Sentinel end
) noexcept
185 : internals(std::make_shared
<LazyInternalsIter
<Iterator
, Sentinel
>>(
186 std::move(begin
), std::move(end
)))
189 template <typename Container
, typename
= decltype(LazyInternalsContainer
<
190 Container
>::container
)>
191 LazyVec(Container container
) noexcept
192 : internals(std::make_shared
<LazyInternalsContainer
<Container
>>(
193 std::move(container
)))
196 template <typename Fn
, typename
= void,
197 typename
= decltype(LazyInternalsFn
<Fn
>::fn
)>
198 LazyVec(Fn fn
) noexcept
199 : internals(std::make_shared
<LazyInternalsFn
<Fn
>>(std::move(fn
)))
204 static bool resolve_at(const std::shared_ptr
<Internals
> &internals
,
205 std::size_t index
) noexcept
207 while (index
>= internals
->resolved_values
.size())
209 switch (internals
->resolve_more())
211 case ResolveResult::Finished
:
213 case ResolveResult::MoreToResolve
:
218 return index
< internals
->resolved_values
.size();
222 bool resolve_at(std::size_t index
) noexcept
224 return resolve_at(internals
, index
);
226 const T
&at(std::size_t index
) noexcept
228 if (!resolve_at(index
))
230 assert(!"index out of bounds");
233 return internals
->resolved_values
[index
];
235 const T
&operator[](std::size_t index
) noexcept
239 std::size_t size_lower_bound() noexcept
241 return internals
->resolved_values
.size();
243 ResolveResult
resolve_more()
245 return internals
->resolve_more();
247 const std::vector
<T
> &resolve()
251 switch (resolve_more())
253 case ResolveResult::Finished
:
254 return internals
->resolved_values
;
255 case ResolveResult::MoreToResolve
:
260 class const_iterator final
262 friend class LazyVec
;
265 std::shared_ptr
<Internals
> internals
;
266 std::size_t index
= 0;
267 bool resolve() const noexcept
274 return resolve_at(internals
, index
);
276 explicit const_iterator(
277 const std::shared_ptr
<Internals
> &internals
) noexcept
278 : internals(internals
)
283 using difference_type
= std::ptrdiff_t;
284 using value_type
= T
;
285 using pointer
= const T
*;
286 using reference
= const T
&;
287 using iterator_category
= std::forward_iterator_tag
;
289 const_iterator() noexcept
= default;
290 const_iterator
&operator++()
296 const_iterator
operator++(int)
302 pointer
operator->() const noexcept
306 assert(!"tried to dereference an end() iterator");
309 return std::addressof(internals
->resolved_values
[index
]);
311 reference
operator*() const noexcept
313 return *operator->();
315 bool at_end() const noexcept
319 bool operator==(const const_iterator
&rhs
) const noexcept
325 assert(internals
== rhs
.internals
);
326 return index
== rhs
.index
;
336 bool operator!=(const const_iterator
&rhs
) const noexcept
338 return !operator==(rhs
);
341 const_iterator
begin() const noexcept
343 return const_iterator(internals
);
345 const_iterator
cbegin() const noexcept
347 return const_iterator(internals
);
349 const_iterator
end() const noexcept
351 return const_iterator();
353 const_iterator
cend() const noexcept
355 return const_iterator();
357 template <typename R
, typename Fn
> LazyVec
<R
> filter_map(Fn
&&fn
) noexcept
359 struct FilterMapper final
363 std::optional
<R
> operator()() noexcept
365 while (iter
!= const_iterator())
367 if (std::optional
<R
> retval
= fn(*iter
++))
375 return LazyVec
<R
>(FilterMapper
{.iter
= begin(), .fn
= std::move(fn
)});
377 template <typename R
, typename Fn
> LazyVec
<R
> map(Fn fn
) noexcept
379 return filter_map
<R
>(
380 [fn
](const T
&value
) -> std::optional
<R
> { return fn(value
); });
382 template <typename Fn
> LazyVec
filter(Fn fn
) noexcept
384 return filter_map
<T
>([fn
](const T
&value
) -> std::optional
<T
> {
394 struct JsonValue final
396 using String
= std::string
;
397 using Number
= double;
398 using Object
= LazyVec
<std::pair
<String
, JsonValue
>>;
399 using Array
= LazyVec
<JsonValue
>;
401 using Null
= std::nullptr_t
;
402 std::variant
<String
, Number
, Object
, Array
, Bool
, Null
> value
;
403 constexpr JsonValue() noexcept
: value(nullptr)
406 JsonValue(String value
) noexcept
: value(std::move(value
))
409 JsonValue(const char *value
) noexcept
: value(std::string(value
))
412 JsonValue(std::string_view value
) noexcept
: value(std::string(value
))
415 constexpr JsonValue(Number value
) noexcept
: value(value
)
418 JsonValue(Object value
) noexcept
: value(std::move(value
))
421 JsonValue(Array value
) noexcept
: value(std::move(value
))
424 constexpr JsonValue(Bool value
) noexcept
: value(value
)
427 constexpr JsonValue(Null
) noexcept
: value(nullptr)
430 constexpr JsonValue(char) noexcept
= delete;
431 constexpr JsonValue(char16_t
) noexcept
= delete;
432 constexpr JsonValue(char32_t
) noexcept
= delete;
433 #define JSON_VALUE_NUM(T) \
434 constexpr JsonValue(T value) noexcept \
435 : JsonValue(static_cast<double>(value)) \
438 JSON_VALUE_NUM(float)
439 JSON_VALUE_NUM(long double)
440 JSON_VALUE_NUM(unsigned char)
441 JSON_VALUE_NUM(signed char)
442 JSON_VALUE_NUM(unsigned short)
443 JSON_VALUE_NUM(short)
444 JSON_VALUE_NUM(unsigned int)
446 JSON_VALUE_NUM(unsigned long)
448 JSON_VALUE_NUM(unsigned long long)
449 JSON_VALUE_NUM(long long)
450 #undef JSON_VALUE_NUM
451 template <typename T
, typename
= decltype(JsonValue(std::declval
<T
&&>()))>
452 constexpr JsonValue(std::optional
<T
> value
) noexcept
: value(nullptr)
456 *this = JsonValue(std::move(*value
));
459 template <typename T
,
460 typename
= decltype(JsonValue(std::declval
<const T
&>()))>
461 JsonValue(LazyVec
<T
> value
) noexcept
462 : value(value
.template map
<JsonValue
>(
463 [](const T
&value
) { return JsonValue(value
); }))
466 template <typename T
,
467 typename
= decltype(JsonValue(std::declval
<const T
&>()))>
468 JsonValue(std::vector
<T
> value
) noexcept
469 : JsonValue(LazyVec
<T
>(std::move(value
)))
472 /// decode a JsonString from WTF-8 to the encoding logically used in JSON:
473 /// WTF-16 aka. potentially ill-formed UTF-16
475 /// https://simonsapin.github.io/wtf-8/
476 class JsonStringDecoder final
479 std::string_view remaining
;
480 bool last_was_lead_surrogate
= false;
481 std::optional
<std::uint16_t> trail_surrogate
;
484 constexpr JsonStringDecoder() noexcept
: JsonStringDecoder("")
487 constexpr explicit JsonStringDecoder(
488 std::string_view json_string
) noexcept
489 : remaining(json_string
)
494 [[noreturn
]] void throw_wtf8_err()
496 *this = JsonStringDecoder();
497 throw std::ios_base::failure("Invalid WTF-8");
501 constexpr std::optional
<std::uint16_t> next()
505 auto retval
= *trail_surrogate
;
506 trail_surrogate
= std::nullopt
;
509 if (remaining
.empty())
513 std::uint32_t code_point
= 0;
516 std::uint8_t min
= 0x80;
517 std::uint8_t max
= 0xBF;
519 auto get
= [&]() -> std::uint8_t {
520 if (remaining
.empty())
524 std::uint8_t retval
= remaining
[0];
525 remaining
.remove_prefix(1);
528 auto cont
= [&](min_max min_max
= {}) {
529 std::uint8_t v
= get();
530 if (v
< min_max
.min
|| v
> min_max
.max
)
535 code_point
|= v
& 0x3F;
537 std::uint8_t initial
= get();
540 code_point
= initial
;
542 else if (initial
< 0xC2)
546 else if (initial
< 0xE0)
548 code_point
= initial
& 0x1F;
551 else if (initial
== 0xE0)
553 code_point
= initial
& 0xF;
557 else if (initial
< 0xF0)
559 code_point
= initial
& 0xF;
563 else if (initial
== 0xF0)
565 code_point
= initial
& 0x7;
570 else if (initial
< 0xF4)
572 code_point
= initial
& 0x7;
577 else if (initial
== 0xF4)
579 code_point
= initial
& 0x7;
588 if (last_was_lead_surrogate
&& code_point
>= 0xDC00 &&
589 code_point
<= 0xDFFF)
591 // got lead surrogate followed by trail surrogate --
595 last_was_lead_surrogate
=
596 (code_point
>= 0xD800 && code_point
<= 0xDBFF);
597 bool is_supplementary_code_point
= code_point
>= 0x10000;
598 if (is_supplementary_code_point
)
600 auto value
= code_point
- 0x10000;
601 std::uint16_t retval
= (value
>> 10) + 0xD800;
602 trail_surrogate
= (value
& 0x3FF) + 0xDC00;
613 template <typename WriteStringView
> struct Visitor final
615 WriteStringView
&write_fn
;
617 std::size_t indent
= 0;
618 void write(std::string_view str
)
624 write_fn(std::string_view(&ch
, 1));
628 for (std::size_t i
= 0; i
< indent
; i
++)
633 void operator()(const String
&value
)
636 JsonStringDecoder
decoder(value
);
637 while (auto value_opt
= decoder
.next())
639 std::uint16_t value
= *value_opt
;
645 write(static_cast<char>(value
));
663 if (value
>= 0x20 && value
<= 0x7E)
665 write(static_cast<char>(value
));
669 static constexpr char hex_digits
[] =
672 for (int i
= 0; i
< 4; i
++)
674 write(hex_digits
[value
>> 12]);
683 void operator()(Number value
)
685 if (std::isnan(value
))
690 if (std::signbit(value
))
695 if (std::isinf(value
))
705 using Buf
= std::array
<char, 32>;
706 auto try_format
= [&](Buf
&buf
, bool e_format
, int prec
) -> bool {
710 result
= std::snprintf(&buf
[0], buf
.size(), "%1.*e", prec
,
715 result
= std::snprintf(&buf
[0], buf
.size(), "%1.*f", prec
,
720 double parsed_value
= std::strtod(&buf
[0], nullptr);
721 if (parsed_value
!= value
)
723 // not precise enough
729 std::optional
<std::string_view
> final
;
730 std::size_t end_prec
= final_buf
.size();
731 for (std::size_t prec
= 0;
732 prec
< final_buf
.size() && prec
< end_prec
; prec
++)
735 if (try_format(buf
, true, prec
))
737 std::string_view
str(&buf
[0]);
738 if (!final
|| str
.size() < final
->size())
741 final
= std::string_view(&final_buf
[0], str
.size());
745 if (try_format(buf
, false, prec
))
747 std::string_view
str(&buf
[0]);
748 if (!final
|| str
.size() < final
->size())
751 final
= std::string_view(&final_buf
[0], str
.size());
756 if (final_buf
[0] == '.')
762 void operator()(Bool value
)
764 write(value
? "true" : "false");
766 void operator()(Null
)
770 template <typename T
, typename Fn
>
771 void write_container_inner(const LazyVec
<T
> &value
, Fn fn
)
774 std::string_view sep
{};
776 for (auto &v
: value
)
795 void operator()(const Array
&value
)
798 write_container_inner(value
, [&](const JsonValue
&value
) {
799 std::visit(*this, value
.value
);
803 void operator()(const Object
&value
)
806 write_container_inner(
807 value
, [&](const std::pair
<String
, JsonValue
> &value
) {
808 operator()(value
.first
);
814 std::visit(*this, value
.second
.value
);
821 template <typename WriteStringView
>
822 void write(WriteStringView
&&write_fn
, bool pretty
= false) const
825 Visitor
<WriteStringView
>{
826 .write_fn
= write_fn
,
831 struct PrettyJsonValue
;
832 PrettyJsonValue
pretty(bool pretty
= true) const noexcept
;
833 friend std::ostream
&operator<<(std::ostream
&os
, const JsonValue
&self
)
835 self
.write([&](std::string_view str
) { os
<< str
; });
840 struct JsonValue::PrettyJsonValue final
844 friend std::ostream
&operator<<(std::ostream
&os
,
845 const PrettyJsonValue
&self
)
847 self
.value
.write([&](std::string_view str
) { os
<< str
; },
853 inline auto JsonValue::pretty(bool pretty
) const noexcept
-> PrettyJsonValue
855 return {.value
= *this, .pretty
= pretty
};