command.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* Copyright 2013 Google Inc. All Rights Reserved.
  2. Distributed under MIT license.
  3. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
  4. */
  5. /* This class models a sequence of literals and a backward reference copy. */
  6. #ifndef BROTLI_ENC_COMMAND_H_
  7. #define BROTLI_ENC_COMMAND_H_
  8. #include "../common/types.h"
  9. #include "../common/port.h"
  10. #include "./fast_log.h"
  11. #include "./prefix.h"
  12. #if defined(__cplusplus) || defined(c_plusplus)
  13. extern "C" {
  14. #endif
  15. static uint32_t kInsBase[] = { 0, 1, 2, 3, 4, 5, 6, 8, 10, 14, 18, 26, 34, 50,
  16. 66, 98, 130, 194, 322, 578, 1090, 2114, 6210, 22594 };
  17. static uint32_t kInsExtra[] = { 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4,
  18. 5, 5, 6, 7, 8, 9, 10, 12, 14, 24 };
  19. static uint32_t kCopyBase[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 18, 22, 30,
  20. 38, 54, 70, 102, 134, 198, 326, 582, 1094, 2118 };
  21. static uint32_t kCopyExtra[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
  22. 4, 4, 5, 5, 6, 7, 8, 9, 10, 24 };
  23. static BROTLI_INLINE uint16_t GetInsertLengthCode(size_t insertlen) {
  24. if (insertlen < 6) {
  25. return (uint16_t)insertlen;
  26. } else if (insertlen < 130) {
  27. uint32_t nbits = Log2FloorNonZero(insertlen - 2) - 1u;
  28. return (uint16_t)((nbits << 1) + ((insertlen - 2) >> nbits) + 2);
  29. } else if (insertlen < 2114) {
  30. return (uint16_t)(Log2FloorNonZero(insertlen - 66) + 10);
  31. } else if (insertlen < 6210) {
  32. return 21u;
  33. } else if (insertlen < 22594) {
  34. return 22u;
  35. } else {
  36. return 23u;
  37. }
  38. }
  39. static BROTLI_INLINE uint16_t GetCopyLengthCode(size_t copylen) {
  40. if (copylen < 10) {
  41. return (uint16_t)(copylen - 2);
  42. } else if (copylen < 134) {
  43. uint32_t nbits = Log2FloorNonZero(copylen - 6) - 1u;
  44. return (uint16_t)((nbits << 1) + ((copylen - 6) >> nbits) + 4);
  45. } else if (copylen < 2118) {
  46. return (uint16_t)(Log2FloorNonZero(copylen - 70) + 12);
  47. } else {
  48. return 23u;
  49. }
  50. }
  51. static BROTLI_INLINE uint16_t CombineLengthCodes(
  52. uint16_t inscode, uint16_t copycode, int use_last_distance) {
  53. uint16_t bits64 =
  54. (uint16_t)((copycode & 0x7u) | ((inscode & 0x7u) << 3));
  55. if (use_last_distance && inscode < 8 && copycode < 16) {
  56. return (copycode < 8) ? bits64 : (bits64 | 64);
  57. } else {
  58. /* "To convert an insert-and-copy length code to an insert length code and
  59. a copy length code, the following table can be used" */
  60. static const uint16_t cells[9] = { 128u, 192u, 384u, 256u, 320u, 512u,
  61. 448u, 576u, 640u };
  62. return cells[(copycode >> 3) + 3 * (inscode >> 3)] | bits64;
  63. }
  64. }
  65. static BROTLI_INLINE void GetLengthCode(size_t insertlen, size_t copylen,
  66. int use_last_distance,
  67. uint16_t* code) {
  68. uint16_t inscode = GetInsertLengthCode(insertlen);
  69. uint16_t copycode = GetCopyLengthCode(copylen);
  70. *code = CombineLengthCodes(inscode, copycode, use_last_distance);
  71. }
  72. static BROTLI_INLINE uint32_t GetInsertBase(uint16_t inscode) {
  73. return kInsBase[inscode];
  74. }
  75. static BROTLI_INLINE uint32_t GetInsertExtra(uint16_t inscode) {
  76. return kInsExtra[inscode];
  77. }
  78. static BROTLI_INLINE uint32_t GetCopyBase(uint16_t copycode) {
  79. return kCopyBase[copycode];
  80. }
  81. static BROTLI_INLINE uint32_t GetCopyExtra(uint16_t copycode) {
  82. return kCopyExtra[copycode];
  83. }
  84. typedef struct Command {
  85. uint32_t insert_len_;
  86. /* Stores copy_len in low 24 bits and copy_len XOR copy_code in high 8 bit. */
  87. uint32_t copy_len_;
  88. uint32_t dist_extra_;
  89. uint16_t cmd_prefix_;
  90. uint16_t dist_prefix_;
  91. } Command;
  92. /* distance_code is e.g. 0 for same-as-last short code, or 16 for offset 1. */
  93. static BROTLI_INLINE void InitCommand(Command* self, size_t insertlen,
  94. size_t copylen, size_t copylen_code, size_t distance_code) {
  95. self->insert_len_ = (uint32_t)insertlen;
  96. self->copy_len_ = (uint32_t)(copylen | ((copylen_code ^ copylen) << 24));
  97. /* The distance prefix and extra bits are stored in this Command as if
  98. npostfix and ndirect were 0, they are only recomputed later after the
  99. clustering if needed. */
  100. PrefixEncodeCopyDistance(
  101. distance_code, 0, 0, &self->dist_prefix_, &self->dist_extra_);
  102. GetLengthCode(
  103. insertlen, copylen_code, self->dist_prefix_ == 0, &self->cmd_prefix_);
  104. }
  105. static BROTLI_INLINE void InitInsertCommand(Command* self, size_t insertlen) {
  106. self->insert_len_ = (uint32_t)insertlen;
  107. self->copy_len_ = 4 << 24;
  108. self->dist_extra_ = 0;
  109. self->dist_prefix_ = 16;
  110. GetLengthCode(insertlen, 4, 0, &self->cmd_prefix_);
  111. }
  112. static BROTLI_INLINE uint32_t CommandDistanceCode(const Command* self) {
  113. if (self->dist_prefix_ < 16) {
  114. return self->dist_prefix_;
  115. } else {
  116. uint32_t nbits = self->dist_extra_ >> 24;
  117. uint32_t extra = self->dist_extra_ & 0xffffff;
  118. uint32_t prefix = self->dist_prefix_ - 12u - 2u * nbits;
  119. return (prefix << nbits) + extra + 12;
  120. }
  121. }
  122. static BROTLI_INLINE uint32_t CommandDistanceContext(const Command* self) {
  123. uint32_t r = self->cmd_prefix_ >> 6;
  124. uint32_t c = self->cmd_prefix_ & 7;
  125. if ((r == 0 || r == 2 || r == 4 || r == 7) && (c <= 2)) {
  126. return c;
  127. }
  128. return 3;
  129. }
  130. static BROTLI_INLINE uint32_t CommandCopyLen(const Command* self) {
  131. return self->copy_len_ & 0xFFFFFF;
  132. }
  133. static BROTLI_INLINE uint32_t CommandCopyLenCode(const Command* self) {
  134. return (self->copy_len_ & 0xFFFFFF) ^ (self->copy_len_ >> 24);
  135. }
  136. #if defined(__cplusplus) || defined(c_plusplus)
  137. } /* extern "C" */
  138. #endif
  139. #endif /* BROTLI_ENC_COMMAND_H_ */