interface.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // Copyright 2010 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Example how to use CRC implementation via the interface which
  15. // hides details of implementation.
  16. //
  17. // The raw implementation is not indended to be used in a project
  18. // directly because:
  19. // - Implementation lives in the header files because that is the
  20. // only way to use templates efficiently.
  21. // - Header files are quite "dirty" -- they define and use a
  22. // lot of macros. Bringing these macros to all files in
  23. // a project is not particularly good idea.
  24. // - The code takes forever to compile with GCC (e.g. GCC
  25. // 4.4.3 and 4.5.0 compile the unittest for about 30 seconds).
  26. //
  27. // Solution:
  28. // - Create your own, clean interface.
  29. // - Do not expose interface internals in a header file.
  30. // - Proxy all calls to your interface to CRC implementation.
  31. // - Keep only one copy of actual implementation.
  32. #ifndef CRCUTIL_INTERFACE_H_
  33. #define CRCUTIL_INTERFACE_H_
  34. #include "std_headers.h" // size_t
  35. namespace crcutil_interface {
  36. // Many projects define their own uint64. Do it here.
  37. typedef unsigned long long UINT64;
  38. class CRC {
  39. public:
  40. // Creates new instance of CRC class.
  41. // If arguments are illegal (e.g. provided generating polynomial
  42. // has more bits than provided degree), returns NULL.
  43. //
  44. // poly_* - generating polynomial (reversed bit format).
  45. // degree - degree of generating polynomial.
  46. // canonical - if true, input CRC value will be XOR'ed with
  47. // (inverted) before and after CRC computation.
  48. // roll_start_value - starting value of rolling CRC.
  49. // roll_window_bytes - length of rolling CRC window in bytes.
  50. // If roll_length is 0, roll_start_value
  51. // shall be 0.
  52. // use_sse4_2 - if true, use SSE4.2 crc32 instruction to compute
  53. // CRC when generating polynomial is CRC32C (Castagnoli)
  54. // allocated_memory - optional (may be NULL) address of a variable
  55. // to store the address of actually allocated memory.
  56. static CRC *Create(UINT64 poly_lo,
  57. UINT64 poly_hi,
  58. size_t degree,
  59. bool canonical,
  60. UINT64 roll_start_value_lo,
  61. UINT64 roll_start_value_hi,
  62. size_t roll_window_bytes,
  63. bool use_sse4_2,
  64. const void **allocated_memory);
  65. // Deletes the instance of CRC class.
  66. virtual void Delete() = 0;
  67. // Returns true if SSE4.2 is available.
  68. static bool IsSSE42Available();
  69. // Returns generating polynomial.
  70. virtual void GeneratingPolynomial(/* OUT */ UINT64 *lo,
  71. /* OUT */ UINT64 *hi = NULL) const = 0;
  72. // Returns degree of generating polynomial.
  73. virtual size_t Degree() const = 0;
  74. // Returns canonization constant used to XOR crc value
  75. // before and after CRC computation.
  76. virtual void CanonizeValue(/* OUT */ UINT64 *lo,
  77. /* OUT */ UINT64 *hi = NULL) const = 0;
  78. // Returns rolling CRC starting value.
  79. virtual void RollStartValue(/* OUT */ UINT64 *lo,
  80. /* OUT */ UINT64 *hi = NULL) const = 0;
  81. // Returns length of rolling CRC window.
  82. virtual size_t RollWindowBytes() const = 0;
  83. // Returns CRC of CRC tables to enable verification
  84. // of integrity of CRC function itself by comparing
  85. // the result with pre-computed value.
  86. virtual void SelfCheckValue(/* OUT */ UINT64 *lo,
  87. /* OUT */ UINT64 *hi = NULL) const = 0;
  88. // Given CRC value of previous chunk of data,
  89. // extends it to new chunk, retuning the result in-place.
  90. //
  91. // If degree of CRC polynomial is 64 or less,
  92. // (*hi) will not be touched.
  93. virtual void Compute(const void *data,
  94. size_t bytes,
  95. /* INOUT */ UINT64 *lo,
  96. /* INOUT */ UINT64 *hi = NULL) const = 0;
  97. // Starts rolling CRC by computing CRC of first
  98. // "roll_length" bytes of "data", using "roll_start_value"
  99. // as starting value (see Create()).
  100. // Should not be called if the value of "roll_value" was 0.
  101. virtual void RollStart(const void *data,
  102. /* OUT */ UINT64 *lo,
  103. /* OUT */ UINT64 *hi = NULL) const = 0;
  104. // Rolls CRC by 1 byte, given the bytes leaving and
  105. // entering the window of "roll_length" bytes.
  106. // RollStart() should be called before "Roll".
  107. // Should not be called if the value of "roll_value" was 0.
  108. virtual void Roll(size_t byte_out,
  109. size_t byte_in,
  110. /* INOUT */ UINT64 *lo,
  111. /* INOUT */ UINT64 *hi = NULL) const = 0;
  112. // Computes CRC of sequence of zeroes -- without touching the data.
  113. virtual void CrcOfZeroes(UINT64 bytes,
  114. /* INOUT */ UINT64 *lo,
  115. /* INOUT */ UINT64 *hi = NULL) const = 0;
  116. // Computes value of CRC(A, bytes, start_new) given known
  117. // crc=CRC(A, bytes, start_old) -- without touching the data.
  118. virtual void ChangeStartValue(
  119. UINT64 start_old_lo, UINT64 start_old_hi,
  120. UINT64 start_new_lo, UINT64 start_new_hi,
  121. UINT64 bytes,
  122. /* INOUT */ UINT64 *lo,
  123. /* INOUT */ UINT64 *hi = NULL) const = 0;
  124. // Returns CRC of concatenation of blocks A and B when CRCs
  125. // of blocks A and B are known -- without touching the data.
  126. //
  127. // To be precise, given CRC(A, |A|, startA) and CRC(B, |B|, 0),
  128. // returns CRC(AB, |AB|, startA).
  129. virtual void Concatenate(UINT64 crcB_lo, UINT64 crcB_hi,
  130. UINT64 bytes_B,
  131. /* INOUT */ UINT64* crcA_lo,
  132. /* INOUT */ UINT64* crcA_hi = NULL) const = 0;
  133. // Given CRC of a message, stores extra (degree + 7)/8 bytes after
  134. // the message so that CRC(message+extra, start) = result.
  135. // Does not change CRC start value (use ChangeStartValue for that).
  136. // Returns number of stored bytes.
  137. virtual size_t StoreComplementaryCrc(
  138. void *dst,
  139. UINT64 message_crc_lo, UINT64 message_crc_hi,
  140. UINT64 result_crc_lo, UINT64 result_crc_hi = 0) const = 0;
  141. // Stores given CRC of a message as (degree + 7)/8 bytes filled
  142. // with 0s to the right. Returns number of stored bytes.
  143. // CRC of the message and stored CRC is a constant value returned
  144. // by CrcOfCrc() -- it does not depend on contents of the message.
  145. virtual size_t StoreCrc(/* OUT */ void *dst,
  146. UINT64 lo,
  147. UINT64 hi = 0) const = 0;
  148. // Computes expected CRC value of CRC(Message,CRC(Message))
  149. // when CRC is stored after the message. This value is fixed
  150. // and does not depend on the message or CRC start value.
  151. virtual void CrcOfCrc(/* OUT */ UINT64 *lo,
  152. /* OUT */ UINT64 *hi = NULL) const = 0;
  153. protected:
  154. // CRC instance should be created only once (most of the time):
  155. // - Creation and initializion is relatively expensive.
  156. // - CRC is fully defined by its generating polynomials
  157. // (well, and few more parameters).
  158. // - CRC instances are pure constants. There is no
  159. // reason to have 2 instances of the same CRC.
  160. // - There are not too many generating polynomials that are
  161. // used on practice. It is hard to imagine a project
  162. // which uses 50 different generating polynomials.
  163. // Thus, a handful of CRC instances is sufficient
  164. // to cover the needs of even very large project.
  165. // - Finally and most importantly, CRC tables should be
  166. // aligned properly. No, the instances of CRC class
  167. // are not created by blind "new" -- they use placement
  168. // "new" and, in absense of placement "delete",
  169. // should be deleted by calling explicit Delete() method.
  170. virtual ~CRC();
  171. // Cannot instantiate the class -- instances may be created
  172. // by CRC::Create() only.
  173. CRC();
  174. };
  175. } // namespace crcutil_interface
  176. #endif // CRCUTIL_INTERFACE_H_