snappy-internal.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Copyright 2008 Google Inc. All Rights Reserved.
  2. //
  3. // Redistribution and use in source and binary forms, with or without
  4. // modification, are permitted provided that the following conditions are
  5. // met:
  6. //
  7. // * Redistributions of source code must retain the above copyright
  8. // notice, this list of conditions and the following disclaimer.
  9. // * Redistributions in binary form must reproduce the above
  10. // copyright notice, this list of conditions and the following disclaimer
  11. // in the documentation and/or other materials provided with the
  12. // distribution.
  13. // * Neither the name of Google Inc. nor the names of its
  14. // contributors may be used to endorse or promote products derived from
  15. // this software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  20. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  21. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  22. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  23. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  27. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. //
  29. // Internals shared between the Snappy implementation and its unittest.
  30. #ifndef UTIL_SNAPPY_SNAPPY_INTERNAL_H_
  31. #define UTIL_SNAPPY_SNAPPY_INTERNAL_H_
  32. #include "snappy-stubs-internal.h"
  33. namespace snappy {
  34. namespace internal {
  35. class WorkingMemory {
  36. public:
  37. WorkingMemory() : large_table_(NULL) { }
  38. ~WorkingMemory() { delete[] large_table_; }
  39. // Allocates and clears a hash table using memory in "*this",
  40. // stores the number of buckets in "*table_size" and returns a pointer to
  41. // the base of the hash table.
  42. uint16* GetHashTable(size_t input_size, int* table_size);
  43. private:
  44. uint16 small_table_[1<<10]; // 2KB
  45. uint16* large_table_; // Allocated only when needed
  46. DISALLOW_COPY_AND_ASSIGN(WorkingMemory);
  47. };
  48. // Flat array compression that does not emit the "uncompressed length"
  49. // prefix. Compresses "input" string to the "*op" buffer.
  50. //
  51. // REQUIRES: "input_length <= kBlockSize"
  52. // REQUIRES: "op" points to an array of memory that is at least
  53. // "MaxCompressedLength(input_length)" in size.
  54. // REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero.
  55. // REQUIRES: "table_size" is a power of two
  56. //
  57. // Returns an "end" pointer into "op" buffer.
  58. // "end - op" is the compressed size of "input".
  59. char* CompressFragment(const char* input,
  60. size_t input_length,
  61. char* op,
  62. uint16* table,
  63. const int table_size);
  64. // Return the largest n such that
  65. //
  66. // s1[0,n-1] == s2[0,n-1]
  67. // and n <= (s2_limit - s2).
  68. //
  69. // Does not read *s2_limit or beyond.
  70. // Does not read *(s1 + (s2_limit - s2)) or beyond.
  71. // Requires that s2_limit >= s2.
  72. //
  73. // Separate implementation for x86_64, for speed. Uses the fact that
  74. // x86_64 is little endian.
  75. #if defined(ARCH_K8)
  76. static inline int FindMatchLength(const char* s1,
  77. const char* s2,
  78. const char* s2_limit) {
  79. assert(s2_limit >= s2);
  80. int matched = 0;
  81. // Find out how long the match is. We loop over the data 64 bits at a
  82. // time until we find a 64-bit block that doesn't match; then we find
  83. // the first non-matching bit and use that to calculate the total
  84. // length of the match.
  85. while (PREDICT_TRUE(s2 <= s2_limit - 8)) {
  86. if (PREDICT_FALSE(UNALIGNED_LOAD64(s2) == UNALIGNED_LOAD64(s1 + matched))) {
  87. s2 += 8;
  88. matched += 8;
  89. } else {
  90. // On current (mid-2008) Opteron models there is a 3% more
  91. // efficient code sequence to find the first non-matching byte.
  92. // However, what follows is ~10% better on Intel Core 2 and newer,
  93. // and we expect AMD's bsf instruction to improve.
  94. uint64 x = UNALIGNED_LOAD64(s2) ^ UNALIGNED_LOAD64(s1 + matched);
  95. int matching_bits = Bits::FindLSBSetNonZero64(x);
  96. matched += matching_bits >> 3;
  97. return matched;
  98. }
  99. }
  100. while (PREDICT_TRUE(s2 < s2_limit)) {
  101. if (PREDICT_TRUE(s1[matched] == *s2)) {
  102. ++s2;
  103. ++matched;
  104. } else {
  105. return matched;
  106. }
  107. }
  108. return matched;
  109. }
  110. #else
  111. static inline int FindMatchLength(const char* s1,
  112. const char* s2,
  113. const char* s2_limit) {
  114. // Implementation based on the x86-64 version, above.
  115. assert(s2_limit >= s2);
  116. int matched = 0;
  117. while (s2 <= s2_limit - 4 &&
  118. UNALIGNED_LOAD32(s2) == UNALIGNED_LOAD32(s1 + matched)) {
  119. s2 += 4;
  120. matched += 4;
  121. }
  122. if (LittleEndian::IsLittleEndian() && s2 <= s2_limit - 4) {
  123. uint32 x = UNALIGNED_LOAD32(s2) ^ UNALIGNED_LOAD32(s1 + matched);
  124. int matching_bits = Bits::FindLSBSetNonZero(x);
  125. matched += matching_bits >> 3;
  126. } else {
  127. while ((s2 < s2_limit) && (s1[matched] == *s2)) {
  128. ++s2;
  129. ++matched;
  130. }
  131. }
  132. return matched;
  133. }
  134. #endif
  135. } // end namespace internal
  136. } // end namespace snappy
  137. #endif // UTIL_SNAPPY_SNAPPY_INTERNAL_H_