关键词搜索

源码搜索 ×
×

漫话Redis源码之六十九

发布2022-01-23浏览689次

详情内容

反转字节,挺常见的操作。与内存有关的操作,常常会涉及到位运算,很快速。

  1. /* Reverse the bytes in a 64-bit word. */
  2. static inline uint64_t rev8(uint64_t a) {
  3. #if defined(__GNUC__) || defined(__clang__)
  4. return __builtin_bswap64(a);
  5. #else
  6. uint64_t m;
  7. m = UINT64_C(0xff00ff00ff00ff);
  8. a = ((a >> 8) & m) | (a & m) << 8;
  9. m = UINT64_C(0xffff0000ffff);
  10. a = ((a >> 16) & m) | (a & m) << 16;
  11. return a >> 32 | a << 32;
  12. #endif
  13. }
  14. /* This function is called once to initialize the CRC table for use on a
  15. big-endian architecture. */
  16. void crcspeed64big_init(crcfn64 fn, uint64_t big_table[8][256]) {
  17. /* Create the little endian table then reverse all the entries. */
  18. crcspeed64little_init(fn, big_table);
  19. for (int k = 0; k < 8; k++) {
  20. for (int n = 0; n < 256; n++) {
  21. big_table[k][n] = rev8(big_table[k][n]);
  22. }
  23. }
  24. }
  25. void crcspeed16big_init(crcfn16 fn, uint16_t big_table[8][256]) {
  26. /* Create the little endian table then reverse all the entries. */
  27. crcspeed16little_init(fn, big_table);
  28. for (int k = 0; k < 8; k++) {
  29. for (int n = 0; n < 256; n++) {
  30. big_table[k][n] = rev8(big_table[k][n]);
  31. }
  32. }
  33. }
  34. /* Calculate a non-inverted CRC multiple bytes at a time on a little-endian
  35. * architecture. If you need inverted CRC, invert *before* calling and invert
  36. * *after* calling.
  37. * 64 bit crc = process 8 bytes at once;
  38. */
  39. uint64_t crcspeed64little(uint64_t little_table[8][256], uint64_t crc,
  40. void *buf, size_t len) {
  41. unsigned char *next = buf;
  42. /* process individual bytes until we reach an 8-byte aligned pointer */
  43. while (len && ((uintptr_t)next & 7) != 0) {
  44. crc = little_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
  45. len--;
  46. }
  47. /* fast middle processing, 8 bytes (aligned!) per loop */
  48. while (len >= 8) {
  49. crc ^= *(uint64_t *)next;
  50. crc = little_table[7][crc & 0xff] ^
  51. little_table[6][(crc >> 8) & 0xff] ^
  52. little_table[5][(crc >> 16) & 0xff] ^
  53. little_table[4][(crc >> 24) & 0xff] ^
  54. little_table[3][(crc >> 32) & 0xff] ^
  55. little_table[2][(crc >> 40) & 0xff] ^
  56. little_table[1][(crc >> 48) & 0xff] ^
  57. little_table[0][crc >> 56];
  58. next += 8;
  59. len -= 8;
  60. }
  61. /* process remaining bytes (can't be larger than 8) */
  62. while (len) {
  63. crc = little_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
  64. len--;
  65. }
  66. return crc;
  67. }
  68. uint16_t crcspeed16little(uint16_t little_table[8][256], uint16_t crc,
  69. void *buf, size_t len) {
  70. unsigned char *next = buf;
  71. /* process individual bytes until we reach an 8-byte aligned pointer */
  72. while (len && ((uintptr_t)next & 7) != 0) {
  73. crc = little_table[0][((crc >> 8) ^ *next++) & 0xff] ^ (crc << 8);
  74. len--;
  75. }
  76. /* fast middle processing, 8 bytes (aligned!) per loop */
  77. while (len >= 8) {
  78. uint64_t n = *(uint64_t *)next;
  79. crc = little_table[7][(n & 0xff) ^ ((crc >> 8) & 0xff)] ^
  80. little_table[6][((n >> 8) & 0xff) ^ (crc & 0xff)] ^
  81. little_table[5][(n >> 16) & 0xff] ^
  82. little_table[4][(n >> 24) & 0xff] ^
  83. little_table[3][(n >> 32) & 0xff] ^
  84. little_table[2][(n >> 40) & 0xff] ^
  85. little_table[1][(n >> 48) & 0xff] ^
  86. little_table[0][n >> 56];
  87. next += 8;
  88. len -= 8;
  89. }
  90. /* process remaining bytes (can't be larger than 8) */
  91. while (len) {
  92. crc = little_table[0][((crc >> 8) ^ *next++) & 0xff] ^ (crc << 8);
  93. len--;
  94. }
  95. return crc;
  96. }
  97. /* Calculate a non-inverted CRC eight bytes at a time on a big-endian
  98. * architecture.
  99. */
  100. uint64_t crcspeed64big(uint64_t big_table[8][256], uint64_t crc, void *buf,
  101. size_t len) {
  102. unsigned char *next = buf;
  103. crc = rev8(crc);
  104. while (len && ((uintptr_t)next & 7) != 0) {
  105. crc = big_table[0][(crc >> 56) ^ *next++] ^ (crc << 8);
  106. len--;
  107. }
  108. while (len >= 8) {
  109. crc ^= *(uint64_t *)next;
  110. crc = big_table[0][crc & 0xff] ^
  111. big_table[1][(crc >> 8) & 0xff] ^
  112. big_table[2][(crc >> 16) & 0xff] ^
  113. big_table[3][(crc >> 24) & 0xff] ^
  114. big_table[4][(crc >> 32) & 0xff] ^
  115. big_table[5][(crc >> 40) & 0xff] ^
  116. big_table[6][(crc >> 48) & 0xff] ^
  117. big_table[7][crc >> 56];
  118. next += 8;
  119. len -= 8;
  120. }
  121. while (len) {
  122. crc = big_table[0][(crc >> 56) ^ *next++] ^ (crc << 8);
  123. len--;
  124. }
  125. return rev8(crc);
  126. }
  127. /* WARNING: Completely untested on big endian architecture. Possibly broken. */
  128. uint16_t crcspeed16big(uint16_t big_table[8][256], uint16_t crc_in, void *buf,
  129. size_t len) {
  130. unsigned char *next = buf;
  131. uint64_t crc = crc_in;
  132. crc = rev8(crc);
  133. while (len && ((uintptr_t)next & 7) != 0) {
  134. crc = big_table[0][((crc >> (56 - 8)) ^ *next++) & 0xff] ^ (crc >> 8);
  135. len--;
  136. }
  137. while (len >= 8) {
  138. uint64_t n = *(uint64_t *)next;
  139. crc = big_table[0][(n & 0xff) ^ ((crc >> (56 - 8)) & 0xff)] ^
  140. big_table[1][((n >> 8) & 0xff) ^ (crc & 0xff)] ^
  141. big_table[2][(n >> 16) & 0xff] ^
  142. big_table[3][(n >> 24) & 0xff] ^
  143. big_table[4][(n >> 32) & 0xff] ^
  144. big_table[5][(n >> 40) & 0xff] ^
  145. big_table[6][(n >> 48) & 0xff] ^
  146. big_table[7][n >> 56];
  147. next += 8;
  148. len -= 8;
  149. }
  150. while (len) {
  151. crc = big_table[0][((crc >> (56 - 8)) ^ *next++) & 0xff] ^ (crc >> 8);
  152. len--;
  153. }
  154. return rev8(crc);
  155. }
  156. /* Return the CRC of buf[0..len-1] with initial crc, processing eight bytes
  157. at a time using passed-in lookup table.
  158. This selects one of two routines depending on the endianess of
  159. the architecture. */
  160. uint64_t crcspeed64native(uint64_t table[8][256], uint64_t crc, void *buf,
  161. size_t len) {
  162. uint64_t n = 1;
  163. return *(char *)&n ? crcspeed64little(table, crc, buf, len)
  164. : crcspeed64big(table, crc, buf, len);
  165. }
  166. uint16_t crcspeed16native(uint16_t table[8][256], uint16_t crc, void *buf,
  167. size_t len) {
  168. uint64_t n = 1;
  169. return *(char *)&n ? crcspeed16little(table, crc, buf, len)
  170. : crcspeed16big(table, crc, buf, len);
  171. }
  172. /* Initialize CRC lookup table in architecture-dependent manner. */
  173. void crcspeed64native_init(crcfn64 fn, uint64_t table[8][256]) {
  174. uint64_t n = 1;
  175. *(char *)&n ? crcspeed64little_init(fn, table)
  176. : crcspeed64big_init(fn, table);
  177. }
  178. void crcspeed16native_init(crcfn16 fn, uint16_t table[8][256]) {
  179. uint64_t n = 1;
  180. *(char *)&n ? crcspeed16little_init(fn, table)
  181. : crcspeed16big_init(fn, table);
  182. }

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载