1#ifndef RPNX_COMPRESSION_IMPLEMENTATION_ZSTANDARD_HPP
2#define RPNX_COMPRESSION_IMPLEMENTATION_ZSTANDARD_HPP
76 std::optional< std::uint8_t >
symbol;
83 std::vector< huffman_node >
nodes;
131 inline constexpr std::array< length_code_entry, 36U >
literal_length_codes{
length_code_entry{0U, 0U}, {1U, 0U}, {2U, 0U}, {3U, 0U}, {4U, 0U}, {5U, 0U}, {6U, 0U}, {7U, 0U}, {8U, 0U}, {9U, 0U}, {10U, 0U}, {11U, 0U}, {12U, 0U}, {13U, 0U}, {14U, 0U}, {15U, 0U}, {16U, 1U}, {18U, 1U}, {20U, 1U}, {22U, 1U}, {24U, 2U}, {28U, 2U}, {32U, 3U}, {40U, 3U}, {48U, 4U}, {64U, 6U}, {128U, 7U}, {256U, 8U}, {512U, 9U}, {1024U, 10U}, {2048U, 11U}, {4096U, 12U}, {8192U, 13U}, {16384U, 14U}, {32768U, 15U}, {65536U, 16U}};
134 inline constexpr std::array< length_code_entry, 53U >
match_length_codes{
length_code_entry{3U, 0U}, {4U, 0U}, {5U, 0U}, {6U, 0U}, {7U, 0U}, {8U, 0U}, {9U, 0U}, {10U, 0U}, {11U, 0U}, {12U, 0U}, {13U, 0U}, {14U, 0U}, {15U, 0U}, {16U, 0U}, {17U, 0U}, {18U, 0U}, {19U, 0U}, {20U, 0U}, {21U, 0U}, {22U, 0U}, {23U, 0U}, {24U, 0U}, {25U, 0U}, {26U, 0U}, {27U, 0U}, {28U, 0U}, {29U, 0U}, {30U, 0U}, {31U, 0U}, {32U, 0U}, {33U, 0U}, {34U, 0U}, {35U, 1U}, {37U, 1U}, {39U, 1U}, {41U, 1U}, {43U, 2U}, {47U, 2U}, {51U, 3U}, {59U, 3U}, {67U, 4U}, {83U, 4U}, {99U, 5U}, {131U, 7U}, {259U, 8U}, {515U, 9U}, {1027U, 10U}, {2051U, 11U}, {4099U, 12U}, {8195U, 13U}, {16387U, 14U}, {32771U, 15U}, {65539U, 16U}};
153 [[nodiscard]] std::uint32_t
peek_bits(std::uint8_t count)
const
155 if (count > 32U || m_bit_position > m_input.size() * 8U || count > m_input.size() * 8U - m_bit_position)
159 std::uint32_t value = 0U;
160 for (std::uint8_t bit_index = 0U; bit_index < count; ++bit_index)
162 std::size_t
const absolute_bit = m_bit_position + bit_index;
163 std::uint8_t
const byte = std::to_integer< std::uint8_t >(m_input[absolute_bit / 8U]);
164 value |=
static_cast< std::uint32_t
>((
byte >> (absolute_bit % 8U)) & 1U) << bit_index;
174 [[nodiscard]] std::uint32_t
read_bits(std::uint8_t count)
176 std::uint32_t
const value =
peek_bits(count);
177 m_bit_position += count;
187 return (m_bit_position + 7U) / 8U;
191 std::span< std::byte const > m_input;
192 std::size_t m_bit_position = 0U;
205 if (input.empty() || input.back() == std::byte{0})
207 throw compression_error(error_code::invalid_data, format::zstandard,
"invalid Zstandard reverse bitstream marker");
209 std::uint8_t
const last_byte = std::to_integer< std::uint8_t >(input.back());
210 std::uint8_t marker_position = 0U;
211 for (std::uint8_t bit_index = 1U; bit_index < 8U; ++bit_index)
213 if ((last_byte >> bit_index) != 0U)
215 marker_position = bit_index;
218 m_bit_position = (input.size() - 1U) * 8U + marker_position;
226 [[nodiscard]] std::uint32_t
read_bits(std::uint8_t count)
228 if (count > 32U || count > m_bit_position)
232 std::size_t
const first_bit = m_bit_position - count;
233 std::uint32_t value = 0U;
234 for (std::uint8_t bit_index = 0U; bit_index < count; ++bit_index)
236 std::size_t
const absolute_bit = first_bit + bit_index;
237 std::uint8_t
const byte = std::to_integer< std::uint8_t >(m_input[absolute_bit / 8U]);
238 value |=
static_cast< std::uint32_t
>((
byte >> (absolute_bit % 8U)) & 1U) << bit_index;
240 m_bit_position = first_bit;
250 return m_bit_position;
254 std::span< std::byte const > m_input;
255 std::size_t m_bit_position = 0U;
264 [[nodiscard]]
inline std::uint64_t
rotate_left(std::uint64_t value, std::uint8_t count)
noexcept
266 return (value << count) | (value >> (64U - count));
275 [[nodiscard]]
inline std::uint32_t
read_word32(std::span< std::byte const > input, std::size_t offset)
noexcept
277 return static_cast< std::uint32_t
>(std::to_integer< std::uint8_t >(input[offset])) | (
static_cast< std::uint32_t
>(std::to_integer< std::uint8_t >(input[offset + 1U])) << 8U) | (
static_cast< std::uint32_t
>(std::to_integer< std::uint8_t >(input[offset + 2U])) << 16U) | (
static_cast< std::uint32_t
>(std::to_integer< std::uint8_t >(input[offset + 3U])) << 24U);
286 [[nodiscard]]
inline std::uint64_t
read_word64(std::span< std::byte const > input, std::size_t offset)
noexcept
288 std::uint64_t value = 0U;
289 for (std::uint8_t byte_index = 0U; byte_index < 8U; ++byte_index)
291 value |=
static_cast< std::uint64_t
>(std::to_integer< std::uint8_t >(input[offset + byte_index])) << (byte_index * 8U);
302 [[nodiscard]]
inline std::uint64_t
xxhash64(std::span< std::byte const > input, std::uint64_t seed = 0U)
noexcept
304 constexpr std::uint64_t prime1 = 0x9e3779b185ebca87ULL;
305 constexpr std::uint64_t prime2 = 0xc2b2ae3d27d4eb4fULL;
306 constexpr std::uint64_t prime3 = 0x165667b19e3779f9ULL;
307 constexpr std::uint64_t prime4 = 0x85ebca77c2b2ae63ULL;
308 constexpr std::uint64_t prime5 = 0x27d4eb2f165667c5ULL;
309 auto round = [](std::uint64_t accumulator, std::uint64_t value)
311 accumulator += value * prime2;
313 return accumulator * prime1;
315 auto merge = [&](std::uint64_t accumulator, std::uint64_t lane)
317 accumulator ^= round(0U, lane);
318 return accumulator * prime1 + prime4;
321 std::size_t position = 0U;
322 std::uint64_t hash = 0U;
323 if (input.size() >= 32U)
325 std::uint64_t lane1 = seed + prime1 + prime2;
326 std::uint64_t lane2 = seed + prime2;
327 std::uint64_t lane3 = seed;
328 std::uint64_t lane4 = seed - prime1;
329 while (position + 32U <= input.size())
331 lane1 = round(lane1,
read_word64(input, position));
332 lane2 = round(lane2,
read_word64(input, position + 8U));
333 lane3 = round(lane3,
read_word64(input, position + 16U));
334 lane4 = round(lane4,
read_word64(input, position + 24U));
338 hash = merge(hash, lane1);
339 hash = merge(hash, lane2);
340 hash = merge(hash, lane3);
341 hash = merge(hash, lane4);
345 hash = seed + prime5;
347 hash += input.size();
348 while (position + 8U <= input.size())
354 if (position + 4U <= input.size())
356 hash ^=
static_cast< std::uint64_t
>(
read_word32(input, position)) * prime1;
360 while (position < input.size())
362 hash ^= std::to_integer< std::uint8_t >(input[position]) * prime5;
384 m_buffer[m_buffer_size++] =
value;
386 if (m_buffer_size == m_buffer.size())
388 m_lane1 = round(m_lane1,
read_word64(m_buffer, 0U));
389 m_lane2 = round(m_lane2,
read_word64(m_buffer, 8U));
390 m_lane3 = round(m_lane3,
read_word64(m_buffer, 16U));
391 m_lane4 = round(m_lane4,
read_word64(m_buffer, 24U));
400 [[nodiscard]] std::uint64_t
value() const noexcept
402 constexpr std::uint64_t prime1 = 0x9e3779b185ebca87ULL;
403 constexpr std::uint64_t prime2 = 0xc2b2ae3d27d4eb4fULL;
404 constexpr std::uint64_t prime3 = 0x165667b19e3779f9ULL;
405 constexpr std::uint64_t prime4 = 0x85ebca77c2b2ae63ULL;
406 constexpr std::uint64_t prime5 = 0x27d4eb2f165667c5ULL;
407 std::uint64_t hash = 0U;
408 if (m_total_size >= 32U)
411 hash = merge(hash, m_lane1);
412 hash = merge(hash, m_lane2);
413 hash = merge(hash, m_lane3);
414 hash = merge(hash, m_lane4);
420 hash += m_total_size;
421 std::size_t position = 0U;
422 std::span< std::byte const >
const remaining(m_buffer.data(), m_buffer_size);
423 while (position + 8U <= remaining.size())
425 hash ^= round(0U,
read_word64(remaining, position));
429 if (position + 4U <= remaining.size())
431 hash ^=
static_cast< std::uint64_t
>(
read_word32(remaining, position)) * prime1;
435 while (position < remaining.size())
437 hash ^= std::to_integer< std::uint8_t >(remaining[position]) * prime5;
456 [[nodiscard]]
static std::uint64_t round(std::uint64_t lane, std::uint64_t
value)
noexcept
458 constexpr std::uint64_t prime1 = 0x9e3779b185ebca87ULL;
459 constexpr std::uint64_t prime2 = 0xc2b2ae3d27d4eb4fULL;
469 [[nodiscard]]
static std::uint64_t merge(std::uint64_t hash, std::uint64_t lane)
noexcept
471 constexpr std::uint64_t prime1 = 0x9e3779b185ebca87ULL;
472 constexpr std::uint64_t prime4 = 0x85ebca77c2b2ae63ULL;
473 hash ^= round(0U, lane);
474 return hash * prime1 + prime4;
477 std::array< std::byte, 32U > m_buffer{};
478 std::size_t m_buffer_size = 0U;
479 std::uint64_t m_total_size = 0U;
480 std::uint64_t m_lane1 = 0x9e3779b185ebca87ULL + 0xc2b2ae3d27d4eb4fULL;
481 std::uint64_t m_lane2 = 0xc2b2ae3d27d4eb4fULL;
482 std::uint64_t m_lane3 = 0U;
483 std::uint64_t m_lane4 = 0U - 0x9e3779b185ebca87ULL;
492 inline void append_integer(std::vector< std::byte >& output, std::uint64_t value, std::uint8_t byte_count)
494 for (std::uint8_t byte_index = 0U; byte_index < byte_count; ++byte_index)
496 output.push_back(
static_cast< std::byte
>((value >> (byte_index * 8U)) & 0xffU));
507 [[nodiscard]]
inline std::uint64_t
read_integer(std::span< std::byte const > input, std::size_t offset, std::uint8_t byte_count)
509 if (offset > input.size() || byte_count > input.size() - offset)
513 std::uint64_t value = 0U;
514 for (std::uint8_t byte_index = 0U; byte_index < byte_count; ++byte_index)
516 value |=
static_cast< std::uint64_t
>(std::to_integer< std::uint8_t >(input[offset + byte_index])) << (byte_index * 8U);
531 std::uint8_t
const accuracy_log =
static_cast< std::uint8_t
>(reader.
read_bits(4U) + 5U);
532 if (accuracy_log > maximum_accuracy_log)
537 std::vector< std::int16_t > probabilities(
static_cast< std::size_t
>(maximum_symbol) + 1U, 0);
538 std::uint32_t remaining = (1U << accuracy_log) + 1U;
539 std::uint32_t threshold = 1U << accuracy_log;
540 std::uint8_t number_of_bits =
static_cast< std::uint8_t
>(accuracy_log + 1U);
541 std::size_t symbol = 0U;
542 std::size_t symbols_with_probability = 0U;
544 while (remaining > 1U)
546 if (symbol >= probabilities.size())
551 std::uint32_t
const low_value = reader.
peek_bits(
static_cast< std::uint8_t
>(number_of_bits - 1U));
552 std::uint32_t
const threshold_offset = (2U * threshold - 1U) - remaining;
553 std::uint32_t encoded_probability = 0U;
554 if (low_value < threshold_offset)
556 encoded_probability = reader.
read_bits(
static_cast< std::uint8_t
>(number_of_bits - 1U));
560 encoded_probability = reader.
read_bits(number_of_bits);
561 if (encoded_probability >= threshold)
563 encoded_probability -= threshold_offset;
567 std::int16_t
const probability =
static_cast< std::int16_t
>(encoded_probability) - 1;
568 probabilities[symbol] = probability;
570 if (probability != 0)
572 ++symbols_with_probability;
574 std::uint32_t
const magnitude = probability < 0 ? static_cast< std::uint32_t >(-probability) :
static_cast< std::uint32_t
>(probability);
575 if (magnitude >= remaining)
579 remaining -= magnitude;
581 if (probability == 0)
583 std::size_t repeated_zero_count = 0U;
584 std::uint32_t repeat_count = 0U;
588 repeated_zero_count += repeat_count;
589 }
while (repeat_count == 3U);
590 if (repeated_zero_count > probabilities.size() - symbol)
594 symbol += repeated_zero_count;
597 while (remaining < threshold)
604 if (symbols_with_probability < 2U)
619 if (accuracy_log > 9U)
623 std::size_t
const table_size =
static_cast< std::size_t
>(1U) << accuracy_log;
624 std::size_t probability_total = 0U;
625 for (std::int16_t probability : probabilities)
627 if (probability < -1)
631 probability_total += probability < 0 ? 1U : static_cast< std::size_t >(probability);
633 if (probability_total != table_size)
638 std::vector< fse_entry > entries(table_size,
fse_entry{0U, 0U, 0U});
639 std::vector< bool > assigned(table_size,
false);
640 std::vector< std::uint16_t > next_state(probabilities.size(), 0U);
641 std::size_t high_position = table_size;
642 for (std::size_t symbol = 0U; symbol < probabilities.size(); ++symbol)
644 std::int16_t
const probability = probabilities[symbol];
645 if (probability == -1)
647 if (high_position == 0U)
652 entries[high_position].symbol =
static_cast< std::uint8_t
>(symbol);
653 assigned[high_position] =
true;
654 next_state[symbol] = 1U;
658 next_state[symbol] =
static_cast< std::uint16_t
>(probability);
662 std::size_t
const table_mask = table_size - 1U;
663 std::size_t
const spread_step = (table_size >> 1U) + (table_size >> 3U) + 3U;
664 std::size_t position = 0U;
665 for (std::size_t symbol = 0U; symbol < probabilities.size(); ++symbol)
667 std::int16_t
const probability = probabilities[symbol];
668 for (std::int16_t occurrence = 0; occurrence < probability; ++occurrence)
670 if (assigned[position])
674 entries[position].symbol =
static_cast< std::uint8_t
>(symbol);
675 assigned[position] =
true;
676 position = (position + spread_step) & table_mask;
677 while (position >= high_position)
679 position = (position + spread_step) & table_mask;
683 if (position != 0U || std::find(assigned.begin(), assigned.end(),
false) != assigned.end())
688 for (std::size_t state = 0U; state < table_size; ++state)
690 std::uint8_t
const symbol = entries[state].symbol;
691 std::uint16_t
const symbol_state = next_state[symbol]++;
692 if (symbol_state == 0U)
696 std::uint8_t
const state_log =
static_cast< std::uint8_t
>(std::bit_width(symbol_state) - 1);
697 std::uint8_t
const number_of_bits =
static_cast< std::uint8_t
>(accuracy_log - state_log);
698 entries[state].number_of_bits = number_of_bits;
699 entries[state].baseline =
static_cast< std::uint16_t
>((
static_cast< std::uint32_t
>(symbol_state) << number_of_bits) - table_size);
701 return fse_table{accuracy_log, std::move(entries)};
720 constexpr std::array< std::int16_t, 36U > probabilities{4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1, -1, -1, -1, -1};
730 constexpr std::array< std::int16_t, 53U > probabilities{1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1};
740 constexpr std::array< std::int16_t, 29U > probabilities{1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1};
749 [[nodiscard]]
inline std::vector< std::uint8_t >
decode_fse_weights(std::span< std::byte const > input)
760 if (state1 >= table.
entries.size() || state2 >= table.
entries.size())
765 std::vector< std::uint8_t > weights;
766 weights.reserve(255U);
767 bool finished =
false;
770 if (weights.size() >= 255U)
775 weights.push_back(transition1.
symbol);
778 if (weights.size() >= 255U)
782 weights.push_back(table.
entries[state2].symbol);
787 if (state1 >= table.
entries.size())
792 if (weights.size() >= 255U)
797 weights.push_back(transition2.
symbol);
800 if (weights.size() >= 255U)
804 weights.push_back(table.
entries[state1].symbol);
809 if (state2 >= table.
entries.size())
824 if (explicit_weights.empty() || explicit_weights.size() >= 256U)
828 std::uint32_t weight_total = 0U;
829 for (std::uint8_t weight : explicit_weights)
837 weight_total += 1U << (weight - 1U);
840 if (weight_total == 0U)
844 std::uint32_t
const table_size = std::bit_ceil(weight_total + 1U);
845 if (table_size > (1U << 11U))
849 std::uint32_t
const final_weight_value = table_size - weight_total;
850 if (!std::has_single_bit(final_weight_value))
854 std::uint8_t
const final_weight =
static_cast< std::uint8_t
>(std::bit_width(final_weight_value));
855 std::uint8_t
const table_log =
static_cast< std::uint8_t
>(std::bit_width(table_size) - 1);
856 std::vector< std::uint8_t > weights(explicit_weights.begin(), explicit_weights.end());
857 weights.push_back(final_weight);
860 std::uint32_t code_space = 0U;
861 for (std::uint8_t weight = 1U; weight <= table_log; ++weight)
863 for (std::size_t symbol = 0U; symbol < weights.size(); ++symbol)
865 if (weights[symbol] != weight)
869 std::uint8_t
const number_of_bits =
static_cast< std::uint8_t
>(table_log + 1U - weight);
870 std::uint32_t
const code = code_space >> (weight - 1U);
871 std::size_t node_index = 0U;
872 for (std::uint8_t depth = 0U; depth < number_of_bits; ++depth)
874 if (table.nodes[node_index].symbol.has_value())
878 std::uint8_t
const bit =
static_cast< std::uint8_t
>((code >> (number_of_bits - depth - 1U)) & 1U);
879 std::optional< std::uint16_t >& child = bit == 0U ? table.nodes[node_index].zero_child : table.nodes[node_index].one_child;
880 if (!child.has_value())
882 if (table.nodes.size() >= std::numeric_limits< std::uint16_t >::max())
886 std::uint16_t
const new_node_index =
static_cast< std::uint16_t
>(table.nodes.size());
887 child = new_node_index;
888 node_index = new_node_index;
896 if (table.nodes[node_index].symbol.has_value() || table.nodes[node_index].zero_child.has_value() || table.nodes[node_index].one_child.has_value())
900 table.nodes[node_index].symbol =
static_cast< std::uint8_t
>(symbol);
901 code_space += 1U << (weight - 1U);
904 if (code_space != table_size)
918 std::uint8_t
const header =
static_cast< std::uint8_t
>(
read_integer(input, 0U, 1U));
919 std::vector< std::uint8_t > weights;
920 std::size_t consumed_bytes = 1U;
923 std::size_t
const compressed_size = header;
924 if (compressed_size == 0U || compressed_size > input.size() - 1U)
929 consumed_bytes += compressed_size;
933 std::size_t
const weight_count =
static_cast< std::size_t
>(header) - 127U;
934 std::size_t
const weight_bytes = (weight_count + 1U) / 2U;
935 if (weight_bytes > input.size() - 1U)
939 weights.reserve(weight_count);
940 for (std::size_t index = 0U; index < weight_count; ++index)
942 std::uint8_t
const pair = std::to_integer< std::uint8_t >(input[1U + index / 2U]);
943 weights.push_back(index % 2U == 0U ? pair >> 4U : pair & 0x0fU);
945 consumed_bytes += weight_bytes;
960 std::vector< std::byte > output;
961 output.reserve(regenerated_size);
962 for (std::size_t output_index = 0U; output_index < regenerated_size; ++output_index)
964 std::size_t node_index = 0U;
965 while (!table.
nodes[node_index].symbol.has_value())
967 std::uint8_t
const bit =
static_cast< std::uint8_t
>(reader.
read_bits(1U));
968 std::optional< std::uint16_t >
const child = bit == 0U ? table.
nodes[node_index].zero_child : table.
nodes[node_index].one_child;
969 if (!child.has_value() || *child >= table.
nodes.size())
975 output.push_back(
static_cast< std::byte
>(*table.
nodes[node_index].symbol));
992 std::uint8_t
const first_byte =
static_cast< std::uint8_t
>(
read_integer(block, 0U, 1U));
993 std::uint8_t
const literals_type = first_byte & 0x03U;
994 std::uint8_t
const size_format =
static_cast< std::uint8_t
>((first_byte >> 2U) & 0x03U);
995 if (literals_type <= 1U)
997 std::uint8_t header_size = 1U;
998 if (size_format == 1U)
1002 else if (size_format == 3U)
1006 std::uint64_t
const header =
read_integer(block, 0U, header_size);
1007 std::size_t
const regenerated_size = size_format == 0U || size_format == 2U ?
static_cast< std::size_t
>(header >> 3U) :
static_cast< std::size_t
>(header >> 4U);
1008 std::size_t
const content_size = literals_type == 0U ? regenerated_size : 1U;
1009 if (header_size > block.size() || content_size > block.size() - header_size)
1014 std::vector< std::byte > literals;
1015 if (literals_type == 0U)
1017 literals.insert(literals.end(), block.begin() +
static_cast< std::ptrdiff_t
>(header_size), block.begin() +
static_cast< std::ptrdiff_t
>(header_size + content_size));
1021 literals.insert(literals.end(), regenerated_size, block[header_size]);
1023 return literals_result{std::move(literals), header_size + content_size};
1026 std::uint8_t header_size = 3U;
1027 std::uint8_t size_bits = 10U;
1028 std::uint8_t compressed_shift = 14U;
1029 if (size_format == 2U)
1033 compressed_shift = 18U;
1035 else if (size_format == 3U)
1039 compressed_shift = 22U;
1041 std::uint64_t
const header =
read_integer(block, 0U, header_size);
1042 std::uint64_t
const size_mask = (std::uint64_t{1U} << size_bits) - 1U;
1043 std::size_t
const regenerated_size =
static_cast< std::size_t
>((header >> 4U) & size_mask);
1044 std::size_t
const compressed_size =
static_cast< std::size_t
>((header >> compressed_shift) & size_mask);
1045 if (header_size > block.size() || compressed_size > block.size() - header_size)
1049 std::span< std::byte const >
const content = block.subspan(header_size, compressed_size);
1050 std::size_t stream_position = 0U;
1051 if (literals_type == 2U)
1061 if (stream_position >= content.size())
1066 std::vector< std::byte > literals;
1067 if (size_format == 0U)
1073 if (content.size() - stream_position < 6U)
1077 std::size_t
const stream1_size =
static_cast< std::size_t
>(
read_integer(content, stream_position, 2U));
1078 std::size_t
const stream2_size =
static_cast< std::size_t
>(
read_integer(content, stream_position + 2U, 2U));
1079 std::size_t
const stream3_size =
static_cast< std::size_t
>(
read_integer(content, stream_position + 4U, 2U));
1080 std::size_t
const streams_size = content.size() - stream_position;
1081 if (stream1_size > streams_size - 6U || stream2_size > streams_size - 6U - stream1_size || stream3_size > streams_size - 6U - stream1_size - stream2_size)
1085 std::size_t
const stream4_size = streams_size - 6U - stream1_size - stream2_size - stream3_size;
1086 std::size_t
const segment_size = (regenerated_size + 3U) / 4U;
1087 if (segment_size * 3U > regenerated_size)
1091 std::size_t
const stream1_position = stream_position + 6U;
1092 std::size_t
const stream2_position = stream1_position + stream1_size;
1093 std::size_t
const stream3_position = stream2_position + stream2_size;
1094 std::size_t
const stream4_position = stream3_position + stream3_size;
1099 literals.reserve(regenerated_size);
1100 literals.insert(literals.end(), decoded1.begin(), decoded1.end());
1101 literals.insert(literals.end(), decoded2.begin(), decoded2.end());
1102 literals.insert(literals.end(), decoded3.begin(), decoded3.end());
1103 literals.insert(literals.end(), decoded4.begin(), decoded4.end());
1105 return literals_result{std::move(literals), header_size + compressed_size};
1120 std::uint8_t
const first_sequence_count =
static_cast< std::uint8_t
>(
read_integer(block, position, 1U));
1122 std::size_t sequence_count = first_sequence_count;
1123 if (first_sequence_count >= 128U && first_sequence_count < 255U)
1125 std::uint8_t
const second_byte =
static_cast< std::uint8_t
>(
read_integer(block, position, 1U));
1127 sequence_count = (
static_cast< std::size_t
>(first_sequence_count - 128U) << 8U) + second_byte;
1129 else if (first_sequence_count == 255U)
1131 sequence_count =
static_cast< std::size_t
>(
read_integer(block, position, 2U)) + 0x7f00U;
1135 std::size_t
const block_output_start = output.size();
1136 std::size_t
const block_output_limit = std::min< std::size_t >(window_size, 128U * 1024U);
1137 if (sequence_count == 0U)
1139 if (position != block.size())
1143 if (literals.
literals.size() > block_output_limit)
1147 if (output.size() > maximum_output_size || literals.
literals.size() > maximum_output_size - output.size())
1151 output.insert(output.end(), literals.
literals.begin(), literals.
literals.end());
1155 std::uint8_t
const modes =
static_cast< std::uint8_t
>(
read_integer(block, position, 1U));
1157 if ((modes & 0x03U) != 0U)
1162 auto read_table = [&](std::uint8_t mode, std::uint8_t maximum_symbol, std::uint8_t maximum_accuracy_log,
fse_table predefined_table, std::optional< fse_table >& previous_table)
1166 previous_table = std::move(predefined_table);
1171 std::uint8_t
const symbol =
static_cast< std::uint8_t
>(
read_integer(block, position, 1U));
1173 if (symbol > maximum_symbol)
1182 if (position > block.size())
1191 if (!previous_table.has_value())
1201 if (position >= block.size())
1212 if (literal_length_state >= literal_length_table.
entries.size() || offset_state >= offset_table.
entries.size() || match_length_state >= match_length_table.
entries.size())
1217 std::size_t literal_position = 0U;
1218 for (std::size_t sequence_index = 0U; sequence_index < sequence_count; ++sequence_index)
1220 fse_entry const literal_length_transition = literal_length_table.
entries[literal_length_state];
1222 fse_entry const match_length_transition = match_length_table.
entries[match_length_state];
1230 std::uint64_t
const offset_value_64 = (std::uint64_t{1U} << offset_transition.
symbol) + reader.
read_bits(offset_transition.
symbol);
1233 if (offset_value_64 > std::numeric_limits< std::size_t >::max())
1237 std::size_t
const offset_value =
static_cast< std::size_t
>(offset_value_64);
1238 if (literal_position > literals.
literals.size() || literal_length > literals.
literals.size() - literal_position)
1242 if (output.size() > maximum_output_size || literal_length > maximum_output_size - output.size())
1246 output.insert(output.end(), literals.
literals.begin() +
static_cast< std::ptrdiff_t
>(literal_position), literals.
literals.begin() +
static_cast< std::ptrdiff_t
>(literal_position + literal_length));
1247 literal_position += literal_length;
1249 std::size_t resolved_offset = 0U;
1250 bool insert_new_offset =
false;
1251 std::size_t repeated_index = 0U;
1252 if (offset_value > 3U)
1254 resolved_offset = offset_value - 3U;
1255 insert_new_offset =
true;
1257 else if (literal_length == 0U && offset_value == 3U)
1264 insert_new_offset =
true;
1268 repeated_index = literal_length == 0U ? offset_value : offset_value - 1U;
1276 if (insert_new_offset)
1284 for (std::size_t index = repeated_index; index > 0U; --index)
1290 if (resolved_offset == 0U || resolved_offset > output.size() || resolved_offset > window_size)
1294 if (output.size() > maximum_output_size || match_length > maximum_output_size - output.size())
1298 for (std::size_t match_index = 0U; match_index < match_length; ++match_index)
1300 output.push_back(output[output.size() - resolved_offset]);
1303 if (sequence_index + 1U < sequence_count)
1308 if (literal_length_state >= literal_length_table.
entries.size() || offset_state >= offset_table.
entries.size() || match_length_state >= match_length_table.
entries.size())
1319 std::size_t
const remaining_literals = literals.
literals.size() - literal_position;
1320 if (output.size() > maximum_output_size || remaining_literals > maximum_output_size - output.size())
1324 output.insert(output.end(), literals.
literals.begin() +
static_cast< std::ptrdiff_t
>(literal_position), literals.
literals.end());
1325 if (output.size() - block_output_start > block_output_limit)
1338 template < std::
size_t code_count >
1341 for (std::size_t code = 0U; code < codes.size(); ++code)
1344 std::uint32_t
const maximum_additional_value = definition.
number_of_bits == 0U ? 0U : (std::uint32_t{1U} << definition.
number_of_bits) - 1U;
1345 if (length >= definition.
baseline && length - definition.
baseline <= maximum_additional_value)
1360 if (block.size() < 4U)
1362 return std::nullopt;
1364 std::vector< std::size_t > prefix_lengths(block.size(), 0U);
1365 for (std::size_t position = 1U; position < block.size(); ++position)
1367 std::size_t prefix_length = prefix_lengths[position - 1U];
1368 while (prefix_length != 0U && block[position] != block[prefix_length])
1370 prefix_length = prefix_lengths[prefix_length - 1U];
1372 if (block[position] == block[prefix_length])
1376 prefix_lengths[position] = prefix_length;
1378 std::size_t
const match_length = prefix_lengths.back();
1379 if (match_length < 3U)
1381 return std::nullopt;
1383 return block.size() - match_length;
1394 if (!period.has_value())
1396 return std::nullopt;
1398 std::size_t
const match_length = block.size() - *period;
1401 std::uint64_t
const offset_value =
static_cast< std::uint64_t
>(*period) + 3U;
1402 std::uint8_t
const offset_code =
static_cast< std::uint8_t
>(std::bit_width(offset_value) - 1);
1403 std::uint64_t
const offset_additional_value = offset_value - (std::uint64_t{1U} << offset_code);
1405 std::vector< std::byte > encoded;
1408 encoded.push_back(
static_cast< std::byte
>(*period << 3U));
1410 else if (*period <= 4095U)
1418 encoded.insert(encoded.end(), block.begin(), block.begin() +
static_cast< std::ptrdiff_t
>(*period));
1419 encoded.push_back(std::byte{0x01});
1420 encoded.push_back(std::byte{0x54});
1421 encoded.push_back(
static_cast< std::byte
>(literal_length.
code));
1422 encoded.push_back(
static_cast< std::byte
>(offset_code));
1423 encoded.push_back(
static_cast< std::byte
>(encoded_match_length.
code));
1426 std::vector< std::byte > bitstream((bit_count + 1U + 7U) / 8U, std::byte{0});
1427 std::size_t bit_position = 0U;
1428 auto append_bits = [&](std::uint64_t value, std::uint8_t count)
1430 for (std::uint8_t bit_index = 0U; bit_index < count; ++bit_index)
1432 if (((value >> bit_index) & 1U) != 0U)
1434 bitstream[bit_position / 8U] |=
static_cast< std::byte
>(1U << (bit_position % 8U));
1441 append_bits(offset_additional_value, offset_code);
1442 bitstream[bit_position / 8U] |=
static_cast< std::byte
>(1U << (bit_position % 8U));
1443 encoded.insert(encoded.end(), bitstream.begin(), bitstream.end());
1444 if (encoded.size() >= block.size())
1446 return std::nullopt;
1462 template < std::input_iterator input_iterator, std::sentinel_for< input_iterator > sentinel,
typename output_iterator >
1465 std::int32_t
const level = options.
level.value_or(3);
1466 if (level < 0 || level > 22)
1470 auto write_integer = [&](std::uint64_t value, std::uint8_t byte_count)
1472 for (std::uint8_t index = 0U; index < byte_count; ++index)
1477 write_integer(0xfd2fb528U, 4U);
1481 constexpr std::size_t block_limit = 128U * 1024U;
1482 std::vector< std::byte > block;
1483 block.reserve(block_limit);
1484 bool emitted_block =
false;
1488 while (first != last && block.size() < block_limit)
1493 bool const last_block = first == last;
1494 bool rle_block = !block.empty();
1495 for (std::size_t index = 1U; index < block.size() && rle_block; ++index)
1497 rle_block = block[index] == block[0U];
1499 std::optional< std::vector< std::byte > > encoded;
1500 if (!rle_block && level != 0)
1506 std::uint32_t
const header =
static_cast< std::uint32_t
>(last_block ? 1U : 0U) | 2U | (
static_cast< std::uint32_t
>(block.size()) << 3U);
1507 write_integer(header, 3U);
1510 else if (encoded.has_value())
1512 std::uint32_t
const header =
static_cast< std::uint32_t
>(last_block ? 1U : 0U) | 4U | (
static_cast< std::uint32_t
>(encoded->size()) << 3U);
1513 write_integer(header, 3U);
1514 for (std::byte value : *encoded)
1521 std::uint32_t
const header =
static_cast< std::uint32_t
>(last_block ? 1U : 0U) | (
static_cast< std::uint32_t
>(block.size()) << 3U);
1522 write_integer(header, 3U);
1523 for (std::byte value : block)
1528 emitted_block =
true;
1533 }
while (!emitted_block || first != last);
1548 template < std::input_iterator input_iterator, std::sentinel_for< input_iterator > sentinel,
typename output_iterator >
1552 auto read_byte = [&]() -> std::byte
1555 if (!reader.
read(value))
1561 auto read_integer = [&](std::uint8_t count) -> std::uint64_t
1563 std::uint64_t value = 0U;
1564 for (std::uint8_t index = 0U; index < count; ++index)
1566 value |=
static_cast< std::uint64_t
>(std::to_integer< std::uint8_t >(read_byte())) << (index * 8U);
1571 std::size_t total_output = 0U;
1572 bool decoded_frame =
false;
1573 while (!reader.
empty())
1575 std::uint32_t
const magic =
static_cast< std::uint32_t
>(
read_integer(4U));
1576 if (magic >= 0x184d2a50U && magic <= 0x184d2a5fU)
1578 std::size_t
const skip_size =
static_cast< std::size_t
>(
read_integer(4U));
1579 for (std::size_t index = 0U; index < skip_size; ++index)
1581 static_cast< void >(read_byte());
1589 if (magic != 0xfd2fb528U)
1593 std::uint8_t
const descriptor = std::to_integer< std::uint8_t >(read_byte());
1594 if ((descriptor & 0x08U) != 0U)
1598 bool const single_segment = (descriptor & 0x20U) != 0U;
1599 bool const checksum_present = (descriptor & 0x04U) != 0U;
1600 std::uint8_t
const dictionary_flag = descriptor & 0x03U;
1601 std::uint8_t
const content_size_flag = descriptor >> 6U;
1602 std::optional< std::size_t > window_size;
1603 if (!single_segment)
1605 std::uint8_t
const window_descriptor = std::to_integer< std::uint8_t >(read_byte());
1606 std::uint8_t
const window_log =
static_cast< std::uint8_t
>(10U + (window_descriptor >> 3U));
1607 if (window_log >= std::numeric_limits< std::size_t >::digits)
1611 std::size_t
const base =
static_cast< std::size_t
>(1U) << window_log;
1612 window_size = base + (base >> 3U) * (window_descriptor & 0x07U);
1614 constexpr std::array< std::uint8_t, 4U > dictionary_sizes{0U, 1U, 2U, 4U};
1615 if (
read_integer(dictionary_sizes[dictionary_flag]) != 0U)
1619 std::uint8_t content_size_bytes = 0U;
1620 if (content_size_flag == 0U)
1622 content_size_bytes = single_segment ? 1U : 0U;
1626 constexpr std::array< std::uint8_t, 4U > content_sizes{0U, 2U, 4U, 8U};
1627 content_size_bytes = content_sizes[content_size_flag];
1629 std::optional< std::uint64_t > content_size;
1630 if (content_size_bytes != 0U)
1633 if (content_size_flag == 1U)
1635 *content_size += 256U;
1644 window_size =
static_cast< std::size_t
>(content_size.value_or(0U));
1646 std::size_t
const effective_window = window_size.value_or(128U * 1024U);
1647 std::vector< std::byte > history;
1651 std::size_t
const frame_begin = total_output;
1652 auto emit_output = [&](std::byte value)
1658 if (checksum_present)
1665 auto emit = [&](std::byte value)
1667 history.push_back(value);
1671 bool last_block =
false;
1674 std::uint32_t
const header =
static_cast< std::uint32_t
>(
read_integer(3U));
1675 last_block = (header & 1U) != 0U;
1676 std::uint8_t
const block_type =
static_cast< std::uint8_t
>((header >> 1U) & 0x03U);
1677 std::size_t
const block_size = header >> 3U;
1678 std::size_t
const maximum_block = std::min< std::size_t >(effective_window, 128U * 1024U);
1679 if (block_size > maximum_block)
1683 if (block_type == 0U)
1685 for (std::size_t index = 0U; index < block_size; ++index)
1690 else if (block_type == 1U)
1692 std::byte
const value = read_byte();
1693 for (std::size_t index = 0U; index < block_size; ++index)
1698 else if (block_type == 2U)
1700 std::vector< std::byte > block;
1701 block.reserve(block_size);
1702 for (std::size_t index = 0U; index < block_size; ++index)
1704 block.push_back(read_byte());
1706 std::vector< std::byte > working = std::move(history);
1707 std::size_t
const history_size = working.size();
1710 for (std::size_t index = history_size; index < working.size(); ++index)
1712 emit_output(working[index]);
1714 std::size_t
const retained = std::min< std::size_t >(working.size(), effective_window);
1715 history.assign(working.end() -
static_cast< std::ptrdiff_t
>(retained), working.end());
1721 if (history.size() > effective_window)
1723 history.erase(history.begin(), history.begin() +
static_cast< std::ptrdiff_t
>(history.size() - effective_window));
1726 if (checksum_present &&
static_cast< std::uint32_t
>(
read_integer(4U)) !=
static_cast< std::uint32_t
>(checksum.
value()))
1730 if (content_size.has_value() && total_output - frame_begin != *content_size)
1734 decoded_frame =
true;
Exception raised for malformed streams, invalid options, and codec failures.
Single-pass byte reader over an input iterator and sentinel.
bool empty() const
Tests whether no unread byte remains.
bool read(std::byte &value)
Reads one byte.
Read a byte-aligned, forward, least-significant-bit-first bitstream.
forward_bit_reader(std::span< std::byte const > input) noexcept
Constructs a reader over a non-owning byte span.
std::uint32_t read_bits(std::uint8_t count)
Consumes and returns the next bits.
std::uint32_t peek_bits(std::uint8_t count) const
Returns the next bits without consuming them.
std::size_t consumed_bytes() const noexcept
Returns the whole number of bytes occupied by consumed bits.
Read a Zstandard entropy bitstream from its end toward its beginning.
std::size_t remaining_bits() const noexcept
Returns the number of useful bits not yet consumed.
reverse_bit_reader(std::span< std::byte const > input)
Constructs a reader and removes the mandatory final-bit marker.
std::uint32_t read_bits(std::uint8_t count)
Consumes bits preceding the current reverse-stream position.
Incremental XXH64 accumulator for streamed Zstandard checksums.
void update(std::byte value) noexcept
Includes one byte in the hash.
std::uint64_t value() const noexcept
Returns the hash for all supplied bytes.
Shared iterator, byte-conversion, and checksum primitives.
void write_byte(output_iterator &output, std::byte value)
Writes one byte through an output iterator and advances it.
constexpr std::byte to_byte(value_type value) noexcept
Converts one supported iterator value to std::byte.
Internal implementation of Zstandard compression and decompression.
output_iterator decompress(input_iterator first, sentinel last, output_iterator output, decompression_options const &options)
Decompresses one or more Zstandard or skippable frames.
encoded_length encode_length(std::size_t length, std::array< length_code_entry, code_count > const &codes)
Selects the sequence length code covering one exact length.
literals_result decode_literals(std::span< std::byte const > block, decoder_state &state)
Decodes the literals section at the front of a compressed block.
normalized_probability_result parse_normalized_probabilities(std::span< std::byte const > input, std::uint8_t maximum_symbol, std::uint8_t maximum_accuracy_log)
Parses one forward-coded normalized FSE probability description.
std::uint64_t read_word64(std::span< std::byte const > input, std::size_t offset) noexcept
Reads an unchecked little-endian 64-bit word.
std::vector< std::uint8_t > decode_fse_weights(std::span< std::byte const > input)
Decodes the two-state FSE stream used for Huffman weights.
std::vector< std::byte > decode_huffman_stream(std::span< std::byte const > input, std::size_t regenerated_size, huffman_table const &table)
Decodes one backward Huffman literal stream to an exact byte count.
void decompress_compressed_block(std::span< std::byte const > block, std::size_t window_size, std::size_t maximum_output_size, decoder_state &state, std::vector< std::byte > &output)
Decodes one compressed block into frame output.
huffman_description_result parse_huffman_description(std::span< std::byte const > input)
Parses a direct or FSE-compressed Huffman tree description.
std::optional< std::vector< std::byte > > compress_periodic_block(std::span< std::byte const > block)
Encodes a periodic block as raw literals plus one match sequence.
std::uint32_t read_word32(std::span< std::byte const > input, std::size_t offset) noexcept
Reads an unchecked little-endian 32-bit word.
fse_table build_fse_table(std::span< std::int16_t const > probabilities, std::uint8_t accuracy_log)
Constructs the FSE decoding table for normalized probabilities.
void append_integer(std::vector< std::byte > &output, std::uint64_t value, std::uint8_t byte_count)
Appends a little-endian integer with a selected byte count.
std::optional< std::size_t > find_repeating_period(std::span< std::byte const > block)
Finds a block prefix whose repetition regenerates the suffix.
output_iterator compress(input_iterator first, sentinel last, output_iterator output, compression_options const &options)
Compresses an iterator range as a Zstandard frame.
huffman_table build_huffman_table(std::span< std::uint8_t const > explicit_weights)
Builds the canonical Huffman tree implied by transmitted weights.
std::uint64_t rotate_left(std::uint64_t value, std::uint8_t count) noexcept
Rotates a 64-bit value left without compiler-specific intrinsics.
constexpr std::array< length_code_entry, 53U > match_length_codes
Match-length code definitions from the Zstandard format.
std::uint64_t read_integer(std::span< std::byte const > input, std::size_t offset, std::uint8_t byte_count)
Reads a checked little-endian integer with a selected byte count.
fse_table build_predefined_match_length_table()
Builds the format-defined predefined match-length FSE table.
constexpr std::array< length_code_entry, 36U > literal_length_codes
Literal-length code definitions from the Zstandard format.
fse_table build_predefined_literal_length_table()
Builds the format-defined predefined literal-length FSE table.
std::uint64_t xxhash64(std::span< std::byte const > input, std::uint64_t seed=0U) noexcept
Computes XXH64 as required by the Zstandard frame checksum.
fse_table build_rle_fse_table(std::uint8_t symbol)
Constructs a one-symbol FSE table for RLE sequence mode.
fse_table build_predefined_offset_table()
Builds the format-defined predefined offset-code FSE table.
@ zstandard
Zstandard frame.
@ trailing_data
Bytes remain after the permitted stream members.
@ output_limit_exceeded
Decoding would exceed a configured resource limit.
@ invalid_option
An option or format value is outside its accepted range.
@ unsupported_feature
Valid input requires a format feature not implemented by the library.
@ invalid_data
The input does not conform to the selected format.
Options shared by compression operations.
std::optional< std::int32_t > level
Optional format-specific compression level.
Resource and stream-validation policy for decompression operations.
std::size_t maximum_output_size
Maximum total number of bytes the operation may emit.
bool allow_concatenated_streams
Whether to decode adjacent members for formats that define concatenation.
Persistent entropy tables and repeat offsets shared by compressed blocks.
std::optional< fse_table > offset_table
Most recent offset-code FSE table.
std::optional< fse_table > literal_length_table
Most recent literal-length FSE table.
std::array< std::size_t, 3U > repeated_offsets
Three repeat offsets in most-recent-first order.
std::optional< huffman_table > huffman_literals_table
Huffman table retained for treeless literal blocks.
std::optional< fse_table > match_length_table
Most recent match-length FSE table.
Encoded sequence length code and its additional-bit payload.
std::uint8_t number_of_bits
Number of significant bits in additional_value.
std::uint32_t additional_value
Additional value stored after the code.
std::uint8_t code
Sequence length code.
One state transition in an FSE decoding table.
std::uint8_t number_of_bits
Number of bits used to select the next state.
std::uint16_t baseline
Baseline added to the decoded transition bits.
std::uint8_t symbol
Symbol emitted when this state is decoded.
Native FSE decoding table indexed by the current decoder state.
std::uint8_t accuracy_log
Base-two logarithm of the state count.
std::vector< fse_entry > entries
State transitions indexed by current state.
A parsed Huffman tree description and its encoded byte length.
std::size_t consumed_bytes
Bytes occupied by the encoded tree description.
huffman_table table
Parsed canonical decoding tree.
One node in a native canonical Huffman decoding tree.
std::optional< std::uint16_t > one_child
Child selected by a one bit, if present.
std::optional< std::uint16_t > zero_child
Child selected by a zero bit, if present.
std::optional< std::uint8_t > symbol
Literal value for a leaf node.
Canonical Huffman decoding tree retained for treeless literal blocks.
std::vector< huffman_node > nodes
Tree nodes with the root at index zero.
Baseline and additional-bit count selected by a sequence length code.
std::uint8_t number_of_bits
Number of additional value bits following the code.
std::uint32_t baseline
Smallest length represented by this code.
Decoded literals and the number of compressed-block bytes they occupy.
std::vector< std::byte > literals
Regenerated literal bytes.
std::size_t consumed_bytes
Bytes occupied by the literals section in its compressed block.
Parsed normalized FSE probabilities and their encoded byte length.
std::vector< std::int16_t > probabilities
Normalized probability for every symbol through the last encoded symbol.
std::uint8_t accuracy_log
Accuracy log encoded by the description.
std::size_t consumed_bytes
Whole number of source bytes occupied by the description.