snappy 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -31,21 +31,23 @@
31
31
  #ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
32
32
  #define THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
33
33
 
34
- #ifdef HAVE_CONFIG_H
34
+ #if HAVE_CONFIG_H
35
35
  #include "config.h"
36
36
  #endif
37
37
 
38
- #include <string>
38
+ #include <stdint.h>
39
39
 
40
- #include <assert.h>
41
- #include <stdlib.h>
42
- #include <string.h>
40
+ #include <cassert>
41
+ #include <cstdlib>
42
+ #include <cstring>
43
+ #include <limits>
44
+ #include <string>
43
45
 
44
- #ifdef HAVE_SYS_MMAN_H
46
+ #if HAVE_SYS_MMAN_H
45
47
  #include <sys/mman.h>
46
48
  #endif
47
49
 
48
- #ifdef HAVE_UNISTD_H
50
+ #if HAVE_UNISTD_H
49
51
  #include <unistd.h>
50
52
  #endif
51
53
 
@@ -67,19 +69,11 @@
67
69
 
68
70
  #include "snappy-stubs-public.h"
69
71
 
70
- #if defined(__x86_64__)
71
-
72
- // Enable 64-bit optimized versions of some routines.
73
- #define ARCH_K8 1
74
-
75
- #elif defined(__ppc64__)
76
-
72
+ // Used to enable 64-bit optimized versions of some routines.
73
+ #if defined(__PPC64__) || defined(__powerpc64__)
77
74
  #define ARCH_PPC 1
78
-
79
- #elif defined(__aarch64__)
80
-
75
+ #elif defined(__aarch64__) || defined(_M_ARM64)
81
76
  #define ARCH_ARM 1
82
-
83
77
  #endif
84
78
 
85
79
  // Needed by OS X, among others.
@@ -93,223 +87,77 @@
93
87
  #ifdef ARRAYSIZE
94
88
  #undef ARRAYSIZE
95
89
  #endif
96
- #define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
90
+ #define ARRAYSIZE(a) int{sizeof(a) / sizeof(*(a))}
97
91
 
98
92
  // Static prediction hints.
99
- #ifdef HAVE_BUILTIN_EXPECT
93
+ #if HAVE_BUILTIN_EXPECT
100
94
  #define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
101
95
  #define SNAPPY_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
102
96
  #else
103
97
  #define SNAPPY_PREDICT_FALSE(x) x
104
98
  #define SNAPPY_PREDICT_TRUE(x) x
105
- #endif
106
-
107
- // This is only used for recomputing the tag byte table used during
108
- // decompression; for simplicity we just remove it from the open-source
109
- // version (anyone who wants to regenerate it can just do the call
110
- // themselves within main()).
111
- #define DEFINE_bool(flag_name, default_value, description) \
112
- bool FLAGS_ ## flag_name = default_value
113
- #define DECLARE_bool(flag_name) \
114
- extern bool FLAGS_ ## flag_name
115
-
116
- namespace snappy {
117
-
118
- static const uint32 kuint32max = static_cast<uint32>(0xFFFFFFFF);
119
- static const int64 kint64max = static_cast<int64>(0x7FFFFFFFFFFFFFFFLL);
99
+ #endif // HAVE_BUILTIN_EXPECT
120
100
 
121
- // Potentially unaligned loads and stores.
122
-
123
- // x86, PowerPC, and ARM64 can simply do these loads and stores native.
124
-
125
- #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \
126
- defined(__aarch64__)
127
-
128
- #define UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
129
- #define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
130
- #define UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
131
-
132
- #define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
133
- #define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
134
- #define UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
135
-
136
- // ARMv7 and newer support native unaligned accesses, but only of 16-bit
137
- // and 32-bit values (not 64-bit); older versions either raise a fatal signal,
138
- // do an unaligned read and rotate the words around a bit, or do the reads very
139
- // slowly (trip through kernel mode). There's no simple #define that says just
140
- // “ARMv7 or higher”, so we have to filter away all ARMv5 and ARMv6
141
- // sub-architectures.
142
- //
143
- // This is a mess, but there's not much we can do about it.
144
- //
145
- // To further complicate matters, only LDR instructions (single reads) are
146
- // allowed to be unaligned, not LDRD (two reads) or LDM (many reads). Unless we
147
- // explicitly tell the compiler that these accesses can be unaligned, it can and
148
- // will combine accesses. On armcc, the way to signal this is done by accessing
149
- // through the type (uint32 __packed *), but GCC has no such attribute
150
- // (it ignores __attribute__((packed)) on individual variables). However,
151
- // we can tell it that a _struct_ is unaligned, which has the same effect,
152
- // so we do that.
153
-
154
- #elif defined(__arm__) && \
155
- !defined(__ARM_ARCH_4__) && \
156
- !defined(__ARM_ARCH_4T__) && \
157
- !defined(__ARM_ARCH_5__) && \
158
- !defined(__ARM_ARCH_5T__) && \
159
- !defined(__ARM_ARCH_5TE__) && \
160
- !defined(__ARM_ARCH_5TEJ__) && \
161
- !defined(__ARM_ARCH_6__) && \
162
- !defined(__ARM_ARCH_6J__) && \
163
- !defined(__ARM_ARCH_6K__) && \
164
- !defined(__ARM_ARCH_6Z__) && \
165
- !defined(__ARM_ARCH_6ZK__) && \
166
- !defined(__ARM_ARCH_6T2__)
167
-
168
- #if __GNUC__
169
- #define ATTRIBUTE_PACKED __attribute__((__packed__))
101
+ // Inlining hints.
102
+ #if HAVE_ATTRIBUTE_ALWAYS_INLINE
103
+ #define SNAPPY_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
170
104
  #else
171
- #define ATTRIBUTE_PACKED
172
- #endif
105
+ #define SNAPPY_ATTRIBUTE_ALWAYS_INLINE
106
+ #endif // HAVE_ATTRIBUTE_ALWAYS_INLINE
173
107
 
174
- namespace base {
175
- namespace internal {
176
-
177
- struct Unaligned16Struct {
178
- uint16 value;
179
- uint8 dummy; // To make the size non-power-of-two.
180
- } ATTRIBUTE_PACKED;
181
-
182
- struct Unaligned32Struct {
183
- uint32 value;
184
- uint8 dummy; // To make the size non-power-of-two.
185
- } ATTRIBUTE_PACKED;
186
-
187
- } // namespace internal
188
- } // namespace base
189
-
190
- #define UNALIGNED_LOAD16(_p) \
191
- ((reinterpret_cast<const ::snappy::base::internal::Unaligned16Struct *>(_p))->value)
192
- #define UNALIGNED_LOAD32(_p) \
193
- ((reinterpret_cast<const ::snappy::base::internal::Unaligned32Struct *>(_p))->value)
194
-
195
- #define UNALIGNED_STORE16(_p, _val) \
196
- ((reinterpret_cast< ::snappy::base::internal::Unaligned16Struct *>(_p))->value = \
197
- (_val))
198
- #define UNALIGNED_STORE32(_p, _val) \
199
- ((reinterpret_cast< ::snappy::base::internal::Unaligned32Struct *>(_p))->value = \
200
- (_val))
201
-
202
- // TODO: NEON supports unaligned 64-bit loads and stores.
203
- // See if that would be more efficient on platforms supporting it,
204
- // at least for copies.
205
-
206
- inline uint64 UNALIGNED_LOAD64(const void *p) {
207
- uint64 t;
208
- memcpy(&t, p, sizeof t);
209
- return t;
210
- }
211
-
212
- inline void UNALIGNED_STORE64(void *p, uint64 v) {
213
- memcpy(p, &v, sizeof v);
214
- }
215
-
216
- #else
108
+ // Stubbed version of ABSL_FLAG.
109
+ //
110
+ // In the open source version, flags can only be changed at compile time.
111
+ #define SNAPPY_FLAG(flag_type, flag_name, default_value, help) \
112
+ flag_type FLAGS_ ## flag_name = default_value
217
113
 
218
- // These functions are provided for architectures that don't support
219
- // unaligned loads and stores.
114
+ namespace snappy {
220
115
 
221
- inline uint16 UNALIGNED_LOAD16(const void *p) {
222
- uint16 t;
223
- memcpy(&t, p, sizeof t);
224
- return t;
225
- }
116
+ // Stubbed version of absl::GetFlag().
117
+ template <typename T>
118
+ inline T GetFlag(T flag) { return flag; }
226
119
 
227
- inline uint32 UNALIGNED_LOAD32(const void *p) {
228
- uint32 t;
229
- memcpy(&t, p, sizeof t);
230
- return t;
231
- }
120
+ static const uint32_t kuint32max = std::numeric_limits<uint32_t>::max();
121
+ static const int64_t kint64max = std::numeric_limits<int64_t>::max();
232
122
 
233
- inline uint64 UNALIGNED_LOAD64(const void *p) {
234
- uint64 t;
235
- memcpy(&t, p, sizeof t);
236
- return t;
237
- }
123
+ // Potentially unaligned loads and stores.
238
124
 
239
- inline void UNALIGNED_STORE16(void *p, uint16 v) {
240
- memcpy(p, &v, sizeof v);
125
+ inline uint16_t UNALIGNED_LOAD16(const void *p) {
126
+ // Compiles to a single movzx/ldrh on clang/gcc/msvc.
127
+ uint16_t v;
128
+ std::memcpy(&v, p, sizeof(v));
129
+ return v;
241
130
  }
242
131
 
243
- inline void UNALIGNED_STORE32(void *p, uint32 v) {
244
- memcpy(p, &v, sizeof v);
132
+ inline uint32_t UNALIGNED_LOAD32(const void *p) {
133
+ // Compiles to a single mov/ldr on clang/gcc/msvc.
134
+ uint32_t v;
135
+ std::memcpy(&v, p, sizeof(v));
136
+ return v;
245
137
  }
246
138
 
247
- inline void UNALIGNED_STORE64(void *p, uint64 v) {
248
- memcpy(p, &v, sizeof v);
139
+ inline uint64_t UNALIGNED_LOAD64(const void *p) {
140
+ // Compiles to a single mov/ldr on clang/gcc/msvc.
141
+ uint64_t v;
142
+ std::memcpy(&v, p, sizeof(v));
143
+ return v;
249
144
  }
250
145
 
251
- #endif
252
-
253
- // The following guarantees declaration of the byte swap functions.
254
- #if defined(SNAPPY_IS_BIG_ENDIAN)
255
-
256
- #ifdef HAVE_SYS_BYTEORDER_H
257
- #include <sys/byteorder.h>
258
- #endif
259
-
260
- #ifdef HAVE_SYS_ENDIAN_H
261
- #include <sys/endian.h>
262
- #endif
263
-
264
- #ifdef _MSC_VER
265
- #include <stdlib.h>
266
- #define bswap_16(x) _byteswap_ushort(x)
267
- #define bswap_32(x) _byteswap_ulong(x)
268
- #define bswap_64(x) _byteswap_uint64(x)
269
-
270
- #elif defined(__APPLE__)
271
- // Mac OS X / Darwin features
272
- #include <libkern/OSByteOrder.h>
273
- #define bswap_16(x) OSSwapInt16(x)
274
- #define bswap_32(x) OSSwapInt32(x)
275
- #define bswap_64(x) OSSwapInt64(x)
276
-
277
- #elif defined(HAVE_BYTESWAP_H)
278
- #include <byteswap.h>
279
-
280
- #elif defined(bswap32)
281
- // FreeBSD defines bswap{16,32,64} in <sys/endian.h> (already #included).
282
- #define bswap_16(x) bswap16(x)
283
- #define bswap_32(x) bswap32(x)
284
- #define bswap_64(x) bswap64(x)
285
-
286
- #elif defined(BSWAP_64)
287
- // Solaris 10 defines BSWAP_{16,32,64} in <sys/byteorder.h> (already #included).
288
- #define bswap_16(x) BSWAP_16(x)
289
- #define bswap_32(x) BSWAP_32(x)
290
- #define bswap_64(x) BSWAP_64(x)
291
-
292
- #else
293
-
294
- inline uint16 bswap_16(uint16 x) {
295
- return (x << 8) | (x >> 8);
146
+ inline void UNALIGNED_STORE16(void *p, uint16_t v) {
147
+ // Compiles to a single mov/strh on clang/gcc/msvc.
148
+ std::memcpy(p, &v, sizeof(v));
296
149
  }
297
150
 
298
- inline uint32 bswap_32(uint32 x) {
299
- x = ((x & 0xff00ff00UL) >> 8) | ((x & 0x00ff00ffUL) << 8);
300
- return (x >> 16) | (x << 16);
151
+ inline void UNALIGNED_STORE32(void *p, uint32_t v) {
152
+ // Compiles to a single mov/str on clang/gcc/msvc.
153
+ std::memcpy(p, &v, sizeof(v));
301
154
  }
302
155
 
303
- inline uint64 bswap_64(uint64 x) {
304
- x = ((x & 0xff00ff00ff00ff00ULL) >> 8) | ((x & 0x00ff00ff00ff00ffULL) << 8);
305
- x = ((x & 0xffff0000ffff0000ULL) >> 16) | ((x & 0x0000ffff0000ffffULL) << 16);
306
- return (x >> 32) | (x << 32);
156
+ inline void UNALIGNED_STORE64(void *p, uint64_t v) {
157
+ // Compiles to a single mov/str on clang/gcc/msvc.
158
+ std::memcpy(p, &v, sizeof(v));
307
159
  }
308
160
 
309
- #endif
310
-
311
- #endif // defined(SNAPPY_IS_BIG_ENDIAN)
312
-
313
161
  // Convert to little-endian storage, opposite of network format.
314
162
  // Convert x from host to little endian: x = LittleEndian.FromHost(x);
315
163
  // convert x from little endian to host: x = LittleEndian.ToHost(x);
@@ -321,44 +169,110 @@ inline uint64 bswap_64(uint64 x) {
321
169
  // x = LittleEndian.Load16(p);
322
170
  class LittleEndian {
323
171
  public:
324
- // Conversion functions.
325
- #if defined(SNAPPY_IS_BIG_ENDIAN)
326
-
327
- static uint16 FromHost16(uint16 x) { return bswap_16(x); }
328
- static uint16 ToHost16(uint16 x) { return bswap_16(x); }
329
-
330
- static uint32 FromHost32(uint32 x) { return bswap_32(x); }
331
- static uint32 ToHost32(uint32 x) { return bswap_32(x); }
332
-
333
- static bool IsLittleEndian() { return false; }
334
-
335
- #else // !defined(SNAPPY_IS_BIG_ENDIAN)
336
-
337
- static uint16 FromHost16(uint16 x) { return x; }
338
- static uint16 ToHost16(uint16 x) { return x; }
339
-
340
- static uint32 FromHost32(uint32 x) { return x; }
341
- static uint32 ToHost32(uint32 x) { return x; }
172
+ // Functions to do unaligned loads and stores in little-endian order.
173
+ static inline uint16_t Load16(const void *ptr) {
174
+ // Compiles to a single mov/str on recent clang and gcc.
175
+ #if SNAPPY_IS_BIG_ENDIAN
176
+ const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr);
177
+ return (static_cast<uint16_t>(buffer[0])) |
178
+ (static_cast<uint16_t>(buffer[1]) << 8);
179
+ #else
180
+ // memcpy() turns into a single instruction early in the optimization
181
+ // pipeline (relatively to a series of byte accesses). So, using memcpy
182
+ // instead of byte accesses may lead to better decisions in more stages of
183
+ // the optimization pipeline.
184
+ uint16_t value;
185
+ std::memcpy(&value, ptr, 2);
186
+ return value;
187
+ #endif
188
+ }
342
189
 
343
- static bool IsLittleEndian() { return true; }
190
+ static inline uint32_t Load32(const void *ptr) {
191
+ // Compiles to a single mov/str on recent clang and gcc.
192
+ #if SNAPPY_IS_BIG_ENDIAN
193
+ const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr);
194
+ return (static_cast<uint32_t>(buffer[0])) |
195
+ (static_cast<uint32_t>(buffer[1]) << 8) |
196
+ (static_cast<uint32_t>(buffer[2]) << 16) |
197
+ (static_cast<uint32_t>(buffer[3]) << 24);
198
+ #else
199
+ // See Load16() for the rationale of using memcpy().
200
+ uint32_t value;
201
+ std::memcpy(&value, ptr, 4);
202
+ return value;
203
+ #endif
204
+ }
344
205
 
345
- #endif // !defined(SNAPPY_IS_BIG_ENDIAN)
206
+ static inline uint64_t Load64(const void *ptr) {
207
+ // Compiles to a single mov/str on recent clang and gcc.
208
+ #if SNAPPY_IS_BIG_ENDIAN
209
+ const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr);
210
+ return (static_cast<uint64_t>(buffer[0])) |
211
+ (static_cast<uint64_t>(buffer[1]) << 8) |
212
+ (static_cast<uint64_t>(buffer[2]) << 16) |
213
+ (static_cast<uint64_t>(buffer[3]) << 24) |
214
+ (static_cast<uint64_t>(buffer[4]) << 32) |
215
+ (static_cast<uint64_t>(buffer[5]) << 40) |
216
+ (static_cast<uint64_t>(buffer[6]) << 48) |
217
+ (static_cast<uint64_t>(buffer[7]) << 56);
218
+ #else
219
+ // See Load16() for the rationale of using memcpy().
220
+ uint64_t value;
221
+ std::memcpy(&value, ptr, 8);
222
+ return value;
223
+ #endif
224
+ }
346
225
 
347
- // Functions to do unaligned loads and stores in little-endian order.
348
- static uint16 Load16(const void *p) {
349
- return ToHost16(UNALIGNED_LOAD16(p));
226
+ static inline void Store16(void *dst, uint16_t value) {
227
+ // Compiles to a single mov/str on recent clang and gcc.
228
+ #if SNAPPY_IS_BIG_ENDIAN
229
+ uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst);
230
+ buffer[0] = static_cast<uint8_t>(value);
231
+ buffer[1] = static_cast<uint8_t>(value >> 8);
232
+ #else
233
+ // See Load16() for the rationale of using memcpy().
234
+ std::memcpy(dst, &value, 2);
235
+ #endif
350
236
  }
351
237
 
352
- static void Store16(void *p, uint16 v) {
353
- UNALIGNED_STORE16(p, FromHost16(v));
238
+ static void Store32(void *dst, uint32_t value) {
239
+ // Compiles to a single mov/str on recent clang and gcc.
240
+ #if SNAPPY_IS_BIG_ENDIAN
241
+ uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst);
242
+ buffer[0] = static_cast<uint8_t>(value);
243
+ buffer[1] = static_cast<uint8_t>(value >> 8);
244
+ buffer[2] = static_cast<uint8_t>(value >> 16);
245
+ buffer[3] = static_cast<uint8_t>(value >> 24);
246
+ #else
247
+ // See Load16() for the rationale of using memcpy().
248
+ std::memcpy(dst, &value, 4);
249
+ #endif
354
250
  }
355
251
 
356
- static uint32 Load32(const void *p) {
357
- return ToHost32(UNALIGNED_LOAD32(p));
252
+ static void Store64(void* dst, uint64_t value) {
253
+ // Compiles to a single mov/str on recent clang and gcc.
254
+ #if SNAPPY_IS_BIG_ENDIAN
255
+ uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst);
256
+ buffer[0] = static_cast<uint8_t>(value);
257
+ buffer[1] = static_cast<uint8_t>(value >> 8);
258
+ buffer[2] = static_cast<uint8_t>(value >> 16);
259
+ buffer[3] = static_cast<uint8_t>(value >> 24);
260
+ buffer[4] = static_cast<uint8_t>(value >> 32);
261
+ buffer[5] = static_cast<uint8_t>(value >> 40);
262
+ buffer[6] = static_cast<uint8_t>(value >> 48);
263
+ buffer[7] = static_cast<uint8_t>(value >> 56);
264
+ #else
265
+ // See Load16() for the rationale of using memcpy().
266
+ std::memcpy(dst, &value, 8);
267
+ #endif
358
268
  }
359
269
 
360
- static void Store32(void *p, uint32 v) {
361
- UNALIGNED_STORE32(p, FromHost32(v));
270
+ static inline constexpr bool IsLittleEndian() {
271
+ #if SNAPPY_IS_BIG_ENDIAN
272
+ return false;
273
+ #else
274
+ return true;
275
+ #endif // SNAPPY_IS_BIG_ENDIAN
362
276
  }
363
277
  };
364
278
 
@@ -366,19 +280,17 @@ class LittleEndian {
366
280
  class Bits {
367
281
  public:
368
282
  // Return floor(log2(n)) for positive integer n.
369
- static int Log2FloorNonZero(uint32 n);
283
+ static int Log2FloorNonZero(uint32_t n);
370
284
 
371
285
  // Return floor(log2(n)) for positive integer n. Returns -1 iff n == 0.
372
- static int Log2Floor(uint32 n);
286
+ static int Log2Floor(uint32_t n);
373
287
 
374
288
  // Return the first set least / most significant bit, 0-indexed. Returns an
375
289
  // undefined value if n == 0. FindLSBSetNonZero() is similar to ffs() except
376
290
  // that it's 0-indexed.
377
- static int FindLSBSetNonZero(uint32 n);
291
+ static int FindLSBSetNonZero(uint32_t n);
378
292
 
379
- #if defined(ARCH_K8) || defined(ARCH_PPC) || defined(ARCH_ARM)
380
- static int FindLSBSetNonZero64(uint64 n);
381
- #endif // defined(ARCH_K8) || defined(ARCH_PPC) || defined(ARCH_ARM)
293
+ static int FindLSBSetNonZero64(uint64_t n);
382
294
 
383
295
  private:
384
296
  // No copying
@@ -386,9 +298,9 @@ class Bits {
386
298
  void operator=(const Bits&);
387
299
  };
388
300
 
389
- #ifdef HAVE_BUILTIN_CTZ
301
+ #if HAVE_BUILTIN_CTZ
390
302
 
391
- inline int Bits::Log2FloorNonZero(uint32 n) {
303
+ inline int Bits::Log2FloorNonZero(uint32_t n) {
392
304
  assert(n != 0);
393
305
  // (31 ^ x) is equivalent to (31 - x) for x in [0, 31]. An easy proof
394
306
  // represents subtraction in base 2 and observes that there's no carry.
@@ -399,66 +311,52 @@ inline int Bits::Log2FloorNonZero(uint32 n) {
399
311
  return 31 ^ __builtin_clz(n);
400
312
  }
401
313
 
402
- inline int Bits::Log2Floor(uint32 n) {
314
+ inline int Bits::Log2Floor(uint32_t n) {
403
315
  return (n == 0) ? -1 : Bits::Log2FloorNonZero(n);
404
316
  }
405
317
 
406
- inline int Bits::FindLSBSetNonZero(uint32 n) {
318
+ inline int Bits::FindLSBSetNonZero(uint32_t n) {
407
319
  assert(n != 0);
408
320
  return __builtin_ctz(n);
409
321
  }
410
322
 
411
- #if defined(ARCH_K8) || defined(ARCH_PPC) || defined(ARCH_ARM)
412
- inline int Bits::FindLSBSetNonZero64(uint64 n) {
413
- assert(n != 0);
414
- return __builtin_ctzll(n);
415
- }
416
- #endif // defined(ARCH_K8) || defined(ARCH_PPC) || defined(ARCH_ARM)
417
-
418
323
  #elif defined(_MSC_VER)
419
324
 
420
- inline int Bits::Log2FloorNonZero(uint32 n) {
325
+ inline int Bits::Log2FloorNonZero(uint32_t n) {
421
326
  assert(n != 0);
327
+ // NOLINTNEXTLINE(runtime/int): The MSVC intrinsic demands unsigned long.
422
328
  unsigned long where;
423
329
  _BitScanReverse(&where, n);
424
330
  return static_cast<int>(where);
425
331
  }
426
332
 
427
- inline int Bits::Log2Floor(uint32 n) {
333
+ inline int Bits::Log2Floor(uint32_t n) {
334
+ // NOLINTNEXTLINE(runtime/int): The MSVC intrinsic demands unsigned long.
428
335
  unsigned long where;
429
336
  if (_BitScanReverse(&where, n))
430
337
  return static_cast<int>(where);
431
338
  return -1;
432
339
  }
433
340
 
434
- inline int Bits::FindLSBSetNonZero(uint32 n) {
341
+ inline int Bits::FindLSBSetNonZero(uint32_t n) {
435
342
  assert(n != 0);
343
+ // NOLINTNEXTLINE(runtime/int): The MSVC intrinsic demands unsigned long.
436
344
  unsigned long where;
437
345
  if (_BitScanForward(&where, n))
438
346
  return static_cast<int>(where);
439
347
  return 32;
440
348
  }
441
349
 
442
- #if defined(ARCH_K8) || defined(ARCH_PPC) || defined(ARCH_ARM)
443
- inline int Bits::FindLSBSetNonZero64(uint64 n) {
444
- assert(n != 0);
445
- unsigned long where;
446
- if (_BitScanForward64(&where, n))
447
- return static_cast<int>(where);
448
- return 64;
449
- }
450
- #endif // defined(ARCH_K8) || defined(ARCH_PPC) || defined(ARCH_ARM)
451
-
452
350
  #else // Portable versions.
453
351
 
454
- inline int Bits::Log2FloorNonZero(uint32 n) {
352
+ inline int Bits::Log2FloorNonZero(uint32_t n) {
455
353
  assert(n != 0);
456
354
 
457
355
  int log = 0;
458
- uint32 value = n;
356
+ uint32_t value = n;
459
357
  for (int i = 4; i >= 0; --i) {
460
358
  int shift = (1 << i);
461
- uint32 x = value >> shift;
359
+ uint32_t x = value >> shift;
462
360
  if (x != 0) {
463
361
  value = x;
464
362
  log += shift;
@@ -468,16 +366,16 @@ inline int Bits::Log2FloorNonZero(uint32 n) {
468
366
  return log;
469
367
  }
470
368
 
471
- inline int Bits::Log2Floor(uint32 n) {
369
+ inline int Bits::Log2Floor(uint32_t n) {
472
370
  return (n == 0) ? -1 : Bits::Log2FloorNonZero(n);
473
371
  }
474
372
 
475
- inline int Bits::FindLSBSetNonZero(uint32 n) {
373
+ inline int Bits::FindLSBSetNonZero(uint32_t n) {
476
374
  assert(n != 0);
477
375
 
478
376
  int rc = 31;
479
377
  for (int i = 4, shift = 1 << 4; i >= 0; --i) {
480
- const uint32 x = n << shift;
378
+ const uint32_t x = n << shift;
481
379
  if (x != 0) {
482
380
  n = x;
483
381
  rc -= shift;
@@ -487,27 +385,48 @@ inline int Bits::FindLSBSetNonZero(uint32 n) {
487
385
  return rc;
488
386
  }
489
387
 
490
- #if defined(ARCH_K8) || defined(ARCH_PPC) || defined(ARCH_ARM)
388
+ #endif // End portable versions.
389
+
390
+ #if HAVE_BUILTIN_CTZ
391
+
392
+ inline int Bits::FindLSBSetNonZero64(uint64_t n) {
393
+ assert(n != 0);
394
+ return __builtin_ctzll(n);
395
+ }
396
+
397
+ #elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
398
+ // _BitScanForward64() is only available on x64 and ARM64.
399
+
400
+ inline int Bits::FindLSBSetNonZero64(uint64_t n) {
401
+ assert(n != 0);
402
+ // NOLINTNEXTLINE(runtime/int): The MSVC intrinsic demands unsigned long.
403
+ unsigned long where;
404
+ if (_BitScanForward64(&where, n))
405
+ return static_cast<int>(where);
406
+ return 64;
407
+ }
408
+
409
+ #else // Portable version.
410
+
491
411
  // FindLSBSetNonZero64() is defined in terms of FindLSBSetNonZero().
492
- inline int Bits::FindLSBSetNonZero64(uint64 n) {
412
+ inline int Bits::FindLSBSetNonZero64(uint64_t n) {
493
413
  assert(n != 0);
494
414
 
495
- const uint32 bottombits = static_cast<uint32>(n);
415
+ const uint32_t bottombits = static_cast<uint32_t>(n);
496
416
  if (bottombits == 0) {
497
- // Bottom bits are zero, so scan in top bits
498
- return 32 + FindLSBSetNonZero(static_cast<uint32>(n >> 32));
417
+ // Bottom bits are zero, so scan the top bits.
418
+ return 32 + FindLSBSetNonZero(static_cast<uint32_t>(n >> 32));
499
419
  } else {
500
420
  return FindLSBSetNonZero(bottombits);
501
421
  }
502
422
  }
503
- #endif // defined(ARCH_K8) || defined(ARCH_PPC) || defined(ARCH_ARM)
504
423
 
505
- #endif // End portable versions.
424
+ #endif // HAVE_BUILTIN_CTZ
506
425
 
507
426
  // Variable-length integer encoding.
508
427
  class Varint {
509
428
  public:
510
- // Maximum lengths of varint encoding of uint32.
429
+ // Maximum lengths of varint encoding of uint32_t.
511
430
  static const int kMax32 = 5;
512
431
 
513
432
  // Attempts to parse a varint32 from a prefix of the bytes in [ptr,limit-1].
@@ -516,23 +435,23 @@ class Varint {
516
435
  // past the last byte of the varint32. Else returns NULL. On success,
517
436
  // "result <= limit".
518
437
  static const char* Parse32WithLimit(const char* ptr, const char* limit,
519
- uint32* OUTPUT);
438
+ uint32_t* OUTPUT);
520
439
 
521
440
  // REQUIRES "ptr" points to a buffer of length sufficient to hold "v".
522
441
  // EFFECTS Encodes "v" into "ptr" and returns a pointer to the
523
442
  // byte just past the last encoded byte.
524
- static char* Encode32(char* ptr, uint32 v);
443
+ static char* Encode32(char* ptr, uint32_t v);
525
444
 
526
445
  // EFFECTS Appends the varint representation of "value" to "*s".
527
- static void Append32(std::string* s, uint32 value);
446
+ static void Append32(std::string* s, uint32_t value);
528
447
  };
529
448
 
530
449
  inline const char* Varint::Parse32WithLimit(const char* p,
531
450
  const char* l,
532
- uint32* OUTPUT) {
451
+ uint32_t* OUTPUT) {
533
452
  const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
534
453
  const unsigned char* limit = reinterpret_cast<const unsigned char*>(l);
535
- uint32 b, result;
454
+ uint32_t b, result;
536
455
  if (ptr >= limit) return NULL;
537
456
  b = *(ptr++); result = b & 127; if (b < 128) goto done;
538
457
  if (ptr >= limit) return NULL;
@@ -549,30 +468,30 @@ inline const char* Varint::Parse32WithLimit(const char* p,
549
468
  return reinterpret_cast<const char*>(ptr);
550
469
  }
551
470
 
552
- inline char* Varint::Encode32(char* sptr, uint32 v) {
471
+ inline char* Varint::Encode32(char* sptr, uint32_t v) {
553
472
  // Operate on characters as unsigneds
554
- unsigned char* ptr = reinterpret_cast<unsigned char*>(sptr);
555
- static const int B = 128;
556
- if (v < (1<<7)) {
557
- *(ptr++) = v;
558
- } else if (v < (1<<14)) {
559
- *(ptr++) = v | B;
560
- *(ptr++) = v>>7;
561
- } else if (v < (1<<21)) {
562
- *(ptr++) = v | B;
563
- *(ptr++) = (v>>7) | B;
564
- *(ptr++) = v>>14;
565
- } else if (v < (1<<28)) {
566
- *(ptr++) = v | B;
567
- *(ptr++) = (v>>7) | B;
568
- *(ptr++) = (v>>14) | B;
569
- *(ptr++) = v>>21;
473
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(sptr);
474
+ static const uint8_t B = 128;
475
+ if (v < (1 << 7)) {
476
+ *(ptr++) = static_cast<uint8_t>(v);
477
+ } else if (v < (1 << 14)) {
478
+ *(ptr++) = static_cast<uint8_t>(v | B);
479
+ *(ptr++) = static_cast<uint8_t>(v >> 7);
480
+ } else if (v < (1 << 21)) {
481
+ *(ptr++) = static_cast<uint8_t>(v | B);
482
+ *(ptr++) = static_cast<uint8_t>((v >> 7) | B);
483
+ *(ptr++) = static_cast<uint8_t>(v >> 14);
484
+ } else if (v < (1 << 28)) {
485
+ *(ptr++) = static_cast<uint8_t>(v | B);
486
+ *(ptr++) = static_cast<uint8_t>((v >> 7) | B);
487
+ *(ptr++) = static_cast<uint8_t>((v >> 14) | B);
488
+ *(ptr++) = static_cast<uint8_t>(v >> 21);
570
489
  } else {
571
- *(ptr++) = v | B;
572
- *(ptr++) = (v>>7) | B;
573
- *(ptr++) = (v>>14) | B;
574
- *(ptr++) = (v>>21) | B;
575
- *(ptr++) = v>>28;
490
+ *(ptr++) = static_cast<uint8_t>(v | B);
491
+ *(ptr++) = static_cast<uint8_t>((v>>7) | B);
492
+ *(ptr++) = static_cast<uint8_t>((v>>14) | B);
493
+ *(ptr++) = static_cast<uint8_t>((v>>21) | B);
494
+ *(ptr++) = static_cast<uint8_t>(v >> 28);
576
495
  }
577
496
  return reinterpret_cast<char*>(ptr);
578
497
  }