DeflateTables.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Array.h>
  8. #include <stdint.h>
  9. namespace Compress {
  10. // RFC 1951 - 3.2.5
  11. static constexpr struct {
  12. u16 symbol;
  13. u16 base_length;
  14. u16 extra_bits;
  15. } packed_length_symbols[29] = {
  16. { 257, 3, 0 },
  17. { 258, 4, 0 },
  18. { 259, 5, 0 },
  19. { 260, 6, 0 },
  20. { 261, 7, 0 },
  21. { 262, 8, 0 },
  22. { 263, 9, 0 },
  23. { 264, 10, 0 },
  24. { 265, 11, 1 },
  25. { 266, 13, 1 },
  26. { 267, 15, 1 },
  27. { 268, 17, 1 },
  28. { 269, 19, 2 },
  29. { 270, 23, 2 },
  30. { 271, 27, 2 },
  31. { 272, 31, 2 },
  32. { 273, 35, 3 },
  33. { 274, 43, 3 },
  34. { 275, 51, 3 },
  35. { 276, 59, 3 },
  36. { 277, 67, 4 },
  37. { 278, 83, 4 },
  38. { 279, 99, 4 },
  39. { 280, 115, 4 },
  40. { 281, 131, 5 },
  41. { 282, 163, 5 },
  42. { 283, 195, 5 },
  43. { 284, 227, 5 },
  44. { 285, 258, 0 }
  45. };
  46. // RFC 1951 - 3.2.5
  47. static constexpr struct {
  48. u16 symbol;
  49. u16 base_distance;
  50. u16 extra_bits;
  51. } packed_distances[31] = {
  52. { 0, 1, 0 },
  53. { 1, 2, 0 },
  54. { 2, 3, 0 },
  55. { 3, 4, 0 },
  56. { 4, 5, 1 },
  57. { 5, 7, 1 },
  58. { 6, 9, 2 },
  59. { 7, 13, 2 },
  60. { 8, 17, 3 },
  61. { 9, 25, 3 },
  62. { 10, 33, 4 },
  63. { 11, 49, 4 },
  64. { 12, 65, 5 },
  65. { 13, 97, 5 },
  66. { 14, 129, 6 },
  67. { 15, 193, 6 },
  68. { 16, 257, 7 },
  69. { 17, 385, 7 },
  70. { 18, 513, 8 },
  71. { 19, 769, 8 },
  72. { 20, 1025, 9 },
  73. { 21, 1537, 9 },
  74. { 22, 2049, 10 },
  75. { 23, 3073, 10 },
  76. { 24, 4097, 11 },
  77. { 25, 6145, 11 },
  78. { 26, 8193, 12 },
  79. { 27, 12289, 12 },
  80. { 28, 16385, 13 },
  81. { 29, 24577, 13 },
  82. { 30, 32 * KiB + 1, 0 }, // signifies end
  83. };
  84. // RFC 1951 - 3.2.6
  85. static constexpr struct {
  86. u16 base_value;
  87. u16 bits;
  88. } fixed_literal_bits[5] = {
  89. { 0, 8 },
  90. { 144, 9 },
  91. { 256, 7 },
  92. { 280, 8 },
  93. { 288, 0 } // signifies end
  94. };
  95. // RFC 1951 - 3.2.7
  96. static constexpr size_t code_lengths_code_lengths_order[] { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
  97. static consteval Array<u16, 259> generate_length_to_symbol()
  98. {
  99. Array<u16, 259> array = { UINT16_MAX, UINT16_MAX, UINT16_MAX }; // there are 256 valid lengths (3-258) + 3 invalid lengths (0-2)
  100. size_t base_length = 0;
  101. for (size_t len = 3; len < 259; len++) {
  102. if (len == packed_length_symbols[base_length + 1].base_length)
  103. base_length++;
  104. array[len] = packed_length_symbols[base_length].symbol;
  105. }
  106. return array;
  107. }
  108. static constexpr auto length_to_symbol = generate_length_to_symbol();
  109. static consteval Array<u16, 256> generate_distance_to_base_lo()
  110. {
  111. Array<u16, 256> array;
  112. size_t base_distance = 0;
  113. for (size_t dist = 1; dist <= 256; dist++) {
  114. if (dist == packed_distances[base_distance + 1].base_distance)
  115. base_distance++;
  116. array[dist - 1] = packed_distances[base_distance].symbol;
  117. }
  118. return array;
  119. }
  120. static constexpr auto distance_to_base_lo = generate_distance_to_base_lo();
  121. static consteval Array<u16, 256> generate_distance_to_base_hi()
  122. {
  123. Array<u16, 256> array = { UINT16_MAX, UINT16_MAX };
  124. size_t base_distance = 16;
  125. for (size_t dist = 257; dist <= 32 * KiB; dist++) {
  126. if (dist == packed_distances[base_distance + 1].base_distance)
  127. base_distance++;
  128. array[(dist - 1) >> 7] = packed_distances[base_distance].symbol;
  129. }
  130. return array;
  131. }
  132. static constexpr auto distance_to_base_hi = generate_distance_to_base_hi();
  133. static consteval Array<u8, 288> generate_fixed_literal_bit_lengths()
  134. {
  135. Array<u8, 288> array;
  136. for (size_t i = 0; i < 4; i++) {
  137. array.span().slice(fixed_literal_bits[i].base_value, fixed_literal_bits[i + 1].base_value - fixed_literal_bits[i].base_value).fill(fixed_literal_bits[i].bits);
  138. }
  139. return array;
  140. }
  141. static constexpr auto fixed_literal_bit_lengths = generate_fixed_literal_bit_lengths();
  142. static consteval Array<u8, 32> generate_fixed_distance_bit_lengths()
  143. {
  144. Array<u8, 32> array;
  145. array.fill(5);
  146. return array;
  147. }
  148. static constexpr auto fixed_distance_bit_lengths = generate_fixed_distance_bit_lengths();
  149. static consteval u8 reverse8(u8 value)
  150. {
  151. u8 result = 0;
  152. for (size_t i = 0; i < 8; i++) {
  153. if (value & (1 << i))
  154. result |= 1 << (7 - i);
  155. }
  156. return result;
  157. }
  158. static consteval Array<u8, UINT8_MAX + 1> generate_reverse8_lookup_table()
  159. {
  160. Array<u8, UINT8_MAX + 1> array;
  161. for (size_t i = 0; i <= UINT8_MAX; i++) {
  162. array[i] = reverse8(i);
  163. }
  164. return array;
  165. }
  166. static constexpr auto reverse8_lookup_table = generate_reverse8_lookup_table();
  167. // Lookup-table based bit swap
  168. ALWAYS_INLINE static u16 fast_reverse16(u16 value, size_t bits)
  169. {
  170. VERIFY(bits <= 16);
  171. u16 lo = value & 0xff;
  172. u16 hi = value >> 8;
  173. u16 reversed = (u16)((reverse8_lookup_table[lo] << 8) | reverse8_lookup_table[hi]);
  174. return reversed >> (16 - bits);
  175. }
  176. }