25 namespace sort_codec_detail {
32 return {std::as_bytes(std::span(value.data(), value.size())),
42 if (width > 64 || (width < 64 && (value >> width)))
43 error_detail::raise<std::invalid_argument>(
"value exceeds bit field");
49 template <
class Code = exponential_golomb<0>>
void write_count(std::uint64_t value) {
50 profile_detail::write_backspace<sort_codec_detail::count_policy<Code>>(
data_, value);
63 error_detail::raise<std::invalid_argument>(
"truncated backspace remainder");
77 result = (result << width) | (
reservoir_ >> (64 - width));
82 if (count >
remaining()) error_detail::raise<std::invalid_argument>(
"truncated sort payload");
88 if (count >
remaining()) error_detail::raise<std::invalid_argument>(
"truncated sort payload");
91 template <
class Code = exponential_golomb<0>> std::uint64_t
read_count() {
95 if (quotient > (std::numeric_limits<std::uint64_t>::max() >> policy::backspace_parameter))
96 error_detail::raise<std::invalid_argument>(
"overflowing exponential-Golomb backspace");
97 auto remainder =
read_bits(
unsigned(policy::backspace_parameter));
98 return (quotient << policy::backspace_parameter) | remainder;
100 constexpr auto modulus = policy::backspace_parameter;
101 constexpr auto width = unsigned(std::bit_width(modulus - 1));
102 constexpr auto cutoff = profile_detail::golomb_cutoff<policy>();
103 constexpr auto limit = std::numeric_limits<std::uint64_t>::max() / modulus;
104 auto quotient =
read_zero_run(limit,
"truncated backspace remainder",
"overflowing Golomb quotient");
105 std::uint64_t remainder = 0;
106 if constexpr (width != 0) {
108 if (remainder >= cutoff) remainder = ((remainder << 1) |
read_bits(1)) - cutoff;
110 auto base = quotient * modulus;
111 if (remainder > std::numeric_limits<std::uint64_t>::max() - base)
112 error_detail::raise<std::invalid_argument>(
"overflowing Golomb backspace");
113 return base + remainder;
125 auto shift = unsigned(offset & 7);
126 auto width = 64 - shift;
137 void skip(std::uint64_t count)
noexcept {
141 std::uint64_t
read_zero_run(std::uint64_t limit,
char const *truncated,
char const *overflow) {
142 std::uint64_t zeros = 0;
144 if (
empty()) error_detail::raise<std::invalid_argument>(truncated);
147 auto leading = std::min(
unsigned(std::countl_zero(
reservoir_)), width);
148 if (leading > limit - zeros) {
149 consume(
unsigned(limit - zeros + 1));
150 error_detail::raise<std::invalid_argument>(overflow);
154 if (leading != width) {
consume(1);
return zeros; }
159 auto zeros = unsigned(std::countl_zero(
reservoir_));
161 if (zeros < 32 && 2 * zeros + 1 <=
cached_) {
162 auto width = 2 * zeros + 1;
163 auto result = (
reservoir_ >> (64 - width)) - 1;
171 "truncated exponential-Golomb count",
"overflowing exponential-Golomb count"));
174 error_detail::raise<std::invalid_argument>(
"truncated exponential-Golomb count");
178 if (suffix) error_detail::raise<std::invalid_argument>(
"overflowing exponential-Golomb count");
179 return std::numeric_limits<std::uint64_t>::max();
181 return ((std::uint64_t{1} << zeros) - 1) + suffix;
193 error_detail::raise<std::invalid_argument>(
"FC comparison lacks inherited prefix");
208 for (
unsigned char c : value) {
220 if (!escape)
return result;
221 if (escape != 255) error_detail::raise<std::invalid_argument>(
"noncanonical string escape");
223 result.push_back(
static_cast<char>(c));
230 auto backspace = in.template read_count<CountCode>();
231 if (backspace > previous_bits) error_detail::raise<std::invalid_argument>(
"FC backspace exceeds key");
232 auto retained = previous_bits - backspace;
233 auto literal = in.
take_bits(in.template read_count<CountCode>());
235 error_detail::raise<std::invalid_argument>(
"FC string ends inside a byte");
236 return {retained, literal};
242 out.template write_count<CountCode>(old.size() - retained);
243 out.template write_count<CountCode>(key.size() - retained);
244 out.
append(key.subview(retained, key.size() - retained));
249 value_type result(
static_cast<std::size_t
>(frame.size() >> 3),
'\0');
250 auto target =
reinterpret_cast<std::byte *
>(result.data());
257 template <
class CountCode = exponential_golomb<0>>
struct fc_bit_key {
261 auto backspace = in.template read_count<CountCode>();
262 if (backspace > previous_bits) error_detail::raise<std::invalid_argument>(
"FC backspace exceeds key");
263 auto retained = previous_bits - backspace;
264 auto literal = in.
take_bits(in.template read_count<CountCode>());
266 return {retained, literal};
269 auto key = value.
view(), old = previous ? previous->view() :
bit_view{};
271 out.template write_count<CountCode>(old.size() - retained);
272 out.template write_count<CountCode>(key.size() - retained);
273 out.
append(key.subview(retained, key.size() - retained));
284 auto bits = value.
view();
285 for (std::uint64_t i = 0; i != bits.size(); ++i) out.
write_bits(2 | bits.at(i), 2);
296 template <
class CountCode = exponential_golomb<0>>
struct string_value {
300 out.template write_count<CountCode>(value.size());
304 auto bytes = in.template read_count<CountCode>();
305 if (bytes > (in.
remaining() >> 3)) error_detail::raise<std::invalid_argument>(
"truncated string value");
307 value_type result(
static_cast<std::size_t
>(bytes),
'\0');
312 auto bytes = in.template read_count<CountCode>();
313 if (bytes > (in.
remaining() >> 3)) error_detail::raise<std::invalid_argument>(
"truncated string value");
318 template <
class CountCode = exponential_golomb<0>>
struct bit_value {
322 auto bits = value.
view();
323 out.template write_count<CountCode>(bits.size());
340 static_assert(Bits >= 1 && Bits <= 64);
363 using value_type = std::optional<typename Codec::value_type>;
365 Codec::fixed_value_bits == 0 ? std::optional<std::uint64_t>{1} : std::nullopt;
368 if (value) Codec::write(out, *value);
371 if (!in.
read_bits(1))
return std::nullopt;
372 return Codec::read(in);
378 using value_type = std::optional<typename Codec::value_type>;
381 if (value && *value == Sentinel) error_detail::raise<std::invalid_argument>(
"value occupies tombstone niche");
382 Codec::write(out, value ? *value : Sentinel);
385 auto value = Codec::read(in);
386 if (value == Sentinel)
return std::nullopt;
415 namespace sort_codec_detail {
417 static_assert(!S::encoding::fixed_value_bits ||
419 "sort encoding promises a value width its codec does not supply");
422 template <
class S,
class... T>
struct contains<S, registry_detail::sorts<T...>>
423 : std::bool_constant<(std::is_same_v<S, T> || ...)> {};
426 template <
class R,
class S>
struct code;
428 static constexpr std::uint64_t size = 0;
432 template <
class L,
class R,
class S>
struct code<
bin<L, R>, S> {
433 static constexpr std::uint64_t size = 1 + [] {
438 constexpr bool right = !contains_sort<L, S>;
445 static constexpr std::uint64_t size = 8;
447 std::uint64_t i = 0, index = 0;
448 ((std::is_same_v<T, S> ? (index = i, ++i) : ++i), ...);
458 template <
class... S>
struct states<registry_detail::sorts<S...>> {
459 using type = std::variant<std::monostate, key_state<S>...>;
467 std::uint64_t
at = 0;
469 std::uint64_t value = 0;
470 for (
unsigned i = 0; i != width; ++i) {
473 value = (value << 1) |
bit;
482 static_assert(sort_codec_detail::contains_sort<Registry, S>,
"sort is absent from registry");
488 write_sort_code<Registry, S>(out);
508 std::visit([&](
auto const & value) {
509 using state = std::remove_cvref_t<
decltype(value)>;
510 if constexpr (std::is_same_v<state, std::monostate>) {
511 if (
path.
bit_size) error_detail::raise<std::invalid_argument>(
"sort anchor has no key");
512 }
else if (
path != sort_code<Registry, typename state::sort_type>())
513 error_detail::raise<std::invalid_argument>(
"sort anchor path disagrees with key type");
518 template <
class Registry,
class TreeCode = exponential_golomb<0>, stream_role Role = stream_role::native>
521 "sort record streams require a bit registry");
531 if (
failed_) error_detail::raise<std::logic_error>(
"failed sort record writer");
533 sort_codec_detail::validate_value_width<S>();
535 auto previous = std::get_if<sort_codec_detail::key_state<S>>(&
state_.
previous);
536 bool same_sort = previous !=
nullptr;
537 auto path = same_sort ?
bit_string{} : sort_code<Registry, S>();
541 if ((!std::holds_alternative<std::monostate>(
state_.
previous) && comparison.order > 0) ||
542 (previous && !key_codec::less(previous->key, key)))
543 error_detail::raise<std::invalid_argument>(
"sort records must have unique sorted keys");
548 out.
append(path_bits.subview(control.sort_retained, path_bits.size() - control.sort_retained));
549 control.key_start = control.start + out.
position();
550 key_codec::write(out, key, previous ? &previous->key :
nullptr);
551 control.value_start = control.start + out.
position();
553 control.end = control.start + out.
position();
558 if (!same_sort)
state_.
path = std::move(path);
560 }
catch (...) {
failed_ =
true;
throw; }
563 requires std::is_same_v<value_codec<S>,
no_value> {
return append<S>(key, {}); }
565 if (
failed_) error_detail::raise<std::logic_error>(
"failed sort record writer");
578 template <
class Registry,
class TreeCode = exponential_golomb<0>, stream_role Role = stream_role::native>
581 "sort record streams require a bit registry");
593 template <
class Visitor>
bool next(Visitor && visitor) {
594 if (
failed_) error_detail::raise<std::logic_error>(
"failed sort record reader");
595 if (
empty())
return false;
599 auto backspace =
input_.template read_count<TreeCode>();
601 error_detail::raise<std::invalid_argument>(
"sort backspace exceeds path");
604 bool reuse = backspace == 0 && !std::holds_alternative<std::monostate>(
state_.
previous);
605 auto decode = [&]<
class S>(std::type_identity<S> tag) {
606 sort_codec_detail::validate_value_width<S>();
607 auto path_bits = reuse ? state_.path.view() : path.
view();
611 using value_codec = std::conditional_t<Role == stream_role::native,
613 auto previous = std::get_if<sort_codec_detail::key_state<S>>(&state_.previous);
614 auto key = key_codec::read(input_, previous ? &previous->key :
nullptr);
616 auto value = value_codec::read(input_);
617 control.
end = input_.position();
618 if ((!std::holds_alternative<std::monostate>(state_.previous) &&
619 !reuse &&
compare_bits(state_.path.view(), path_bits) > 0) ||
620 (previous && !key_codec::less(previous->key, key)))
621 error_detail::raise<std::invalid_argument>(
"sort records must have unique sorted keys");
623 if (!reuse) state_.path = std::move(path);
624 auto const & stored = std::get<sort_codec_detail::key_state<S>>(state_.previous);
625 std::invoke(std::forward<Visitor>(visitor), tag, stored.key, value, control);
630 std::visit([&](
auto const & previous) {
631 using state = std::remove_cvref_t<
decltype(previous)>;
632 if constexpr (!std::is_same_v<state, std::monostate>)
633 decode(std::type_identity<typename state::sort_type>{});
638 dispatch_sort<Registry>(prefix, [&]<
class S>(std::type_identity<S> tag,
auto &) {
640 error_detail::raise<std::invalid_argument>(
"retained sort prefix crosses leaf");
645 }
catch (...) {
failed_ =
true;
throw; }
std::uint64_t load_big(void const *source) noexcept
Definition key_detail.h:57
void put_fixed(bit_string &target, std::uint64_t &at, std::uint64_t value, unsigned width)
Definition profile.h:504
std::uint64_t add(std::uint64_t a, std::uint64_t b)
Definition profile.h:39
std::uint64_t multiply(std::uint64_t a, std::uint64_t b)
Definition profile.h:44
void resize(bit_string &value, std::uint64_t bits)
Definition profile.h:465
void copy_bits(std::byte *target, std::uint64_t first, bit_view source) noexcept
Definition profile.h:123
std::uint64_t load_bits(bit_view data, std::uint64_t first, unsigned width) noexcept
Definition profile.h:93
void append(bit_string &target, bit_view source)
Definition profile.h:480
constexpr void validate_value_width()
Definition sort_codec.h:416
constexpr bool contains_sort
Definition sort_codec.h:424
bit_view string_bits(std::string const &value)
Definition sort_codec.h:31
Definition active_engine.h:18
bit_string sort_code()
Definition sort_codec.h:485
bit_comparison compare_common_bits(bit_view a, bit_view b)
Definition profile.h:215
int compare_bits(bit_view a, bit_view b)
Definition profile.h:243
void write_sort_code(sort_bit_writer &out)
Definition sort_codec.h:480
Declares Everett's profile support.
Describes sort codes, encoding requirements and typed registry dispatch.
std::uint64_t common_bits
Definition profile.h:210
void validate() const
Definition profile.h:170
bit_view view() const &
Definition profile.h:178
static bit_string copy(bit_view source)
Definition profile.h:181
std::uint64_t bit_size
Definition profile.h:168
Definition sort_codec.h:318
static void write(sort_bit_writer &out, value_type const &value)
Definition sort_codec.h:321
static value_type read(sort_bit_reader &in)
Definition sort_codec.h:326
static constexpr std::optional< std::uint64_t > fixed_value_bits
Definition sort_codec.h:320
static void skip(sort_bit_reader &in)
Definition sort_codec.h:327
std::span< std::byte const > storage() const noexcept
Definition profile.h:67
std::uint64_t size() const noexcept
Definition profile.h:64
std::uint64_t offset() const noexcept
Definition profile.h:66
bit_view subview(std::uint64_t first, std::uint64_t count) const
Definition profile.h:73
bit_view prefix(std::uint64_t count) const
Definition profile.h:80
Definition sort_codec.h:257
static void write(sort_bit_writer &out, value_type const &value, value_type const *previous=nullptr)
Definition sort_codec.h:268
static fc_key_frame read_frame(sort_bit_reader &in, std::uint64_t previous_bits)
Definition sort_codec.h:260
static bool less(value_type const &a, value_type const &b)
Definition sort_codec.h:259
static void write_ordered(sort_bit_writer &out, value_type const &value)
Definition sort_codec.h:283
static value_type read(sort_bit_reader &in, value_type const *previous=nullptr)
Definition sort_codec.h:275
static value_type read_ordered(sort_bit_reader &in)
Definition sort_codec.h:288
Definition sort_codec.h:186
std::uint64_t size() const
Definition sort_codec.h:189
bit_comparison compare(bit_view query, bit_comparison previous) const
Definition sort_codec.h:190
bit_view literal
Definition sort_codec.h:188
std::uint64_t retained_bits
Definition sort_codec.h:187
Definition sort_codec.h:228
static fc_key_frame read_frame(sort_bit_reader &in, std::uint64_t previous_bits)
Definition sort_codec.h:229
static value_type read(sort_bit_reader &in, value_type const *previous=nullptr)
Definition sort_codec.h:246
static void write(sort_bit_writer &out, value_type const &value, value_type const *previous=nullptr)
Definition sort_codec.h:238
Definition sort_codec.h:377
static void skip(sort_bit_reader &in)
Definition sort_codec.h:389
static void write(sort_bit_writer &out, value_type const &value)
Definition sort_codec.h:380
static value_type read(sort_bit_reader &in)
Definition sort_codec.h:384
static constexpr auto fixed_value_bits
Definition sort_codec.h:379
std::optional< typename Codec::value_type > value_type
Definition sort_codec.h:378
Definition sort_codec.h:392
static void skip(sort_bit_reader &) noexcept
Definition sort_codec.h:397
static void write(sort_bit_writer &, value_type) noexcept
Definition sort_codec.h:395
std::monostate value_type
Definition sort_codec.h:393
static value_type read(sort_bit_reader &) noexcept
Definition sort_codec.h:396
static constexpr std::optional< std::uint64_t > fixed_value_bits
Definition sort_codec.h:394
Definition sort_codec.h:202
static bool less(value_type const &a, value_type const &b)
Definition sort_codec.h:204
std::string value_type
Definition sort_codec.h:203
static value_type read_ordered(sort_bit_reader &in)
Definition sort_codec.h:214
static void write_ordered(sort_bit_writer &out, value_type const &value)
Definition sort_codec.h:207
Definition sort_codec.h:330
static void write(sort_bit_writer &out, value_type const &value, value_type const *=nullptr)
Definition sort_codec.h:331
static value_type read(sort_bit_reader &in, value_type const *=nullptr)
Definition sort_codec.h:334
Definition registry.h:217
Definition sort_codec.h:56
std::uint64_t at_
Definition sort_codec.h:118
std::uint64_t remaining() const noexcept
Definition sort_codec.h:59
std::uint64_t read_count()
Definition sort_codec.h:91
bool empty() const noexcept
Definition sort_codec.h:60
sort_bit_reader(bit_view data)
Definition sort_codec.h:57
std::uint64_t read_bits(unsigned width)
Definition sort_codec.h:61
void skip(std::uint64_t count) noexcept
Definition sort_codec.h:137
std::uint64_t read_zero_run(std::uint64_t limit, char const *truncated, char const *overflow)
Definition sort_codec.h:141
std::uint64_t reservoir_
Definition sort_codec.h:121
bit_view data_
Definition sort_codec.h:117
std::uint64_t position() const noexcept
Definition sort_codec.h:58
std::uint64_t read_exponential_slow()
Definition sort_codec.h:169
unsigned cached_
Definition sort_codec.h:122
bit_view take_bits(std::uint64_t count)
Definition sort_codec.h:81
std::uint64_t read_exponential()
Definition sort_codec.h:157
void consume(unsigned count) noexcept
Definition sort_codec.h:132
void skip_bits(std::uint64_t count)
Definition sort_codec.h:87
void refill() noexcept
Definition sort_codec.h:123
Definition sort_codec.h:38
bit_string & data_
Definition sort_codec.h:53
void append(bit_view bits)
Definition sort_codec.h:48
std::uint64_t position() const noexcept
Definition sort_codec.h:40
void write_bits(std::uint64_t value, unsigned width)
Definition sort_codec.h:41
void write_count(std::uint64_t value)
Definition sort_codec.h:49
sort_bit_writer(bit_string &data)
Definition sort_codec.h:39
static void write(sort_bit_writer &out)
Definition sort_codec.h:437
static void write(sort_bit_writer &out)
Definition sort_codec.h:446
static void write(sort_bit_writer &)
Definition sort_codec.h:429
Definition sort_codec.h:426
Definition sort_codec.h:421
Definition sort_codec.h:26
static constexpr auto backspace_code
Definition sort_codec.h:28
static constexpr auto unit
Definition sort_codec.h:27
static constexpr auto backspace_parameter
Definition sort_codec.h:29
Definition sort_codec.h:452
key_type key
Definition sort_codec.h:455
S sort_type
Definition sort_codec.h:453
typename sort_codec< S >::key_codec::value_type key_type
Definition sort_codec.h:454
Definition sort_codec.h:463
sort_bit_reader & input
Definition sort_codec.h:464
std::uint64_t at
Definition sort_codec.h:467
bit_view retained
Definition sort_codec.h:465
std::uint64_t read_bits(unsigned width)
Definition sort_codec.h:468
sort_bit_writer & path
Definition sort_codec.h:466
std::variant< std::monostate, key_state< S >... > type
Definition sort_codec.h:459
Definition sort_codec.h:457
Definition sort_codec.h:401
typename S::key_codec key_codec
Definition sort_codec.h:402
typename S::value_codec value_codec
Definition sort_codec.h:403
Definition sort_codec.h:492
std::uint64_t end
Definition sort_codec.h:498
std::uint64_t sort_retained
Definition sort_codec.h:494
std::uint64_t value_start
Definition sort_codec.h:497
std::uint64_t start
Definition sort_codec.h:493
std::uint64_t sort_bits
Definition sort_codec.h:495
std::uint64_t key_start
Definition sort_codec.h:496
Definition sort_codec.h:579
state_type const & state() const &noexcept
Definition sort_codec.h:589
bool failed_
Definition sort_codec.h:650
state_type state_
Definition sort_codec.h:649
bool failed() const noexcept
Definition sort_codec.h:587
std::uint64_t position() const noexcept
Definition sort_codec.h:588
bool empty() const noexcept
Definition sort_codec.h:586
sort_record_reader(bit_view data, state_type state={})
Definition sort_codec.h:583
bool next(Visitor &&visitor)
Definition sort_codec.h:593
sort_bit_reader input_
Definition sort_codec.h:648
Definition sort_codec.h:503
void validate() const
Definition sort_codec.h:506
bit_string path
Definition sort_codec.h:504
sort_codec_detail::states< typenameregistry_detail::info< Registry >::leaves >::type previous
Definition sort_codec.h:505
Definition sort_codec.h:519
bit_string frame_
Definition sort_codec.h:573
bit_string const & data() const &
Definition sort_codec.h:564
state_type state_
Definition sort_codec.h:574
sort_record_writer(state_type state)
Definition sort_codec.h:526
std::conditional_t< Role==stream_role::native, typename sort_codec< S >::value_codec, no_value > value_codec
Definition sort_codec.h:524
state_type const & state() const &noexcept
Definition sort_codec.h:569
sort_record_control append(typename sort_codec< S >::key_codec::value_type const &key, typename value_codec< S >::value_type const &value)
Definition sort_codec.h:528
bit_string data_
Definition sort_codec.h:572
bool failed() const noexcept
Definition sort_codec.h:570
sort_record_control append(typename sort_codec< S >::key_codec::value_type const &key)
Definition sort_codec.h:562
sort_record_writer()=default
bit_string const & data() const &&=delete
bool failed_
Definition sort_codec.h:575
Definition sort_codec.h:296
static value_type read(sort_bit_reader &in)
Definition sort_codec.h:303
static void write(sort_bit_writer &out, value_type const &value)
Definition sort_codec.h:299
static void skip(sort_bit_reader &in)
Definition sort_codec.h:311
std::string value_type
Definition sort_codec.h:297
static constexpr std::optional< std::uint64_t > fixed_value_bits
Definition sort_codec.h:298
Definition sort_codec.h:362
static void write(sort_bit_writer &out, value_type const &value)
Definition sort_codec.h:366
static value_type read(sort_bit_reader &in)
Definition sort_codec.h:370
std::optional< typename Codec::value_type > value_type
Definition sort_codec.h:363
static constexpr std::optional< std::uint64_t > fixed_value_bits
Definition sort_codec.h:364
static void skip(sort_bit_reader &in)
Definition sort_codec.h:374
Definition sort_codec.h:348
static value_type read(sort_bit_reader &in, value_type const *=nullptr)
Definition sort_codec.h:354
static void write_ordered(sort_bit_writer &out, value_type value)
Definition sort_codec.h:357
std::uint64_t value_type
Definition sort_codec.h:349
static bool less(value_type a, value_type b) noexcept
Definition sort_codec.h:350
static value_type read_ordered(sort_bit_reader &in)
Definition sort_codec.h:358
static void write(sort_bit_writer &out, value_type value, value_type const *=nullptr)
Definition sort_codec.h:351
Definition sort_codec.h:339
static void write(sort_bit_writer &out, value_type value)
Definition sort_codec.h:343
static void skip(sort_bit_reader &in)
Definition sort_codec.h:345
static value_type read(sort_bit_reader &in)
Definition sort_codec.h:344
static constexpr std::optional< std::uint64_t > fixed_value_bits
Definition sort_codec.h:342
std::uint64_t value_type
Definition sort_codec.h:341