1 //
2 //
3 // Copyright 2015 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #ifndef GRPC_SRC_CORE_LIB_GPR_USEFUL_H
20 #define GRPC_SRC_CORE_LIB_GPR_USEFUL_H
21 
22 #include <grpc/support/port_platform.h>
23 
24 #include <cstddef>
25 
26 #include "absl/strings/string_view.h"
27 #include "absl/types/variant.h"
28 
29 /// useful utilities that don't belong anywhere else
30 
31 namespace grpc_core {
32 
33 template <typename T>
Clamp(T val,T min,T max)34 T Clamp(T val, T min, T max) {
35   if (val < min) return min;
36   if (max < val) return max;
37   return val;
38 }
39 
40 /// rotl, rotr assume x is unsigned
41 template <typename T>
RotateLeft(T x,T n)42 constexpr T RotateLeft(T x, T n) {
43   return ((x << n) | (x >> (sizeof(x) * 8 - n)));
44 }
45 template <typename T>
RotateRight(T x,T n)46 constexpr T RotateRight(T x, T n) {
47   return ((x >> n) | (x << (sizeof(x) * 8 - n)));
48 }
49 
50 // Set the n-th bit of i
51 template <typename T>
SetBit(T * i,size_t n)52 T SetBit(T* i, size_t n) {
53   return *i |= (T(1) << n);
54 }
55 
56 // Clear the n-th bit of i
57 template <typename T>
ClearBit(T * i,size_t n)58 T ClearBit(T* i, size_t n) {
59   return *i &= ~(T(1) << n);
60 }
61 
62 // Get the n-th bit of i
63 template <typename T>
GetBit(T i,size_t n)64 bool GetBit(T i, size_t n) {
65   return (i & (T(1) << n)) != 0;
66 }
67 
68 namespace useful_detail {
HexdigitBitcount(uint32_t x)69 inline constexpr uint32_t HexdigitBitcount(uint32_t x) {
70   return (x - ((x >> 1) & 0x77777777) - ((x >> 2) & 0x33333333) -
71           ((x >> 3) & 0x11111111));
72 }
73 }  // namespace useful_detail
74 
BitCount(uint32_t i)75 inline constexpr uint32_t BitCount(uint32_t i) {
76   return (((useful_detail::HexdigitBitcount(i) +
77             (useful_detail::HexdigitBitcount(i) >> 4)) &
78            0x0f0f0f0f) %
79           255);
80 }
81 
BitCount(uint64_t i)82 inline constexpr uint32_t BitCount(uint64_t i) {
83   return BitCount(static_cast<uint32_t>(i)) +
84          BitCount(static_cast<uint32_t>(i >> 32));
85 }
86 
BitCount(uint16_t i)87 inline constexpr uint32_t BitCount(uint16_t i) {
88   return BitCount(static_cast<uint32_t>(i));
89 }
BitCount(uint8_t i)90 inline constexpr uint32_t BitCount(uint8_t i) {
91   return BitCount(static_cast<uint32_t>(i));
92 }
BitCount(int64_t i)93 inline constexpr uint32_t BitCount(int64_t i) {
94   return BitCount(static_cast<uint64_t>(i));
95 }
BitCount(int32_t i)96 inline constexpr uint32_t BitCount(int32_t i) {
97   return BitCount(static_cast<uint32_t>(i));
98 }
BitCount(int16_t i)99 inline constexpr uint32_t BitCount(int16_t i) {
100   return BitCount(static_cast<uint16_t>(i));
101 }
BitCount(int8_t i)102 inline constexpr uint32_t BitCount(int8_t i) {
103   return BitCount(static_cast<uint8_t>(i));
104 }
105 
106 // This function uses operator< to implement a qsort-style comparison, whereby:
107 // if a is smaller than b, a number smaller than 0 is returned.
108 // if a is bigger than b, a number greater than 0 is returned.
109 // if a is neither smaller nor bigger than b, 0 is returned.
110 template <typename T>
QsortCompare(const T & a,const T & b)111 int QsortCompare(const T& a, const T& b) {
112   if (a < b) return -1;
113   if (b < a) return 1;
114   return 0;
115 }
116 
117 template <typename... X>
QsortCompare(const absl::variant<X...> & a,const absl::variant<X...> & b)118 int QsortCompare(const absl::variant<X...>& a, const absl::variant<X...>& b) {
119   const int index = QsortCompare(a.index(), b.index());
120   if (index != 0) return index;
121   return absl::visit(
122       [&](const auto& x) {
123         return QsortCompare(x, absl::get<absl::remove_cvref_t<decltype(x)>>(b));
124       },
125       a);
126 }
127 
QsortCompare(absl::string_view a,absl::string_view b)128 inline int QsortCompare(absl::string_view a, absl::string_view b) {
129   return a.compare(b);
130 }
131 
QsortCompare(const std::string & a,const std::string & b)132 inline int QsortCompare(const std::string& a, const std::string& b) {
133   return a.compare(b);
134 }
135 
136 template <typename A, typename B>
QsortCompare(const std::pair<A,B> & a,const std::pair<A,B> & b)137 int QsortCompare(const std::pair<A, B>& a, const std::pair<A, B>& b) {
138   const int first = QsortCompare(a.first, b.first);
139   if (first != 0) return first;
140   return QsortCompare(a.second, b.second);
141 }
142 
143 template <typename T>
HashPointer(T * p,size_t range)144 constexpr size_t HashPointer(T* p, size_t range) {
145   return (((reinterpret_cast<size_t>(p)) >> 4) ^
146           ((reinterpret_cast<size_t>(p)) >> 9) ^
147           ((reinterpret_cast<size_t>(p)) >> 14)) %
148          range;
149 }
150 
151 // Compute a+b.
152 // If the result is greater than INT64_MAX, return INT64_MAX.
153 // If the result is less than INT64_MIN, return INT64_MIN.
SaturatingAdd(int64_t a,int64_t b)154 inline int64_t SaturatingAdd(int64_t a, int64_t b) {
155   if (a > 0) {
156     if (b > INT64_MAX - a) {
157       return INT64_MAX;
158     }
159   } else if (b < INT64_MIN - a) {
160     return INT64_MIN;
161   }
162   return a + b;
163 }
164 
MixHash32(uint32_t a,uint32_t b)165 inline uint32_t MixHash32(uint32_t a, uint32_t b) {
166   return RotateLeft(a, 2u) ^ b;
167 }
168 
RoundUpToPowerOf2(uint32_t v)169 inline uint32_t RoundUpToPowerOf2(uint32_t v) {
170   v--;
171   v |= v >> 1;
172   v |= v >> 2;
173   v |= v >> 4;
174   v |= v >> 8;
175   v |= v >> 16;
176   v++;
177   return v;
178 }
179 
180 }  // namespace grpc_core
181 
182 #define GPR_ARRAY_SIZE(array) (sizeof(array) / sizeof(*(array)))
183 
184 #endif  // GRPC_SRC_CORE_LIB_GPR_USEFUL_H
185