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