/*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef FOLLY_EXPERIMENTAL_BITS_H_
-#define FOLLY_EXPERIMENTAL_BITS_H_
+#pragma once
#include <cstddef>
-#include <type_traits>
#include <limits>
+#include <type_traits>
+
+#include <glog/logging.h>
#include <folly/Bits.h>
#include <folly/Portability.h>
static T load(const Unaligned<T>& x) { return x.value; }
static void store(Unaligned<T>& x, T v) { x.value = v; }
static T loadRMW(const Unaligned<T>& x) {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wuninitialized"
-// make sure we compile without warning on gcc 4.6 with -Wpragmas
-#if __GNUC_PREREQ(4, 7)
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+ FOLLY_PUSH_WARNING
+ FOLLY_GCC_DISABLE_WARNING("-Wuninitialized")
+#if !__clang__ // for gcc version [4.8, ?)
+ FOLLY_GCC_DISABLE_WARNING("-Wmaybe-uninitialized")
#endif
return x.value;
-#pragma GCC diagnostic pop
+ FOLLY_POP_WARNING
}
};
-// Special version that allows to disable address sanitizer on demand.
+// Special version that allows one to disable address sanitizer on demand.
template <class T>
struct BitsTraits<UnalignedNoASan<T>, typename std::enable_if<
(std::is_integral<T>::value)>::type> {
store(UnalignedNoASan<T>& x, T v) { x.value = v; }
static T FOLLY_DISABLE_ADDRESS_SANITIZER
loadRMW(const UnalignedNoASan<T>& x) {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wuninitialized"
-// make sure we compile without warning on gcc 4.6 with -Wpragmas
-#if __GNUC_PREREQ(4, 7)
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+ FOLLY_PUSH_WARNING
+ FOLLY_GCC_DISABLE_WARNING("-Wuninitialized")
+#if !__clang__ // for gcc version [4.8, ?)
+ FOLLY_GCC_DISABLE_WARNING("-Wmaybe-uninitialized")
#endif
return x.value;
-#pragma GCC diagnostic pop
+ FOLLY_POP_WARNING
}
};
static T load(const T& x) { return x; }
static void store(T& x, T v) { x = v; }
static T loadRMW(const T& x) {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wuninitialized"
-#if __GNUC_PREREQ(4, 7)
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+ FOLLY_PUSH_WARNING
+ FOLLY_GCC_DISABLE_WARNING("-Wuninitialized")
+#if !__clang__ // for gcc version [4.8, ?)
+ FOLLY_GCC_DISABLE_WARNING("-Wmaybe-uninitialized")
#endif
return x;
-#pragma GCC diagnostic pop
+ FOLLY_POP_WARNING
}
};
-} // namespace detail
+} // namespace detail
/**
* Wrapper class with static methods for various bit-level operations,
static constexpr UnderlyingType zero = UnderlyingType(0);
static constexpr UnderlyingType one = UnderlyingType(1);
+ using UnsignedType = typename std::make_unsigned<UnderlyingType>::type;
static constexpr UnderlyingType ones(size_t count) {
- return count < bitsPerBlock ? (one << count) - 1 : ~zero;
+ return (count < bitsPerBlock)
+ ? static_cast<UnderlyingType>((UnsignedType{1} << count) - 1)
+ : ~zero;
}
};
// gcc 4.8 needs more -Wmaybe-uninitialized tickling, as it propagates the
// taint upstream from loadRMW
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wuninitialized"
-#if __GNUC_PREREQ(4, 7)
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+FOLLY_PUSH_WARNING
+FOLLY_GCC_DISABLE_WARNING("-Wuninitialized")
+#if !__clang__ // for gcc version [4.8, ?)
+FOLLY_GCC_DISABLE_WARNING("-Wmaybe-uninitialized")
#endif
template <class T, class Traits>
template <class T, class Traits>
inline void Bits<T, Traits>::set(T* p, size_t bitStart, size_t count,
UnderlyingType value) {
- assert(count <= sizeof(UnderlyingType) * 8);
+ DCHECK_LE(count, sizeof(UnderlyingType) * 8);
size_t cut = bitsPerBlock - count;
- assert(value == (value << cut >> cut));
+ if (cut != 8 * sizeof(UnderlyingType)) {
+ using U = typename std::make_unsigned<UnderlyingType>::type;
+ DCHECK_EQ(value, UnderlyingType(U(value) << cut) >> cut);
+ }
size_t idx = blockIndex(bitStart);
size_t offset = bitOffset(bitStart);
if (std::is_signed<UnderlyingType>::value) {
size_t countInThisBlock = bitsPerBlock - offset;
size_t countInNextBlock = count - countInThisBlock;
- UnderlyingType thisBlock = value & ((one << countInThisBlock) - 1);
- UnderlyingType nextBlock = value >> countInThisBlock;
+ UnderlyingType thisBlock = UnderlyingType(value & ones(countInThisBlock));
+ UnderlyingType nextBlock = UnderlyingType(value >> countInThisBlock);
if (std::is_signed<UnderlyingType>::value) {
nextBlock &= ones(countInNextBlock);
}
Traits::store(*p, v);
}
-#pragma GCC diagnostic pop
+FOLLY_POP_WARNING
template <class T, class Traits>
inline bool Bits<T, Traits>::test(const T* p, size_t bit) {
template <class T, class Traits>
inline auto Bits<T, Traits>::get(const T* p, size_t bitStart, size_t count)
-> UnderlyingType {
- assert(count <= sizeof(UnderlyingType) * 8);
+ if (count == 0) {
+ return UnderlyingType{};
+ }
+
+ DCHECK_LE(count, sizeof(UnderlyingType) * 8);
size_t idx = blockIndex(bitStart);
size_t offset = bitOffset(bitStart);
UnderlyingType ret;
return n;
}
-} // namespace folly
-
-#endif /* FOLLY_EXPERIMENTAL_BITS_H_ */
+} // namespace folly