Coverage Report

Created: 2026-06-22 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/brpc/src/butil/crc32c.cc
Line
Count
Source
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under the BSD-style license found in the
3
//  LICENSE file in the root directory of this source tree. An additional grant
4
//  of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7
// Use of this source code is governed by a BSD-style license that can be
8
// found in the LICENSE file. See the AUTHORS file for names of contributors.
9
//
10
// A portable implementation of crc32c, optimized to handle
11
// four bytes at a time.
12
13
#include "butil/crc32c.h"
14
15
#include <string.h>
16
#include <stdint.h>
17
#ifdef __SSE4_2__
18
#include <nmmintrin.h>
19
#endif
20
#include "butil/build_config.h"
21
22
namespace butil {
23
namespace crc32c {
24
25
static const uint32_t table0_[256] = {
26
  0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4,
27
  0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
28
  0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
29
  0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
30
  0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b,
31
  0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
32
  0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54,
33
  0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
34
  0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
35
  0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
36
  0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5,
37
  0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
38
  0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45,
39
  0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
40
  0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
41
  0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
42
  0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48,
43
  0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
44
  0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687,
45
  0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
46
  0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
47
  0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
48
  0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8,
49
  0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
50
  0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096,
51
  0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
52
  0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
53
  0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
54
  0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9,
55
  0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
56
  0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36,
57
  0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
58
  0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
59
  0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
60
  0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043,
61
  0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
62
  0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3,
63
  0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
64
  0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
65
  0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
66
  0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652,
67
  0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
68
  0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d,
69
  0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
70
  0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
71
  0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
72
  0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2,
73
  0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
74
  0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530,
75
  0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
76
  0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
77
  0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
78
  0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f,
79
  0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
80
  0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90,
81
  0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
82
  0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
83
  0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
84
  0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321,
85
  0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
86
  0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81,
87
  0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
88
  0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
89
  0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351
90
};
91
static const uint32_t table1_[256] = {
92
  0x00000000, 0x13a29877, 0x274530ee, 0x34e7a899,
93
  0x4e8a61dc, 0x5d28f9ab, 0x69cf5132, 0x7a6dc945,
94
  0x9d14c3b8, 0x8eb65bcf, 0xba51f356, 0xa9f36b21,
95
  0xd39ea264, 0xc03c3a13, 0xf4db928a, 0xe7790afd,
96
  0x3fc5f181, 0x2c6769f6, 0x1880c16f, 0x0b225918,
97
  0x714f905d, 0x62ed082a, 0x560aa0b3, 0x45a838c4,
98
  0xa2d13239, 0xb173aa4e, 0x859402d7, 0x96369aa0,
99
  0xec5b53e5, 0xfff9cb92, 0xcb1e630b, 0xd8bcfb7c,
100
  0x7f8be302, 0x6c297b75, 0x58ced3ec, 0x4b6c4b9b,
101
  0x310182de, 0x22a31aa9, 0x1644b230, 0x05e62a47,
102
  0xe29f20ba, 0xf13db8cd, 0xc5da1054, 0xd6788823,
103
  0xac154166, 0xbfb7d911, 0x8b507188, 0x98f2e9ff,
104
  0x404e1283, 0x53ec8af4, 0x670b226d, 0x74a9ba1a,
105
  0x0ec4735f, 0x1d66eb28, 0x298143b1, 0x3a23dbc6,
106
  0xdd5ad13b, 0xcef8494c, 0xfa1fe1d5, 0xe9bd79a2,
107
  0x93d0b0e7, 0x80722890, 0xb4958009, 0xa737187e,
108
  0xff17c604, 0xecb55e73, 0xd852f6ea, 0xcbf06e9d,
109
  0xb19da7d8, 0xa23f3faf, 0x96d89736, 0x857a0f41,
110
  0x620305bc, 0x71a19dcb, 0x45463552, 0x56e4ad25,
111
  0x2c896460, 0x3f2bfc17, 0x0bcc548e, 0x186eccf9,
112
  0xc0d23785, 0xd370aff2, 0xe797076b, 0xf4359f1c,
113
  0x8e585659, 0x9dface2e, 0xa91d66b7, 0xbabffec0,
114
  0x5dc6f43d, 0x4e646c4a, 0x7a83c4d3, 0x69215ca4,
115
  0x134c95e1, 0x00ee0d96, 0x3409a50f, 0x27ab3d78,
116
  0x809c2506, 0x933ebd71, 0xa7d915e8, 0xb47b8d9f,
117
  0xce1644da, 0xddb4dcad, 0xe9537434, 0xfaf1ec43,
118
  0x1d88e6be, 0x0e2a7ec9, 0x3acdd650, 0x296f4e27,
119
  0x53028762, 0x40a01f15, 0x7447b78c, 0x67e52ffb,
120
  0xbf59d487, 0xacfb4cf0, 0x981ce469, 0x8bbe7c1e,
121
  0xf1d3b55b, 0xe2712d2c, 0xd69685b5, 0xc5341dc2,
122
  0x224d173f, 0x31ef8f48, 0x050827d1, 0x16aabfa6,
123
  0x6cc776e3, 0x7f65ee94, 0x4b82460d, 0x5820de7a,
124
  0xfbc3faf9, 0xe861628e, 0xdc86ca17, 0xcf245260,
125
  0xb5499b25, 0xa6eb0352, 0x920cabcb, 0x81ae33bc,
126
  0x66d73941, 0x7575a136, 0x419209af, 0x523091d8,
127
  0x285d589d, 0x3bffc0ea, 0x0f186873, 0x1cbaf004,
128
  0xc4060b78, 0xd7a4930f, 0xe3433b96, 0xf0e1a3e1,
129
  0x8a8c6aa4, 0x992ef2d3, 0xadc95a4a, 0xbe6bc23d,
130
  0x5912c8c0, 0x4ab050b7, 0x7e57f82e, 0x6df56059,
131
  0x1798a91c, 0x043a316b, 0x30dd99f2, 0x237f0185,
132
  0x844819fb, 0x97ea818c, 0xa30d2915, 0xb0afb162,
133
  0xcac27827, 0xd960e050, 0xed8748c9, 0xfe25d0be,
134
  0x195cda43, 0x0afe4234, 0x3e19eaad, 0x2dbb72da,
135
  0x57d6bb9f, 0x447423e8, 0x70938b71, 0x63311306,
136
  0xbb8de87a, 0xa82f700d, 0x9cc8d894, 0x8f6a40e3,
137
  0xf50789a6, 0xe6a511d1, 0xd242b948, 0xc1e0213f,
138
  0x26992bc2, 0x353bb3b5, 0x01dc1b2c, 0x127e835b,
139
  0x68134a1e, 0x7bb1d269, 0x4f567af0, 0x5cf4e287,
140
  0x04d43cfd, 0x1776a48a, 0x23910c13, 0x30339464,
141
  0x4a5e5d21, 0x59fcc556, 0x6d1b6dcf, 0x7eb9f5b8,
142
  0x99c0ff45, 0x8a626732, 0xbe85cfab, 0xad2757dc,
143
  0xd74a9e99, 0xc4e806ee, 0xf00fae77, 0xe3ad3600,
144
  0x3b11cd7c, 0x28b3550b, 0x1c54fd92, 0x0ff665e5,
145
  0x759baca0, 0x663934d7, 0x52de9c4e, 0x417c0439,
146
  0xa6050ec4, 0xb5a796b3, 0x81403e2a, 0x92e2a65d,
147
  0xe88f6f18, 0xfb2df76f, 0xcfca5ff6, 0xdc68c781,
148
  0x7b5fdfff, 0x68fd4788, 0x5c1aef11, 0x4fb87766,
149
  0x35d5be23, 0x26772654, 0x12908ecd, 0x013216ba,
150
  0xe64b1c47, 0xf5e98430, 0xc10e2ca9, 0xd2acb4de,
151
  0xa8c17d9b, 0xbb63e5ec, 0x8f844d75, 0x9c26d502,
152
  0x449a2e7e, 0x5738b609, 0x63df1e90, 0x707d86e7,
153
  0x0a104fa2, 0x19b2d7d5, 0x2d557f4c, 0x3ef7e73b,
154
  0xd98eedc6, 0xca2c75b1, 0xfecbdd28, 0xed69455f,
155
  0x97048c1a, 0x84a6146d, 0xb041bcf4, 0xa3e32483
156
};
157
static const uint32_t table2_[256] = {
158
  0x00000000, 0xa541927e, 0x4f6f520d, 0xea2ec073,
159
  0x9edea41a, 0x3b9f3664, 0xd1b1f617, 0x74f06469,
160
  0x38513ec5, 0x9d10acbb, 0x773e6cc8, 0xd27ffeb6,
161
  0xa68f9adf, 0x03ce08a1, 0xe9e0c8d2, 0x4ca15aac,
162
  0x70a27d8a, 0xd5e3eff4, 0x3fcd2f87, 0x9a8cbdf9,
163
  0xee7cd990, 0x4b3d4bee, 0xa1138b9d, 0x045219e3,
164
  0x48f3434f, 0xedb2d131, 0x079c1142, 0xa2dd833c,
165
  0xd62de755, 0x736c752b, 0x9942b558, 0x3c032726,
166
  0xe144fb14, 0x4405696a, 0xae2ba919, 0x0b6a3b67,
167
  0x7f9a5f0e, 0xdadbcd70, 0x30f50d03, 0x95b49f7d,
168
  0xd915c5d1, 0x7c5457af, 0x967a97dc, 0x333b05a2,
169
  0x47cb61cb, 0xe28af3b5, 0x08a433c6, 0xade5a1b8,
170
  0x91e6869e, 0x34a714e0, 0xde89d493, 0x7bc846ed,
171
  0x0f382284, 0xaa79b0fa, 0x40577089, 0xe516e2f7,
172
  0xa9b7b85b, 0x0cf62a25, 0xe6d8ea56, 0x43997828,
173
  0x37691c41, 0x92288e3f, 0x78064e4c, 0xdd47dc32,
174
  0xc76580d9, 0x622412a7, 0x880ad2d4, 0x2d4b40aa,
175
  0x59bb24c3, 0xfcfab6bd, 0x16d476ce, 0xb395e4b0,
176
  0xff34be1c, 0x5a752c62, 0xb05bec11, 0x151a7e6f,
177
  0x61ea1a06, 0xc4ab8878, 0x2e85480b, 0x8bc4da75,
178
  0xb7c7fd53, 0x12866f2d, 0xf8a8af5e, 0x5de93d20,
179
  0x29195949, 0x8c58cb37, 0x66760b44, 0xc337993a,
180
  0x8f96c396, 0x2ad751e8, 0xc0f9919b, 0x65b803e5,
181
  0x1148678c, 0xb409f5f2, 0x5e273581, 0xfb66a7ff,
182
  0x26217bcd, 0x8360e9b3, 0x694e29c0, 0xcc0fbbbe,
183
  0xb8ffdfd7, 0x1dbe4da9, 0xf7908dda, 0x52d11fa4,
184
  0x1e704508, 0xbb31d776, 0x511f1705, 0xf45e857b,
185
  0x80aee112, 0x25ef736c, 0xcfc1b31f, 0x6a802161,
186
  0x56830647, 0xf3c29439, 0x19ec544a, 0xbcadc634,
187
  0xc85da25d, 0x6d1c3023, 0x8732f050, 0x2273622e,
188
  0x6ed23882, 0xcb93aafc, 0x21bd6a8f, 0x84fcf8f1,
189
  0xf00c9c98, 0x554d0ee6, 0xbf63ce95, 0x1a225ceb,
190
  0x8b277743, 0x2e66e53d, 0xc448254e, 0x6109b730,
191
  0x15f9d359, 0xb0b84127, 0x5a968154, 0xffd7132a,
192
  0xb3764986, 0x1637dbf8, 0xfc191b8b, 0x595889f5,
193
  0x2da8ed9c, 0x88e97fe2, 0x62c7bf91, 0xc7862def,
194
  0xfb850ac9, 0x5ec498b7, 0xb4ea58c4, 0x11abcaba,
195
  0x655baed3, 0xc01a3cad, 0x2a34fcde, 0x8f756ea0,
196
  0xc3d4340c, 0x6695a672, 0x8cbb6601, 0x29faf47f,
197
  0x5d0a9016, 0xf84b0268, 0x1265c21b, 0xb7245065,
198
  0x6a638c57, 0xcf221e29, 0x250cde5a, 0x804d4c24,
199
  0xf4bd284d, 0x51fcba33, 0xbbd27a40, 0x1e93e83e,
200
  0x5232b292, 0xf77320ec, 0x1d5de09f, 0xb81c72e1,
201
  0xccec1688, 0x69ad84f6, 0x83834485, 0x26c2d6fb,
202
  0x1ac1f1dd, 0xbf8063a3, 0x55aea3d0, 0xf0ef31ae,
203
  0x841f55c7, 0x215ec7b9, 0xcb7007ca, 0x6e3195b4,
204
  0x2290cf18, 0x87d15d66, 0x6dff9d15, 0xc8be0f6b,
205
  0xbc4e6b02, 0x190ff97c, 0xf321390f, 0x5660ab71,
206
  0x4c42f79a, 0xe90365e4, 0x032da597, 0xa66c37e9,
207
  0xd29c5380, 0x77ddc1fe, 0x9df3018d, 0x38b293f3,
208
  0x7413c95f, 0xd1525b21, 0x3b7c9b52, 0x9e3d092c,
209
  0xeacd6d45, 0x4f8cff3b, 0xa5a23f48, 0x00e3ad36,
210
  0x3ce08a10, 0x99a1186e, 0x738fd81d, 0xd6ce4a63,
211
  0xa23e2e0a, 0x077fbc74, 0xed517c07, 0x4810ee79,
212
  0x04b1b4d5, 0xa1f026ab, 0x4bdee6d8, 0xee9f74a6,
213
  0x9a6f10cf, 0x3f2e82b1, 0xd50042c2, 0x7041d0bc,
214
  0xad060c8e, 0x08479ef0, 0xe2695e83, 0x4728ccfd,
215
  0x33d8a894, 0x96993aea, 0x7cb7fa99, 0xd9f668e7,
216
  0x9557324b, 0x3016a035, 0xda386046, 0x7f79f238,
217
  0x0b899651, 0xaec8042f, 0x44e6c45c, 0xe1a75622,
218
  0xdda47104, 0x78e5e37a, 0x92cb2309, 0x378ab177,
219
  0x437ad51e, 0xe63b4760, 0x0c158713, 0xa954156d,
220
  0xe5f54fc1, 0x40b4ddbf, 0xaa9a1dcc, 0x0fdb8fb2,
221
  0x7b2bebdb, 0xde6a79a5, 0x3444b9d6, 0x91052ba8
222
};
223
static const uint32_t table3_[256] = {
224
  0x00000000, 0xdd45aab8, 0xbf672381, 0x62228939,
225
  0x7b2231f3, 0xa6679b4b, 0xc4451272, 0x1900b8ca,
226
  0xf64463e6, 0x2b01c95e, 0x49234067, 0x9466eadf,
227
  0x8d665215, 0x5023f8ad, 0x32017194, 0xef44db2c,
228
  0xe964b13d, 0x34211b85, 0x560392bc, 0x8b463804,
229
  0x924680ce, 0x4f032a76, 0x2d21a34f, 0xf06409f7,
230
  0x1f20d2db, 0xc2657863, 0xa047f15a, 0x7d025be2,
231
  0x6402e328, 0xb9474990, 0xdb65c0a9, 0x06206a11,
232
  0xd725148b, 0x0a60be33, 0x6842370a, 0xb5079db2,
233
  0xac072578, 0x71428fc0, 0x136006f9, 0xce25ac41,
234
  0x2161776d, 0xfc24ddd5, 0x9e0654ec, 0x4343fe54,
235
  0x5a43469e, 0x8706ec26, 0xe524651f, 0x3861cfa7,
236
  0x3e41a5b6, 0xe3040f0e, 0x81268637, 0x5c632c8f,
237
  0x45639445, 0x98263efd, 0xfa04b7c4, 0x27411d7c,
238
  0xc805c650, 0x15406ce8, 0x7762e5d1, 0xaa274f69,
239
  0xb327f7a3, 0x6e625d1b, 0x0c40d422, 0xd1057e9a,
240
  0xaba65fe7, 0x76e3f55f, 0x14c17c66, 0xc984d6de,
241
  0xd0846e14, 0x0dc1c4ac, 0x6fe34d95, 0xb2a6e72d,
242
  0x5de23c01, 0x80a796b9, 0xe2851f80, 0x3fc0b538,
243
  0x26c00df2, 0xfb85a74a, 0x99a72e73, 0x44e284cb,
244
  0x42c2eeda, 0x9f874462, 0xfda5cd5b, 0x20e067e3,
245
  0x39e0df29, 0xe4a57591, 0x8687fca8, 0x5bc25610,
246
  0xb4868d3c, 0x69c32784, 0x0be1aebd, 0xd6a40405,
247
  0xcfa4bccf, 0x12e11677, 0x70c39f4e, 0xad8635f6,
248
  0x7c834b6c, 0xa1c6e1d4, 0xc3e468ed, 0x1ea1c255,
249
  0x07a17a9f, 0xdae4d027, 0xb8c6591e, 0x6583f3a6,
250
  0x8ac7288a, 0x57828232, 0x35a00b0b, 0xe8e5a1b3,
251
  0xf1e51979, 0x2ca0b3c1, 0x4e823af8, 0x93c79040,
252
  0x95e7fa51, 0x48a250e9, 0x2a80d9d0, 0xf7c57368,
253
  0xeec5cba2, 0x3380611a, 0x51a2e823, 0x8ce7429b,
254
  0x63a399b7, 0xbee6330f, 0xdcc4ba36, 0x0181108e,
255
  0x1881a844, 0xc5c402fc, 0xa7e68bc5, 0x7aa3217d,
256
  0x52a0c93f, 0x8fe56387, 0xedc7eabe, 0x30824006,
257
  0x2982f8cc, 0xf4c75274, 0x96e5db4d, 0x4ba071f5,
258
  0xa4e4aad9, 0x79a10061, 0x1b838958, 0xc6c623e0,
259
  0xdfc69b2a, 0x02833192, 0x60a1b8ab, 0xbde41213,
260
  0xbbc47802, 0x6681d2ba, 0x04a35b83, 0xd9e6f13b,
261
  0xc0e649f1, 0x1da3e349, 0x7f816a70, 0xa2c4c0c8,
262
  0x4d801be4, 0x90c5b15c, 0xf2e73865, 0x2fa292dd,
263
  0x36a22a17, 0xebe780af, 0x89c50996, 0x5480a32e,
264
  0x8585ddb4, 0x58c0770c, 0x3ae2fe35, 0xe7a7548d,
265
  0xfea7ec47, 0x23e246ff, 0x41c0cfc6, 0x9c85657e,
266
  0x73c1be52, 0xae8414ea, 0xcca69dd3, 0x11e3376b,
267
  0x08e38fa1, 0xd5a62519, 0xb784ac20, 0x6ac10698,
268
  0x6ce16c89, 0xb1a4c631, 0xd3864f08, 0x0ec3e5b0,
269
  0x17c35d7a, 0xca86f7c2, 0xa8a47efb, 0x75e1d443,
270
  0x9aa50f6f, 0x47e0a5d7, 0x25c22cee, 0xf8878656,
271
  0xe1873e9c, 0x3cc29424, 0x5ee01d1d, 0x83a5b7a5,
272
  0xf90696d8, 0x24433c60, 0x4661b559, 0x9b241fe1,
273
  0x8224a72b, 0x5f610d93, 0x3d4384aa, 0xe0062e12,
274
  0x0f42f53e, 0xd2075f86, 0xb025d6bf, 0x6d607c07,
275
  0x7460c4cd, 0xa9256e75, 0xcb07e74c, 0x16424df4,
276
  0x106227e5, 0xcd278d5d, 0xaf050464, 0x7240aedc,
277
  0x6b401616, 0xb605bcae, 0xd4273597, 0x09629f2f,
278
  0xe6264403, 0x3b63eebb, 0x59416782, 0x8404cd3a,
279
  0x9d0475f0, 0x4041df48, 0x22635671, 0xff26fcc9,
280
  0x2e238253, 0xf36628eb, 0x9144a1d2, 0x4c010b6a,
281
  0x5501b3a0, 0x88441918, 0xea669021, 0x37233a99,
282
  0xd867e1b5, 0x05224b0d, 0x6700c234, 0xba45688c,
283
  0xa345d046, 0x7e007afe, 0x1c22f3c7, 0xc167597f,
284
  0xc747336e, 0x1a0299d6, 0x782010ef, 0xa565ba57,
285
  0xbc65029d, 0x6120a825, 0x0302211c, 0xde478ba4,
286
  0x31035088, 0xec46fa30, 0x8e647309, 0x5321d9b1,
287
  0x4a21617b, 0x9764cbc3, 0xf54642fa, 0x2803e842
288
};
289
290
// Lower-level versions of Get... that read directly from a character buffer
291
// without any bounds checking.
292
293
7.71k
static inline uint32_t DecodeFixed32(const char* ptr) {
294
7.71k
#if defined(ARCH_CPU_LITTLE_ENDIAN) && ARCH_CPU_LITTLE_ENDIAN
295
    // Load the raw bytes
296
7.71k
    uint32_t result;
297
7.71k
    memcpy(&result, ptr, sizeof(result));  // gcc optimizes this to a plain load
298
7.71k
    return result;
299
#else
300
    return ((static_cast<uint32_t>(static_cast<unsigned char>(ptr[0])))
301
        | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[1])) << 8)
302
        | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[2])) << 16)
303
        | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[3])) << 24));
304
#endif
305
7.71k
}
306
307
0
inline uint64_t DecodeFixed64(const char* ptr) {
308
0
#if defined(ARCH_CPU_LITTLE_ENDIAN) && ARCH_CPU_LITTLE_ENDIAN
309
0
    // Load the raw bytes
310
0
    uint64_t result;
311
0
    memcpy(&result, ptr, sizeof(result));  // gcc optimizes this to a plain load
312
0
    return result;
313
0
#else
314
0
    uint64_t lo = DecodeFixed32(ptr);
315
0
    uint64_t hi = DecodeFixed32(ptr + 4);
316
0
    return (hi << 32) | lo;
317
0
#endif
318
0
}
319
320
// Used to fetch a naturally-aligned 32-bit word in little endian byte-order
321
7.71k
static inline uint32_t LE_LOAD32(const uint8_t *p) {
322
7.71k
  return DecodeFixed32(reinterpret_cast<const char*>(p));
323
7.71k
}
324
325
#ifdef __SSE4_2__
326
#ifdef __LP64__
327
static inline uint64_t LE_LOAD64(const uint8_t *p) {
328
  return DecodeFixed64(reinterpret_cast<const char*>(p));
329
}
330
#endif
331
#endif
332
333
3.85k
static inline void Slow_CRC32(uint64_t* l, uint8_t const **p) {
334
3.85k
  uint32_t c = static_cast<uint32_t>(*l ^ LE_LOAD32(*p));
335
3.85k
  *p += 4;
336
3.85k
  *l = table3_[c & 0xff] ^
337
3.85k
  table2_[(c >> 8) & 0xff] ^
338
3.85k
  table1_[(c >> 16) & 0xff] ^
339
3.85k
  table0_[c >> 24];
340
  // DO it twice.
341
3.85k
  c = static_cast<uint32_t>(*l ^ LE_LOAD32(*p));
342
3.85k
  *p += 4;
343
3.85k
  *l = table3_[c & 0xff] ^
344
3.85k
  table2_[(c >> 8) & 0xff] ^
345
3.85k
  table1_[(c >> 16) & 0xff] ^
346
3.85k
  table0_[c >> 24];
347
3.85k
}
348
349
0
static inline void Fast_CRC32(uint64_t* l, uint8_t const **p) {
350
0
#ifdef __SSE4_2__
351
0
#ifdef __LP64__
352
0
  *l = _mm_crc32_u64(*l, LE_LOAD64(*p));
353
0
  *p += 8;
354
0
#else
355
0
  *l = _mm_crc32_u32(static_cast<unsigned int>(*l), LE_LOAD32(*p));
356
0
  *p += 4;
357
0
  *l = _mm_crc32_u32(static_cast<unsigned int>(*l), LE_LOAD32(*p));
358
0
  *p += 4;
359
0
#endif
360
0
#else
361
0
  Slow_CRC32(l, p);
362
0
#endif
363
0
}
364
365
class FastCRC32Functor {
366
public:
367
0
  inline void operator()(uint64_t* l, uint8_t const **p) const {
368
0
    return Fast_CRC32(l , p);
369
0
  }
370
};
371
372
class SlowCRC32Functor {
373
public:
374
3.85k
  inline void operator()(uint64_t* l, uint8_t const **p) const {
375
3.85k
    return Slow_CRC32(l , p);
376
3.85k
  }
377
};
378
379
template<typename CRC32Functor>
380
186
uint32_t ExtendImpl(uint32_t crc, const char* buf, size_t size) {
381
186
  CRC32Functor CRC32;
382
383
186
  const uint8_t *p = reinterpret_cast<const uint8_t *>(buf);
384
186
  const uint8_t *e = p + size;
385
186
  uint64_t l = crc ^ 0xffffffffu;
386
387
// Align n to (1 << m) byte boundary
388
186
#define ALIGN(n, m)     ((n + ((1 << m) - 1)) & ~((1 << m) - 1))
389
390
333
#define STEP1 do {                              \
391
333
    int c = (l & 0xff) ^ *p++;                  \
392
333
    l = table0_[c] ^ (l >> 8);                  \
393
333
} while (0)
394
395
396
  // Point x at first 16-byte aligned byte in string.  This might be
397
  // just past the end of the string.
398
186
  const uintptr_t pval = reinterpret_cast<uintptr_t>(p);
399
186
  const uint8_t* x = reinterpret_cast<const uint8_t*>(ALIGN(pval, 4));
400
186
  if (x <= e) {
401
    // Process bytes until finished or p is 16-byte aligned
402
186
    while (p != x) {
403
0
      STEP1;
404
0
    }
405
186
  }
406
  // Process bytes 16 at a time
407
2.04k
  while ((e-p) >= 16) {
408
1.86k
    CRC32(&l, &p);
409
1.86k
    CRC32(&l, &p);
410
1.86k
  }
411
  // Process bytes 8 at a time
412
319
  while ((e-p) >= 8) {
413
133
    CRC32(&l, &p);
414
133
  }
415
  // Process the last few bytes
416
519
  while (p != e) {
417
333
    STEP1;
418
333
  }
419
186
#undef STEP1
420
186
#undef ALIGN
421
186
  return static_cast<uint32_t>(l ^ 0xffffffffu);
422
186
}
423
424
#if defined(__riscv) && (__riscv_xlen == 64) && defined(__riscv_zbc)
425
#include <stdio.h>
426
427
// RISC-V Zbc carry-less multiplication inline helpers
428
static inline uint64_t rv_clmul(uint64_t a, uint64_t b) {
429
  uint64_t result;
430
  __asm__ volatile ("clmul %0, %1, %2" : "=r"(result) : "r"(a), "r"(b));
431
  return result;
432
}
433
434
static inline uint64_t rv_clmulh(uint64_t a, uint64_t b) {
435
  uint64_t result;
436
  __asm__ volatile ("clmulh %0, %1, %2" : "=r"(result) : "r"(a), "r"(b));
437
  return result;
438
}
439
440
// Bitwise CRC32C fallback for small chunks
441
static inline uint32_t rv_crc32c_bitwise(uint32_t crc, const uint8_t* buf,
442
                                         size_t len) {
443
  uint32_t c = crc;
444
  for (size_t i = 0; i < len; ++i) {
445
    c ^= buf[i];
446
    for (int k = 0; k < 8; ++k) {
447
      c = (c >> 1) ^ ((c & 1) ? 0x82F63B78U : 0);
448
    }
449
  }
450
  return c;
451
}
452
453
// Fold a 128-bit CRC state (lo:hi) with fold constants and XOR in new data
454
static inline void rv_fold_pair_xor_data(uint64_t* lo, uint64_t* hi,
455
                                         uint64_t k0, uint64_t k1,
456
                                         uint64_t d0, uint64_t d1) {
457
  uint64_t l = rv_clmul(*lo, k0) ^ rv_clmul(*hi, k1);
458
  uint64_t h = rv_clmulh(*lo, k0) ^ rv_clmulh(*hi, k1);
459
  *lo = l ^ d0;
460
  *hi = h ^ d1;
461
}
462
463
// Fold a 128-bit CRC state with fold constants and XOR in another state
464
static inline void rv_fold_pair_xor_state(uint64_t* lo, uint64_t* hi,
465
                                          uint64_t k0, uint64_t k1,
466
                                          uint64_t s0, uint64_t s1) {
467
  uint64_t l = rv_clmul(*lo, k0) ^ rv_clmul(*hi, k1);
468
  uint64_t h = rv_clmulh(*lo, k0) ^ rv_clmulh(*hi, k1);
469
  *lo = l ^ s0;
470
  *hi = h ^ s1;
471
}
472
473
// Folding constants for CRC32C (Castagnoli polynomial 0x1EDC6F41)
474
// x^(64*i+64) mod P(x) for i=1..4, in bit-reflected form
475
static const uint64_t crc32c_fold_const[4] __attribute__((aligned(16))) = {
476
  0x00000000740eef02ULL,  // k1: fold 512->256
477
  0x000000009e4addf8ULL,  // k2: fold 512->256
478
  0x00000000f20c0dfeULL,  // k3: fold 256->128
479
  0x00000000493c7d27ULL   // k4: fold 256->128
480
};
481
482
// Barrett reduction constants for CRC32C finalization
483
#define RV_CRC32C_CONST_0    0x00000000dd45aab8ULL  // x^64 mod P
484
#define RV_CRC32C_CONST_1    0x00000000493c7d27ULL  // x^96 mod P
485
#define RV_CRC32C_CONST_QUO  0x0000000dea713f1ULL   // floor(x^64 / P)
486
#define RV_CRC32C_CONST_POLY 0x0000000105ec76f1ULL  // P(x) true LE full
487
#define RV_CRC32_MASK32      0x00000000FFFFFFFFULL
488
489
// Hardware-accelerated CRC32C using RISC-V Zbc carry-less multiplication.
490
// Processes data in 64-byte chunks with 128-bit folding, then Barrett reduces.
491
static uint32_t rv_crc32c_clmul(uint32_t crc, const char* buf, size_t len) {
492
  // Convert external CRC to internal register state
493
  crc ^= 0xFFFFFFFF;
494
495
  const uint8_t* p = reinterpret_cast<const uint8_t*>(buf);
496
  size_t n = len;
497
498
  // Small data: use bitwise fallback
499
  if (n < 64) {
500
    return rv_crc32c_bitwise(crc, p, n) ^ 0xFFFFFFFF;
501
  }
502
503
  // Align to 16-byte boundary
504
  uintptr_t mis = (uintptr_t)p & 0xF;
505
  if (mis) {
506
    size_t pre = 16 - mis;
507
    if (pre > n) pre = n;
508
    crc = rv_crc32c_bitwise(crc, p, pre);
509
    p += pre;
510
    n -= pre;
511
    if (n < 64) {
512
      return rv_crc32c_bitwise(crc, p, n) ^ 0xFFFFFFFF;
513
    }
514
  }
515
516
  // Load first 64 bytes and XOR CRC into the first 8 bytes
517
  uint64_t x0, x1, y0, y1, z0, z1, w0, w1;
518
  memcpy(&x0, p + 0, 8);
519
  memcpy(&x1, p + 8, 8);
520
  memcpy(&y0, p + 16, 8);
521
  memcpy(&y1, p + 24, 8);
522
  memcpy(&z0, p + 32, 8);
523
  memcpy(&z1, p + 40, 8);
524
  memcpy(&w0, p + 48, 8);
525
  memcpy(&w1, p + 56, 8);
526
527
  x0 ^= (uint64_t)crc;
528
  p += 64;
529
  n -= 64;
530
531
  const uint64_t k1 = crc32c_fold_const[0];
532
  const uint64_t k2 = crc32c_fold_const[1];
533
  const uint64_t k3 = crc32c_fold_const[2];
534
  const uint64_t k4 = crc32c_fold_const[3];
535
536
  // Main loop: fold 64 bytes per iteration using 128-bit folding
537
  while (n >= 64) {
538
    uint64_t d0, d1;
539
    memcpy(&d0, p + 0, 8);
540
    memcpy(&d1, p + 8, 8);
541
    rv_fold_pair_xor_data(&x0, &x1, k1, k2, d0, d1);
542
    memcpy(&d0, p + 16, 8);
543
    memcpy(&d1, p + 24, 8);
544
    rv_fold_pair_xor_data(&y0, &y1, k1, k2, d0, d1);
545
    memcpy(&d0, p + 32, 8);
546
    memcpy(&d1, p + 40, 8);
547
    rv_fold_pair_xor_data(&z0, &z1, k1, k2, d0, d1);
548
    memcpy(&d0, p + 48, 8);
549
    memcpy(&d1, p + 56, 8);
550
    rv_fold_pair_xor_data(&w0, &w1, k1, k2, d0, d1);
551
    p += 64;
552
    n -= 64;
553
  }
554
555
  // Reduce 4x128-bit to 1x128-bit
556
  rv_fold_pair_xor_state(&x0, &x1, k3, k4, y0, y1);
557
  rv_fold_pair_xor_state(&x0, &x1, k3, k4, z0, z1);
558
  rv_fold_pair_xor_state(&x0, &x1, k3, k4, w0, w1);
559
560
  // Barrett reduction: 128-bit -> 32-bit CRC
561
  uint64_t t4 = rv_clmul(x0, RV_CRC32C_CONST_1);
562
  uint64_t t3 = rv_clmulh(x0, RV_CRC32C_CONST_1);
563
  uint64_t t1 = x1 ^ t4;
564
  t4 = t1 & RV_CRC32_MASK32;
565
  t1 >>= 32;
566
  uint64_t t0 = rv_clmul(t4, RV_CRC32C_CONST_0);
567
  t3 = (t3 << 32) ^ t1 ^ t0;
568
569
  t4 = t3 & RV_CRC32_MASK32;
570
  t4 = rv_clmul(t4, RV_CRC32C_CONST_QUO);
571
  t4 &= RV_CRC32_MASK32;
572
  t4 = rv_clmul(t4, RV_CRC32C_CONST_POLY);
573
  t4 ^= t3;
574
575
  uint32_t c = (uint32_t)((t4 >> 32) & RV_CRC32_MASK32);
576
  // Handle remaining bytes
577
  if (n) {
578
    c = rv_crc32c_bitwise(c, p, n);
579
  }
580
  // Convert internal register state to external CRC
581
  return c ^ 0xFFFFFFFF;
582
}
583
584
// Runtime detection: check if RISC-V CPU supports Zbc extension
585
static bool isZbc() {
586
  static const bool zbc_supported = []() {
587
    FILE* f = fopen("/proc/cpuinfo", "r");
588
    if (!f) return false;
589
    bool supported = false;
590
    char line[1024];
591
    while (fgets(line, sizeof(line), f)) {
592
      if (strstr(line, "isa") || strstr(line, "hart isa")) {
593
        char* colon = strchr(line, ':');
594
        if (colon) {
595
          if (strstr(colon, "_zbc") || strstr(colon, "zbc")) {
596
            supported = true;
597
            break;
598
          }
599
        }
600
      }
601
    }
602
    fclose(f);
603
    return supported;
604
  }();
605
  return zbc_supported;
606
}
607
}
608
#endif  // __riscv && __riscv_xlen == 64
609
610
// Detect if SSE4.2 or not.
611
#ifdef __SSE4_2__
612
static bool isSSE42() {
613
#if defined(__GNUC__) && defined(__x86_64__) && !defined(IOS_CROSS_COMPILE)
614
  uint32_t c_;
615
  uint32_t d_;
616
  __asm__("cpuid" : "=c"(c_), "=d"(d_) : "a"(1) : "ebx");
617
  return c_ & (1U << 20);  // copied from CpuId.h in Folly.
618
#else
619
  return false;
620
#endif
621
}
622
#endif
623
624
typedef uint32_t (*Function)(uint32_t, const char*, size_t);
625
626
1
static inline Function Choose_Extend() {
627
#ifdef __SSE4_2__
628
  if (isSSE42()) {
629
    return (Function)ExtendImpl<FastCRC32Functor>;
630
  }
631
#endif
632
#if defined(__riscv) && (__riscv_xlen == 64) && defined(__riscv_zbc)
633
  if (isZbc()) {
634
    return (Function)rv_crc32c_clmul;
635
  }
636
#endif
637
1
  return (Function)ExtendImpl<SlowCRC32Functor>;
638
1
}
639
640
0
bool IsFastCrc32Supported() {
641
#ifdef __SSE4_2__
642
  if (isSSE42()) return true;
643
#endif
644
#if defined(__riscv) && (__riscv_xlen == 64) && defined(__riscv_zbc)
645
  if (isZbc()) return true;
646
#endif
647
0
  return false;
648
0
}
649
650
186
uint32_t Extend(uint32_t crc, const char* buf, size_t size) {
651
186
  static Function ChosenExtend = Choose_Extend();
652
186
  return ChosenExtend(crc, buf, size);
653
186
}
654
655
}  // namespace crc32c
656
}  // namespace butil