Change AsyncSSLSocket getSecurityProtocol to handle unencrypted mode
[folly.git] / folly / experimental / Bits.h
index 0601513fd3ee596e4f2d23ad677d2b509179416a..0b1960c26609a8fd207ef4d55fda3fde41ef6047 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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>
@@ -55,18 +56,17 @@ struct BitsTraits<Unaligned<T>, typename std::enable_if<
   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> {
@@ -77,14 +77,13 @@ struct BitsTraits<UnalignedNoASan<T>, typename std::enable_if<
   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
   }
 };
 
@@ -96,17 +95,17 @@ struct BitsTraits<T, typename std::enable_if<
   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,
@@ -195,18 +194,20 @@ struct Bits {
   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>
@@ -224,9 +225,12 @@ inline void Bits<T, Traits>::clear(T* p, size_t bit) {
 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) {
@@ -238,8 +242,8 @@ inline void Bits<T, Traits>::set(T* p, size_t bitStart, size_t count,
     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);
     }
@@ -258,7 +262,7 @@ inline void Bits<T, Traits>::innerSet(T* p, size_t offset, size_t count,
   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) {
@@ -268,7 +272,11 @@ 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;
@@ -304,6 +312,4 @@ inline size_t Bits<T, Traits>::count(const T* begin, const T* end) {
   return n;
 }
 
-}  // namespace folly
-
-#endif /* FOLLY_EXPERIMENTAL_BITS_H_ */
+} // namespace folly