cannam@49
|
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
cannam@49
|
2 // Licensed under the MIT License:
|
cannam@49
|
3 //
|
cannam@49
|
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
cannam@49
|
5 // of this software and associated documentation files (the "Software"), to deal
|
cannam@49
|
6 // in the Software without restriction, including without limitation the rights
|
cannam@49
|
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
cannam@49
|
8 // copies of the Software, and to permit persons to whom the Software is
|
cannam@49
|
9 // furnished to do so, subject to the following conditions:
|
cannam@49
|
10 //
|
cannam@49
|
11 // The above copyright notice and this permission notice shall be included in
|
cannam@49
|
12 // all copies or substantial portions of the Software.
|
cannam@49
|
13 //
|
cannam@49
|
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
cannam@49
|
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
cannam@49
|
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
cannam@49
|
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
cannam@49
|
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
cannam@49
|
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
cannam@49
|
20 // THE SOFTWARE.
|
cannam@49
|
21
|
cannam@49
|
22 // Header that should be #included by everyone.
|
cannam@49
|
23 //
|
cannam@49
|
24 // This defines very simple utilities that are widely applicable.
|
cannam@49
|
25
|
cannam@49
|
26 #ifndef KJ_COMMON_H_
|
cannam@49
|
27 #define KJ_COMMON_H_
|
cannam@49
|
28
|
cannam@49
|
29 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS
|
cannam@49
|
30 #pragma GCC system_header
|
cannam@49
|
31 #endif
|
cannam@49
|
32
|
cannam@49
|
33 #ifndef KJ_NO_COMPILER_CHECK
|
cannam@49
|
34 #if __cplusplus < 201103L && !__CDT_PARSER__ && !_MSC_VER
|
cannam@49
|
35 #error "This code requires C++11. Either your compiler does not support it or it is not enabled."
|
cannam@49
|
36 #ifdef __GNUC__
|
cannam@49
|
37 // Compiler claims compatibility with GCC, so presumably supports -std.
|
cannam@49
|
38 #error "Pass -std=c++11 on the compiler command line to enable C++11."
|
cannam@49
|
39 #endif
|
cannam@49
|
40 #endif
|
cannam@49
|
41
|
cannam@49
|
42 #ifdef __GNUC__
|
cannam@49
|
43 #if __clang__
|
cannam@49
|
44 #if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2)
|
cannam@49
|
45 #warning "This library requires at least Clang 3.2."
|
cannam@49
|
46 #elif defined(__apple_build_version__) && __apple_build_version__ <= 4250028
|
cannam@49
|
47 #warning "This library requires at least Clang 3.2. XCode 4.6's Clang, which claims to be "\
|
cannam@49
|
48 "version 4.2 (wat?), is actually built from some random SVN revision between 3.1 "\
|
cannam@49
|
49 "and 3.2. Unfortunately, it is insufficient for compiling this library. You can "\
|
cannam@49
|
50 "download the real Clang 3.2 (or newer) from the Clang web site. Step-by-step "\
|
cannam@49
|
51 "instructions can be found in Cap'n Proto's documentation: "\
|
cannam@49
|
52 "http://kentonv.github.io/capnproto/install.html#clang_32_on_mac_osx"
|
cannam@49
|
53 #elif __cplusplus >= 201103L && !__has_include(<initializer_list>)
|
cannam@49
|
54 #warning "Your compiler supports C++11 but your C++ standard library does not. If your "\
|
cannam@49
|
55 "system has libc++ installed (as should be the case on e.g. Mac OSX), try adding "\
|
cannam@49
|
56 "-stdlib=libc++ to your CXXFLAGS."
|
cannam@49
|
57 #endif
|
cannam@49
|
58 #else
|
cannam@49
|
59 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
|
cannam@49
|
60 #warning "This library requires at least GCC 4.7."
|
cannam@49
|
61 #endif
|
cannam@49
|
62 #endif
|
cannam@49
|
63 #elif defined(_MSC_VER)
|
cannam@49
|
64 #if _MSC_VER < 1900
|
cannam@49
|
65 #error "You need Visual Studio 2015 or better to compile this code."
|
cannam@49
|
66 #elif !CAPNP_LITE
|
cannam@49
|
67 // TODO(cleanup): This is KJ, but we're talking about Cap'n Proto.
|
cannam@49
|
68 #error "As of this writing, Cap'n Proto only supports Visual C++ in 'lite mode'; please #define CAPNP_LITE"
|
cannam@49
|
69 #endif
|
cannam@49
|
70 #else
|
cannam@49
|
71 #warning "I don't recognize your compiler. As of this writing, Clang and GCC are the only "\
|
cannam@49
|
72 "known compilers with enough C++11 support for this library. "\
|
cannam@49
|
73 "#define KJ_NO_COMPILER_CHECK to make this warning go away."
|
cannam@49
|
74 #endif
|
cannam@49
|
75 #endif
|
cannam@49
|
76
|
cannam@49
|
77 #include <stddef.h>
|
cannam@49
|
78 #include <initializer_list>
|
cannam@49
|
79
|
cannam@49
|
80 #if __linux__ && __cplusplus > 201200L
|
cannam@49
|
81 // Hack around stdlib bug with C++14 that exists on some Linux systems.
|
cannam@49
|
82 // Apparently in this mode the C library decides not to define gets() but the C++ library still
|
cannam@49
|
83 // tries to import it into the std namespace. This bug has been fixed at the source but is still
|
cannam@49
|
84 // widely present in the wild e.g. on Ubuntu 14.04.
|
cannam@49
|
85 #undef _GLIBCXX_HAVE_GETS
|
cannam@49
|
86 #endif
|
cannam@49
|
87
|
cannam@49
|
88 #if defined(_MSC_VER)
|
cannam@49
|
89 #include <intrin.h> // __popcnt
|
cannam@49
|
90 #endif
|
cannam@49
|
91
|
cannam@49
|
92 // =======================================================================================
|
cannam@49
|
93
|
cannam@49
|
94 namespace kj {
|
cannam@49
|
95
|
cannam@49
|
96 typedef unsigned int uint;
|
cannam@49
|
97 typedef unsigned char byte;
|
cannam@49
|
98
|
cannam@49
|
99 // =======================================================================================
|
cannam@49
|
100 // Common macros, especially for common yet compiler-specific features.
|
cannam@49
|
101
|
cannam@49
|
102 // Detect whether RTTI and exceptions are enabled, assuming they are unless we have specific
|
cannam@49
|
103 // evidence to the contrary. Clients can always define KJ_NO_RTTI or KJ_NO_EXCEPTIONS explicitly
|
cannam@49
|
104 // to override these checks.
|
cannam@49
|
105 #ifdef __GNUC__
|
cannam@49
|
106 #if !defined(KJ_NO_RTTI) && !__GXX_RTTI
|
cannam@49
|
107 #define KJ_NO_RTTI 1
|
cannam@49
|
108 #endif
|
cannam@49
|
109 #if !defined(KJ_NO_EXCEPTIONS) && !__EXCEPTIONS
|
cannam@49
|
110 #define KJ_NO_EXCEPTIONS 1
|
cannam@49
|
111 #endif
|
cannam@49
|
112 #elif defined(_MSC_VER)
|
cannam@49
|
113 #if !defined(KJ_NO_RTTI) && !defined(_CPPRTTI)
|
cannam@49
|
114 #define KJ_NO_RTTI 1
|
cannam@49
|
115 #endif
|
cannam@49
|
116 #if !defined(KJ_NO_EXCEPTIONS) && !defined(_CPPUNWIND)
|
cannam@49
|
117 #define KJ_NO_EXCEPTIONS 1
|
cannam@49
|
118 #endif
|
cannam@49
|
119 #endif
|
cannam@49
|
120
|
cannam@49
|
121 #if !defined(KJ_DEBUG) && !defined(KJ_NDEBUG)
|
cannam@49
|
122 // Heuristically decide whether to enable debug mode. If DEBUG or NDEBUG is defined, use that.
|
cannam@49
|
123 // Otherwise, fall back to checking whether optimization is enabled.
|
cannam@49
|
124 #if defined(DEBUG) || defined(_DEBUG)
|
cannam@49
|
125 #define KJ_DEBUG
|
cannam@49
|
126 #elif defined(NDEBUG)
|
cannam@49
|
127 #define KJ_NDEBUG
|
cannam@49
|
128 #elif __OPTIMIZE__
|
cannam@49
|
129 #define KJ_NDEBUG
|
cannam@49
|
130 #else
|
cannam@49
|
131 #define KJ_DEBUG
|
cannam@49
|
132 #endif
|
cannam@49
|
133 #endif
|
cannam@49
|
134
|
cannam@49
|
135 #define KJ_DISALLOW_COPY(classname) \
|
cannam@49
|
136 classname(const classname&) = delete; \
|
cannam@49
|
137 classname& operator=(const classname&) = delete
|
cannam@49
|
138 // Deletes the implicit copy constructor and assignment operator.
|
cannam@49
|
139
|
cannam@49
|
140 #ifdef __GNUC__
|
cannam@49
|
141 #define KJ_LIKELY(condition) __builtin_expect(condition, true)
|
cannam@49
|
142 #define KJ_UNLIKELY(condition) __builtin_expect(condition, false)
|
cannam@49
|
143 // Branch prediction macros. Evaluates to the condition given, but also tells the compiler that we
|
cannam@49
|
144 // expect the condition to be true/false enough of the time that it's worth hard-coding branch
|
cannam@49
|
145 // prediction.
|
cannam@49
|
146 #else
|
cannam@49
|
147 #define KJ_LIKELY(condition) (condition)
|
cannam@49
|
148 #define KJ_UNLIKELY(condition) (condition)
|
cannam@49
|
149 #endif
|
cannam@49
|
150
|
cannam@49
|
151 #if defined(KJ_DEBUG) || __NO_INLINE__
|
cannam@49
|
152 #define KJ_ALWAYS_INLINE(prototype) inline prototype
|
cannam@49
|
153 // Don't force inline in debug mode.
|
cannam@49
|
154 #else
|
cannam@49
|
155 #if defined(_MSC_VER)
|
cannam@49
|
156 #define KJ_ALWAYS_INLINE(prototype) __forceinline prototype
|
cannam@49
|
157 #else
|
cannam@49
|
158 #define KJ_ALWAYS_INLINE(prototype) inline prototype __attribute__((always_inline))
|
cannam@49
|
159 #endif
|
cannam@49
|
160 // Force a function to always be inlined. Apply only to the prototype, not to the definition.
|
cannam@49
|
161 #endif
|
cannam@49
|
162
|
cannam@49
|
163 #if defined(_MSC_VER)
|
cannam@49
|
164 #define KJ_NOINLINE __declspec(noinline)
|
cannam@49
|
165 #else
|
cannam@49
|
166 #define KJ_NOINLINE __attribute__((noinline))
|
cannam@49
|
167 #endif
|
cannam@49
|
168
|
cannam@49
|
169 #if defined(_MSC_VER)
|
cannam@49
|
170 #define KJ_NORETURN(prototype) __declspec(noreturn) prototype
|
cannam@49
|
171 #define KJ_UNUSED
|
cannam@49
|
172 #define KJ_WARN_UNUSED_RESULT
|
cannam@49
|
173 // TODO(msvc): KJ_WARN_UNUSED_RESULT can use _Check_return_ on MSVC, but it's a prefix, so
|
cannam@49
|
174 // wrapping the whole prototype is needed. http://msdn.microsoft.com/en-us/library/jj159529.aspx
|
cannam@49
|
175 // Similarly, KJ_UNUSED could use __pragma(warning(suppress:...)), but again that's a prefix.
|
cannam@49
|
176 #else
|
cannam@49
|
177 #define KJ_NORETURN(prototype) prototype __attribute__((noreturn))
|
cannam@49
|
178 #define KJ_UNUSED __attribute__((unused))
|
cannam@49
|
179 #define KJ_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
cannam@49
|
180 #endif
|
cannam@49
|
181
|
cannam@49
|
182 #if __clang__
|
cannam@49
|
183 #define KJ_UNUSED_MEMBER __attribute__((unused))
|
cannam@49
|
184 // Inhibits "unused" warning for member variables. Only Clang produces such a warning, while GCC
|
cannam@49
|
185 // complains if the attribute is set on members.
|
cannam@49
|
186 #else
|
cannam@49
|
187 #define KJ_UNUSED_MEMBER
|
cannam@49
|
188 #endif
|
cannam@49
|
189
|
cannam@49
|
190 #if __clang__
|
cannam@49
|
191 #define KJ_DEPRECATED(reason) \
|
cannam@49
|
192 __attribute__((deprecated(reason)))
|
cannam@49
|
193 #define KJ_UNAVAILABLE(reason) \
|
cannam@49
|
194 __attribute__((unavailable(reason)))
|
cannam@49
|
195 #elif __GNUC__
|
cannam@49
|
196 #define KJ_DEPRECATED(reason) \
|
cannam@49
|
197 __attribute__((deprecated))
|
cannam@49
|
198 #define KJ_UNAVAILABLE(reason)
|
cannam@49
|
199 #else
|
cannam@49
|
200 #define KJ_DEPRECATED(reason)
|
cannam@49
|
201 #define KJ_UNAVAILABLE(reason)
|
cannam@49
|
202 // TODO(msvc): Again, here, MSVC prefers a prefix, __declspec(deprecated).
|
cannam@49
|
203 #endif
|
cannam@49
|
204
|
cannam@49
|
205 namespace _ { // private
|
cannam@49
|
206
|
cannam@49
|
207 KJ_NORETURN(void inlineRequireFailure(
|
cannam@49
|
208 const char* file, int line, const char* expectation, const char* macroArgs,
|
cannam@49
|
209 const char* message = nullptr));
|
cannam@49
|
210
|
cannam@49
|
211 KJ_NORETURN(void unreachable());
|
cannam@49
|
212
|
cannam@49
|
213 } // namespace _ (private)
|
cannam@49
|
214
|
cannam@49
|
215 #ifdef KJ_DEBUG
|
cannam@49
|
216 #if _MSC_VER
|
cannam@49
|
217 #define KJ_IREQUIRE(condition, ...) \
|
cannam@49
|
218 if (KJ_LIKELY(condition)); else ::kj::_::inlineRequireFailure( \
|
cannam@49
|
219 __FILE__, __LINE__, #condition, "" #__VA_ARGS__, __VA_ARGS__)
|
cannam@49
|
220 // Version of KJ_DREQUIRE() which is safe to use in headers that are #included by users. Used to
|
cannam@49
|
221 // check preconditions inside inline methods. KJ_IREQUIRE is particularly useful in that
|
cannam@49
|
222 // it will be enabled depending on whether the application is compiled in debug mode rather than
|
cannam@49
|
223 // whether libkj is.
|
cannam@49
|
224 #else
|
cannam@49
|
225 #define KJ_IREQUIRE(condition, ...) \
|
cannam@49
|
226 if (KJ_LIKELY(condition)); else ::kj::_::inlineRequireFailure( \
|
cannam@49
|
227 __FILE__, __LINE__, #condition, #__VA_ARGS__, ##__VA_ARGS__)
|
cannam@49
|
228 // Version of KJ_DREQUIRE() which is safe to use in headers that are #included by users. Used to
|
cannam@49
|
229 // check preconditions inside inline methods. KJ_IREQUIRE is particularly useful in that
|
cannam@49
|
230 // it will be enabled depending on whether the application is compiled in debug mode rather than
|
cannam@49
|
231 // whether libkj is.
|
cannam@49
|
232 #endif
|
cannam@49
|
233 #else
|
cannam@49
|
234 #define KJ_IREQUIRE(condition, ...)
|
cannam@49
|
235 #endif
|
cannam@49
|
236
|
cannam@49
|
237 #define KJ_IASSERT KJ_IREQUIRE
|
cannam@49
|
238
|
cannam@49
|
239 #define KJ_UNREACHABLE ::kj::_::unreachable();
|
cannam@49
|
240 // Put this on code paths that cannot be reached to suppress compiler warnings about missing
|
cannam@49
|
241 // returns.
|
cannam@49
|
242
|
cannam@49
|
243 #if __clang__
|
cannam@49
|
244 #define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT
|
cannam@49
|
245 #else
|
cannam@49
|
246 #define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT KJ_UNREACHABLE
|
cannam@49
|
247 #endif
|
cannam@49
|
248
|
cannam@49
|
249 // #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack)
|
cannam@49
|
250 //
|
cannam@49
|
251 // Allocate an array, preferably on the stack, unless it is too big. On GCC this will use
|
cannam@49
|
252 // variable-sized arrays. For other compilers we could just use a fixed-size array. `minStack`
|
cannam@49
|
253 // is the stack array size to use if variable-width arrays are not supported. `maxStack` is the
|
cannam@49
|
254 // maximum stack array size if variable-width arrays *are* supported.
|
cannam@49
|
255 #if __GNUC__ && !__clang__
|
cannam@49
|
256 #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \
|
cannam@49
|
257 size_t name##_size = (size); \
|
cannam@49
|
258 bool name##_isOnStack = name##_size <= (maxStack); \
|
cannam@49
|
259 type name##_stack[name##_isOnStack ? size : 0]; \
|
cannam@49
|
260 ::kj::Array<type> name##_heap = name##_isOnStack ? \
|
cannam@49
|
261 nullptr : kj::heapArray<type>(name##_size); \
|
cannam@49
|
262 ::kj::ArrayPtr<type> name = name##_isOnStack ? \
|
cannam@49
|
263 kj::arrayPtr(name##_stack, name##_size) : name##_heap
|
cannam@49
|
264 #else
|
cannam@49
|
265 #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \
|
cannam@49
|
266 size_t name##_size = (size); \
|
cannam@49
|
267 bool name##_isOnStack = name##_size <= (minStack); \
|
cannam@49
|
268 type name##_stack[minStack]; \
|
cannam@49
|
269 ::kj::Array<type> name##_heap = name##_isOnStack ? \
|
cannam@49
|
270 nullptr : kj::heapArray<type>(name##_size); \
|
cannam@49
|
271 ::kj::ArrayPtr<type> name = name##_isOnStack ? \
|
cannam@49
|
272 kj::arrayPtr(name##_stack, name##_size) : name##_heap
|
cannam@49
|
273 #endif
|
cannam@49
|
274
|
cannam@49
|
275 #define KJ_CONCAT_(x, y) x##y
|
cannam@49
|
276 #define KJ_CONCAT(x, y) KJ_CONCAT_(x, y)
|
cannam@49
|
277 #define KJ_UNIQUE_NAME(prefix) KJ_CONCAT(prefix, __LINE__)
|
cannam@49
|
278 // Create a unique identifier name. We use concatenate __LINE__ rather than __COUNTER__ so that
|
cannam@49
|
279 // the name can be used multiple times in the same macro.
|
cannam@49
|
280
|
cannam@49
|
281 #if _MSC_VER
|
cannam@49
|
282
|
cannam@49
|
283 #define KJ_CONSTEXPR(...) __VA_ARGS__
|
cannam@49
|
284 // Use in cases where MSVC barfs on constexpr. A replacement keyword (e.g. "const") can be
|
cannam@49
|
285 // provided, or just leave blank to remove the keyword entirely.
|
cannam@49
|
286 //
|
cannam@49
|
287 // TODO(msvc): Remove this hack once MSVC fully supports constexpr.
|
cannam@49
|
288
|
cannam@49
|
289 #ifndef __restrict__
|
cannam@49
|
290 #define __restrict__ __restrict
|
cannam@49
|
291 // TODO(msvc): Would it be better to define a KJ_RESTRICT macro?
|
cannam@49
|
292 #endif
|
cannam@49
|
293
|
cannam@49
|
294 #pragma warning(disable: 4521 4522)
|
cannam@49
|
295 // This warning complains when there are two copy constructors, one for a const reference and
|
cannam@49
|
296 // one for a non-const reference. It is often quite necessary to do this in wrapper templates,
|
cannam@49
|
297 // therefore this warning is dumb and we disable it.
|
cannam@49
|
298
|
cannam@49
|
299 #pragma warning(disable: 4458)
|
cannam@49
|
300 // Warns when a parameter name shadows a class member. Unfortunately my code does this a lot,
|
cannam@49
|
301 // since I don't use a special name format for members.
|
cannam@49
|
302
|
cannam@49
|
303 #else // _MSC_VER
|
cannam@49
|
304 #define KJ_CONSTEXPR(...) constexpr
|
cannam@49
|
305 #endif
|
cannam@49
|
306
|
cannam@49
|
307 // =======================================================================================
|
cannam@49
|
308 // Template metaprogramming helpers.
|
cannam@49
|
309
|
cannam@49
|
310 template <typename T> struct NoInfer_ { typedef T Type; };
|
cannam@49
|
311 template <typename T> using NoInfer = typename NoInfer_<T>::Type;
|
cannam@49
|
312 // Use NoInfer<T>::Type in place of T for a template function parameter to prevent inference of
|
cannam@49
|
313 // the type based on the parameter value.
|
cannam@49
|
314
|
cannam@49
|
315 template <typename T> struct RemoveConst_ { typedef T Type; };
|
cannam@49
|
316 template <typename T> struct RemoveConst_<const T> { typedef T Type; };
|
cannam@49
|
317 template <typename T> using RemoveConst = typename RemoveConst_<T>::Type;
|
cannam@49
|
318
|
cannam@49
|
319 template <typename> struct IsLvalueReference_ { static constexpr bool value = false; };
|
cannam@49
|
320 template <typename T> struct IsLvalueReference_<T&> { static constexpr bool value = true; };
|
cannam@49
|
321 template <typename T>
|
cannam@49
|
322 inline constexpr bool isLvalueReference() { return IsLvalueReference_<T>::value; }
|
cannam@49
|
323
|
cannam@49
|
324 template <typename T> struct Decay_ { typedef T Type; };
|
cannam@49
|
325 template <typename T> struct Decay_<T&> { typedef typename Decay_<T>::Type Type; };
|
cannam@49
|
326 template <typename T> struct Decay_<T&&> { typedef typename Decay_<T>::Type Type; };
|
cannam@49
|
327 template <typename T> struct Decay_<T[]> { typedef typename Decay_<T*>::Type Type; };
|
cannam@49
|
328 template <typename T> struct Decay_<const T[]> { typedef typename Decay_<const T*>::Type Type; };
|
cannam@49
|
329 template <typename T, size_t s> struct Decay_<T[s]> { typedef typename Decay_<T*>::Type Type; };
|
cannam@49
|
330 template <typename T, size_t s> struct Decay_<const T[s]> { typedef typename Decay_<const T*>::Type Type; };
|
cannam@49
|
331 template <typename T> struct Decay_<const T> { typedef typename Decay_<T>::Type Type; };
|
cannam@49
|
332 template <typename T> struct Decay_<volatile T> { typedef typename Decay_<T>::Type Type; };
|
cannam@49
|
333 template <typename T> using Decay = typename Decay_<T>::Type;
|
cannam@49
|
334
|
cannam@49
|
335 template <bool b> struct EnableIf_;
|
cannam@49
|
336 template <> struct EnableIf_<true> { typedef void Type; };
|
cannam@49
|
337 template <bool b> using EnableIf = typename EnableIf_<b>::Type;
|
cannam@49
|
338 // Use like:
|
cannam@49
|
339 //
|
cannam@49
|
340 // template <typename T, typename = EnableIf<isValid<T>()>
|
cannam@49
|
341 // void func(T&& t);
|
cannam@49
|
342
|
cannam@49
|
343 template <typename...> struct VoidSfinae_ { using Type = void; };
|
cannam@49
|
344 template <typename... Ts> using VoidSfinae = typename VoidSfinae_<Ts...>::Type;
|
cannam@49
|
345 // Note: VoidSfinae is std::void_t from C++17.
|
cannam@49
|
346
|
cannam@49
|
347 template <typename T>
|
cannam@49
|
348 T instance() noexcept;
|
cannam@49
|
349 // Like std::declval, but doesn't transform T into an rvalue reference. If you want that, specify
|
cannam@49
|
350 // instance<T&&>().
|
cannam@49
|
351
|
cannam@49
|
352 struct DisallowConstCopy {
|
cannam@49
|
353 // Inherit from this, or declare a member variable of this type, to prevent the class from being
|
cannam@49
|
354 // copyable from a const reference -- instead, it will only be copyable from non-const references.
|
cannam@49
|
355 // This is useful for enforcing transitive constness of contained pointers.
|
cannam@49
|
356 //
|
cannam@49
|
357 // For example, say you have a type T which contains a pointer. T has non-const methods which
|
cannam@49
|
358 // modify the value at that pointer, but T's const methods are designed to allow reading only.
|
cannam@49
|
359 // Unfortunately, if T has a regular copy constructor, someone can simply make a copy of T and
|
cannam@49
|
360 // then use it to modify the pointed-to value. However, if T inherits DisallowConstCopy, then
|
cannam@49
|
361 // callers will only be able to copy non-const instances of T. Ideally, there is some
|
cannam@49
|
362 // parallel type ImmutableT which is like a version of T that only has const methods, and can
|
cannam@49
|
363 // be copied from a const T.
|
cannam@49
|
364 //
|
cannam@49
|
365 // Note that due to C++ rules about implicit copy constructors and assignment operators, any
|
cannam@49
|
366 // type that contains or inherits from a type that disallows const copies will also automatically
|
cannam@49
|
367 // disallow const copies. Hey, cool, that's exactly what we want.
|
cannam@49
|
368
|
cannam@49
|
369 DisallowConstCopy() = default;
|
cannam@49
|
370 DisallowConstCopy(DisallowConstCopy&) = default;
|
cannam@49
|
371 DisallowConstCopy(DisallowConstCopy&&) = default;
|
cannam@49
|
372 DisallowConstCopy& operator=(DisallowConstCopy&) = default;
|
cannam@49
|
373 DisallowConstCopy& operator=(DisallowConstCopy&&) = default;
|
cannam@49
|
374 };
|
cannam@49
|
375
|
cannam@49
|
376 template <typename T>
|
cannam@49
|
377 struct DisallowConstCopyIfNotConst: public DisallowConstCopy {
|
cannam@49
|
378 // Inherit from this when implementing a template that contains a pointer to T and which should
|
cannam@49
|
379 // enforce transitive constness. If T is a const type, this has no effect. Otherwise, it is
|
cannam@49
|
380 // an alias for DisallowConstCopy.
|
cannam@49
|
381 };
|
cannam@49
|
382
|
cannam@49
|
383 template <typename T>
|
cannam@49
|
384 struct DisallowConstCopyIfNotConst<const T> {};
|
cannam@49
|
385
|
cannam@49
|
386 template <typename T> struct IsConst_ { static constexpr bool value = false; };
|
cannam@49
|
387 template <typename T> struct IsConst_<const T> { static constexpr bool value = true; };
|
cannam@49
|
388 template <typename T> constexpr bool isConst() { return IsConst_<T>::value; }
|
cannam@49
|
389
|
cannam@49
|
390 template <typename T> struct EnableIfNotConst_ { typedef T Type; };
|
cannam@49
|
391 template <typename T> struct EnableIfNotConst_<const T>;
|
cannam@49
|
392 template <typename T> using EnableIfNotConst = typename EnableIfNotConst_<T>::Type;
|
cannam@49
|
393
|
cannam@49
|
394 template <typename T> struct EnableIfConst_;
|
cannam@49
|
395 template <typename T> struct EnableIfConst_<const T> { typedef T Type; };
|
cannam@49
|
396 template <typename T> using EnableIfConst = typename EnableIfConst_<T>::Type;
|
cannam@49
|
397
|
cannam@49
|
398 template <typename T> struct RemoveConstOrDisable_ { struct Type; };
|
cannam@49
|
399 template <typename T> struct RemoveConstOrDisable_<const T> { typedef T Type; };
|
cannam@49
|
400 template <typename T> using RemoveConstOrDisable = typename RemoveConstOrDisable_<T>::Type;
|
cannam@49
|
401
|
cannam@49
|
402 template <typename T> struct IsReference_ { static constexpr bool value = false; };
|
cannam@49
|
403 template <typename T> struct IsReference_<T&> { static constexpr bool value = true; };
|
cannam@49
|
404 template <typename T> constexpr bool isReference() { return IsReference_<T>::value; }
|
cannam@49
|
405
|
cannam@49
|
406 template <typename From, typename To>
|
cannam@49
|
407 struct PropagateConst_ { typedef To Type; };
|
cannam@49
|
408 template <typename From, typename To>
|
cannam@49
|
409 struct PropagateConst_<const From, To> { typedef const To Type; };
|
cannam@49
|
410 template <typename From, typename To>
|
cannam@49
|
411 using PropagateConst = typename PropagateConst_<From, To>::Type;
|
cannam@49
|
412
|
cannam@49
|
413 namespace _ { // private
|
cannam@49
|
414
|
cannam@49
|
415 template <typename T>
|
cannam@49
|
416 T refIfLvalue(T&&);
|
cannam@49
|
417
|
cannam@49
|
418 } // namespace _ (private)
|
cannam@49
|
419
|
cannam@49
|
420 #define KJ_DECLTYPE_REF(exp) decltype(::kj::_::refIfLvalue(exp))
|
cannam@49
|
421 // Like decltype(exp), but if exp is an lvalue, produces a reference type.
|
cannam@49
|
422 //
|
cannam@49
|
423 // int i;
|
cannam@49
|
424 // decltype(i) i1(i); // i1 has type int.
|
cannam@49
|
425 // KJ_DECLTYPE_REF(i + 1) i2(i + 1); // i2 has type int.
|
cannam@49
|
426 // KJ_DECLTYPE_REF(i) i3(i); // i3 has type int&.
|
cannam@49
|
427 // KJ_DECLTYPE_REF(kj::mv(i)) i4(kj::mv(i)); // i4 has type int.
|
cannam@49
|
428
|
cannam@49
|
429 template <typename T>
|
cannam@49
|
430 struct CanConvert_ {
|
cannam@49
|
431 static int sfinae(T);
|
cannam@49
|
432 static bool sfinae(...);
|
cannam@49
|
433 };
|
cannam@49
|
434
|
cannam@49
|
435 template <typename T, typename U>
|
cannam@49
|
436 constexpr bool canConvert() {
|
cannam@49
|
437 return sizeof(CanConvert_<U>::sfinae(instance<T>())) == sizeof(int);
|
cannam@49
|
438 }
|
cannam@49
|
439
|
cannam@49
|
440 #if __clang__
|
cannam@49
|
441 template <typename T>
|
cannam@49
|
442 constexpr bool canMemcpy() {
|
cannam@49
|
443 // Returns true if T can be copied using memcpy instead of using the copy constructor or
|
cannam@49
|
444 // assignment operator.
|
cannam@49
|
445
|
cannam@49
|
446 // Clang unhelpfully defines __has_trivial_{copy,assign}(T) to be true if the copy constructor /
|
cannam@49
|
447 // assign operator are deleted, on the basis that a strict reading of the definition of "trivial"
|
cannam@49
|
448 // according to the standard says that deleted functions are in fact trivial. Meanwhile Clang
|
cannam@49
|
449 // provides these admittedly-better intrinsics, but GCC does not.
|
cannam@49
|
450 return __is_trivially_constructible(T, const T&) && __is_trivially_assignable(T, const T&);
|
cannam@49
|
451 }
|
cannam@49
|
452 #else
|
cannam@49
|
453 template <typename T>
|
cannam@49
|
454 constexpr bool canMemcpy() {
|
cannam@49
|
455 // Returns true if T can be copied using memcpy instead of using the copy constructor or
|
cannam@49
|
456 // assignment operator.
|
cannam@49
|
457
|
cannam@49
|
458 // GCC defines these to mean what we want them to mean.
|
cannam@49
|
459 return __has_trivial_copy(T) && __has_trivial_assign(T);
|
cannam@49
|
460 }
|
cannam@49
|
461 #endif
|
cannam@49
|
462
|
cannam@49
|
463 // =======================================================================================
|
cannam@49
|
464 // Equivalents to std::move() and std::forward(), since these are very commonly needed and the
|
cannam@49
|
465 // std header <utility> pulls in lots of other stuff.
|
cannam@49
|
466 //
|
cannam@49
|
467 // We use abbreviated names mv and fwd because these helpers (especially mv) are so commonly used
|
cannam@49
|
468 // that the cost of typing more letters outweighs the cost of being slightly harder to understand
|
cannam@49
|
469 // when first encountered.
|
cannam@49
|
470
|
cannam@49
|
471 template<typename T> constexpr T&& mv(T& t) noexcept { return static_cast<T&&>(t); }
|
cannam@49
|
472 template<typename T> constexpr T&& fwd(NoInfer<T>& t) noexcept { return static_cast<T&&>(t); }
|
cannam@49
|
473
|
cannam@49
|
474 template<typename T> constexpr T cp(T& t) noexcept { return t; }
|
cannam@49
|
475 template<typename T> constexpr T cp(const T& t) noexcept { return t; }
|
cannam@49
|
476 // Useful to force a copy, particularly to pass into a function that expects T&&.
|
cannam@49
|
477
|
cannam@49
|
478 template <typename T, typename U, bool takeT> struct MinType_;
|
cannam@49
|
479 template <typename T, typename U> struct MinType_<T, U, true> { typedef T Type; };
|
cannam@49
|
480 template <typename T, typename U> struct MinType_<T, U, false> { typedef U Type; };
|
cannam@49
|
481
|
cannam@49
|
482 template <typename T, typename U>
|
cannam@49
|
483 using MinType = typename MinType_<T, U, sizeof(T) <= sizeof(U)>::Type;
|
cannam@49
|
484 // Resolves to the smaller of the two input types.
|
cannam@49
|
485
|
cannam@49
|
486 template <typename T, typename U>
|
cannam@49
|
487 inline constexpr auto min(T&& a, U&& b) -> MinType<Decay<T>, Decay<U>> {
|
cannam@49
|
488 return a < b ? MinType<Decay<T>, Decay<U>>(a) : MinType<Decay<T>, Decay<U>>(b);
|
cannam@49
|
489 }
|
cannam@49
|
490
|
cannam@49
|
491 template <typename T, typename U, bool takeT> struct MaxType_;
|
cannam@49
|
492 template <typename T, typename U> struct MaxType_<T, U, true> { typedef T Type; };
|
cannam@49
|
493 template <typename T, typename U> struct MaxType_<T, U, false> { typedef U Type; };
|
cannam@49
|
494
|
cannam@49
|
495 template <typename T, typename U>
|
cannam@49
|
496 using MaxType = typename MaxType_<T, U, sizeof(T) >= sizeof(U)>::Type;
|
cannam@49
|
497 // Resolves to the larger of the two input types.
|
cannam@49
|
498
|
cannam@49
|
499 template <typename T, typename U>
|
cannam@49
|
500 inline constexpr auto max(T&& a, U&& b) -> MaxType<Decay<T>, Decay<U>> {
|
cannam@49
|
501 return a > b ? MaxType<Decay<T>, Decay<U>>(a) : MaxType<Decay<T>, Decay<U>>(b);
|
cannam@49
|
502 }
|
cannam@49
|
503
|
cannam@49
|
504 template <typename T, size_t s>
|
cannam@49
|
505 inline constexpr size_t size(T (&arr)[s]) { return s; }
|
cannam@49
|
506 template <typename T>
|
cannam@49
|
507 inline constexpr size_t size(T&& arr) { return arr.size(); }
|
cannam@49
|
508 // Returns the size of the parameter, whether the parameter is a regular C array or a container
|
cannam@49
|
509 // with a `.size()` method.
|
cannam@49
|
510
|
cannam@49
|
511 class MaxValue_ {
|
cannam@49
|
512 private:
|
cannam@49
|
513 template <typename T>
|
cannam@49
|
514 inline constexpr T maxSigned() const {
|
cannam@49
|
515 return (1ull << (sizeof(T) * 8 - 1)) - 1;
|
cannam@49
|
516 }
|
cannam@49
|
517 template <typename T>
|
cannam@49
|
518 inline constexpr T maxUnsigned() const {
|
cannam@49
|
519 return ~static_cast<T>(0u);
|
cannam@49
|
520 }
|
cannam@49
|
521
|
cannam@49
|
522 public:
|
cannam@49
|
523 #define _kJ_HANDLE_TYPE(T) \
|
cannam@49
|
524 inline constexpr operator signed T() const { return MaxValue_::maxSigned < signed T>(); } \
|
cannam@49
|
525 inline constexpr operator unsigned T() const { return MaxValue_::maxUnsigned<unsigned T>(); }
|
cannam@49
|
526 _kJ_HANDLE_TYPE(char)
|
cannam@49
|
527 _kJ_HANDLE_TYPE(short)
|
cannam@49
|
528 _kJ_HANDLE_TYPE(int)
|
cannam@49
|
529 _kJ_HANDLE_TYPE(long)
|
cannam@49
|
530 _kJ_HANDLE_TYPE(long long)
|
cannam@49
|
531 #undef _kJ_HANDLE_TYPE
|
cannam@49
|
532
|
cannam@49
|
533 inline constexpr operator char() const {
|
cannam@49
|
534 // `char` is different from both `signed char` and `unsigned char`, and may be signed or
|
cannam@49
|
535 // unsigned on different platforms. Ugh.
|
cannam@49
|
536 return char(-1) < 0 ? MaxValue_::maxSigned<char>()
|
cannam@49
|
537 : MaxValue_::maxUnsigned<char>();
|
cannam@49
|
538 }
|
cannam@49
|
539 };
|
cannam@49
|
540
|
cannam@49
|
541 class MinValue_ {
|
cannam@49
|
542 private:
|
cannam@49
|
543 template <typename T>
|
cannam@49
|
544 inline constexpr T minSigned() const {
|
cannam@49
|
545 return 1ull << (sizeof(T) * 8 - 1);
|
cannam@49
|
546 }
|
cannam@49
|
547 template <typename T>
|
cannam@49
|
548 inline constexpr T minUnsigned() const {
|
cannam@49
|
549 return 0u;
|
cannam@49
|
550 }
|
cannam@49
|
551
|
cannam@49
|
552 public:
|
cannam@49
|
553 #define _kJ_HANDLE_TYPE(T) \
|
cannam@49
|
554 inline constexpr operator signed T() const { return MinValue_::minSigned < signed T>(); } \
|
cannam@49
|
555 inline constexpr operator unsigned T() const { return MinValue_::minUnsigned<unsigned T>(); }
|
cannam@49
|
556 _kJ_HANDLE_TYPE(char)
|
cannam@49
|
557 _kJ_HANDLE_TYPE(short)
|
cannam@49
|
558 _kJ_HANDLE_TYPE(int)
|
cannam@49
|
559 _kJ_HANDLE_TYPE(long)
|
cannam@49
|
560 _kJ_HANDLE_TYPE(long long)
|
cannam@49
|
561 #undef _kJ_HANDLE_TYPE
|
cannam@49
|
562
|
cannam@49
|
563 inline constexpr operator char() const {
|
cannam@49
|
564 // `char` is different from both `signed char` and `unsigned char`, and may be signed or
|
cannam@49
|
565 // unsigned on different platforms. Ugh.
|
cannam@49
|
566 return char(-1) < 0 ? MinValue_::minSigned<char>()
|
cannam@49
|
567 : MinValue_::minUnsigned<char>();
|
cannam@49
|
568 }
|
cannam@49
|
569 };
|
cannam@49
|
570
|
cannam@49
|
571 static KJ_CONSTEXPR(const) MaxValue_ maxValue = MaxValue_();
|
cannam@49
|
572 // A special constant which, when cast to an integer type, takes on the maximum possible value of
|
cannam@49
|
573 // that type. This is useful to use as e.g. a parameter to a function because it will be robust
|
cannam@49
|
574 // in the face of changes to the parameter's type.
|
cannam@49
|
575 //
|
cannam@49
|
576 // `char` is not supported, but `signed char` and `unsigned char` are.
|
cannam@49
|
577
|
cannam@49
|
578 static KJ_CONSTEXPR(const) MinValue_ minValue = MinValue_();
|
cannam@49
|
579 // A special constant which, when cast to an integer type, takes on the minimum possible value
|
cannam@49
|
580 // of that type. This is useful to use as e.g. a parameter to a function because it will be robust
|
cannam@49
|
581 // in the face of changes to the parameter's type.
|
cannam@49
|
582 //
|
cannam@49
|
583 // `char` is not supported, but `signed char` and `unsigned char` are.
|
cannam@49
|
584
|
cannam@49
|
585 #if __GNUC__
|
cannam@49
|
586 inline constexpr float inf() { return __builtin_huge_valf(); }
|
cannam@49
|
587 inline constexpr float nan() { return __builtin_nanf(""); }
|
cannam@49
|
588
|
cannam@49
|
589 #elif _MSC_VER
|
cannam@49
|
590
|
cannam@49
|
591 // Do what MSVC math.h does
|
cannam@49
|
592 #pragma warning(push)
|
cannam@49
|
593 #pragma warning(disable: 4756) // "overflow in constant arithmetic"
|
cannam@49
|
594 inline constexpr float inf() { return (float)(1e300 * 1e300); }
|
cannam@49
|
595 #pragma warning(pop)
|
cannam@49
|
596
|
cannam@49
|
597 float nan();
|
cannam@49
|
598 // Unfortunatley, inf() * 0.0f produces a NaN with the sign bit set, whereas our preferred
|
cannam@49
|
599 // canonical NaN should not have the sign bit set. std::numeric_limits<float>::quiet_NaN()
|
cannam@49
|
600 // returns the correct NaN, but we don't want to #include that here. So, we give up and make
|
cannam@49
|
601 // this out-of-line on MSVC.
|
cannam@49
|
602 //
|
cannam@49
|
603 // TODO(msvc): Can we do better?
|
cannam@49
|
604
|
cannam@49
|
605 #else
|
cannam@49
|
606 #error "Not sure how to support your compiler."
|
cannam@49
|
607 #endif
|
cannam@49
|
608
|
cannam@49
|
609 inline constexpr bool isNaN(float f) { return f != f; }
|
cannam@49
|
610 inline constexpr bool isNaN(double f) { return f != f; }
|
cannam@49
|
611
|
cannam@49
|
612 inline int popCount(unsigned int x) {
|
cannam@49
|
613 #if defined(_MSC_VER)
|
cannam@49
|
614 return __popcnt(x);
|
cannam@49
|
615 // Note: __popcnt returns unsigned int, but the value is clearly guaranteed to fit into an int
|
cannam@49
|
616 #else
|
cannam@49
|
617 return __builtin_popcount(x);
|
cannam@49
|
618 #endif
|
cannam@49
|
619 }
|
cannam@49
|
620
|
cannam@49
|
621 // =======================================================================================
|
cannam@49
|
622 // Useful fake containers
|
cannam@49
|
623
|
cannam@49
|
624 template <typename T>
|
cannam@49
|
625 class Range {
|
cannam@49
|
626 public:
|
cannam@49
|
627 inline constexpr Range(const T& begin, const T& end): begin_(begin), end_(end) {}
|
cannam@49
|
628
|
cannam@49
|
629 class Iterator {
|
cannam@49
|
630 public:
|
cannam@49
|
631 Iterator() = default;
|
cannam@49
|
632 inline Iterator(const T& value): value(value) {}
|
cannam@49
|
633
|
cannam@49
|
634 inline const T& operator* () const { return value; }
|
cannam@49
|
635 inline const T& operator[](size_t index) const { return value + index; }
|
cannam@49
|
636 inline Iterator& operator++() { ++value; return *this; }
|
cannam@49
|
637 inline Iterator operator++(int) { return Iterator(value++); }
|
cannam@49
|
638 inline Iterator& operator--() { --value; return *this; }
|
cannam@49
|
639 inline Iterator operator--(int) { return Iterator(value--); }
|
cannam@49
|
640 inline Iterator& operator+=(ptrdiff_t amount) { value += amount; return *this; }
|
cannam@49
|
641 inline Iterator& operator-=(ptrdiff_t amount) { value -= amount; return *this; }
|
cannam@49
|
642 inline Iterator operator+ (ptrdiff_t amount) const { return Iterator(value + amount); }
|
cannam@49
|
643 inline Iterator operator- (ptrdiff_t amount) const { return Iterator(value - amount); }
|
cannam@49
|
644 inline ptrdiff_t operator- (const Iterator& other) const { return value - other.value; }
|
cannam@49
|
645
|
cannam@49
|
646 inline bool operator==(const Iterator& other) const { return value == other.value; }
|
cannam@49
|
647 inline bool operator!=(const Iterator& other) const { return value != other.value; }
|
cannam@49
|
648 inline bool operator<=(const Iterator& other) const { return value <= other.value; }
|
cannam@49
|
649 inline bool operator>=(const Iterator& other) const { return value >= other.value; }
|
cannam@49
|
650 inline bool operator< (const Iterator& other) const { return value < other.value; }
|
cannam@49
|
651 inline bool operator> (const Iterator& other) const { return value > other.value; }
|
cannam@49
|
652
|
cannam@49
|
653 private:
|
cannam@49
|
654 T value;
|
cannam@49
|
655 };
|
cannam@49
|
656
|
cannam@49
|
657 inline Iterator begin() const { return Iterator(begin_); }
|
cannam@49
|
658 inline Iterator end() const { return Iterator(end_); }
|
cannam@49
|
659
|
cannam@49
|
660 inline auto size() const -> decltype(instance<T>() - instance<T>()) { return end_ - begin_; }
|
cannam@49
|
661
|
cannam@49
|
662 private:
|
cannam@49
|
663 T begin_;
|
cannam@49
|
664 T end_;
|
cannam@49
|
665 };
|
cannam@49
|
666
|
cannam@49
|
667 template <typename T>
|
cannam@49
|
668 inline constexpr Range<Decay<T>> range(T begin, T end) { return Range<Decay<T>>(begin, end); }
|
cannam@49
|
669 // Returns a fake iterable container containing all values of T from `begin` (inclusive) to `end`
|
cannam@49
|
670 // (exclusive). Example:
|
cannam@49
|
671 //
|
cannam@49
|
672 // // Prints 1, 2, 3, 4, 5, 6, 7, 8, 9.
|
cannam@49
|
673 // for (int i: kj::range(1, 10)) { print(i); }
|
cannam@49
|
674
|
cannam@49
|
675 template <typename T>
|
cannam@49
|
676 inline constexpr Range<size_t> indices(T&& container) {
|
cannam@49
|
677 // Shortcut for iterating over the indices of a container:
|
cannam@49
|
678 //
|
cannam@49
|
679 // for (size_t i: kj::indices(myArray)) { handle(myArray[i]); }
|
cannam@49
|
680
|
cannam@49
|
681 return range<size_t>(0, kj::size(container));
|
cannam@49
|
682 }
|
cannam@49
|
683
|
cannam@49
|
684 template <typename T>
|
cannam@49
|
685 class Repeat {
|
cannam@49
|
686 public:
|
cannam@49
|
687 inline constexpr Repeat(const T& value, size_t count): value(value), count(count) {}
|
cannam@49
|
688
|
cannam@49
|
689 class Iterator {
|
cannam@49
|
690 public:
|
cannam@49
|
691 Iterator() = default;
|
cannam@49
|
692 inline Iterator(const T& value, size_t index): value(value), index(index) {}
|
cannam@49
|
693
|
cannam@49
|
694 inline const T& operator* () const { return value; }
|
cannam@49
|
695 inline const T& operator[](ptrdiff_t index) const { return value; }
|
cannam@49
|
696 inline Iterator& operator++() { ++index; return *this; }
|
cannam@49
|
697 inline Iterator operator++(int) { return Iterator(value, index++); }
|
cannam@49
|
698 inline Iterator& operator--() { --index; return *this; }
|
cannam@49
|
699 inline Iterator operator--(int) { return Iterator(value, index--); }
|
cannam@49
|
700 inline Iterator& operator+=(ptrdiff_t amount) { index += amount; return *this; }
|
cannam@49
|
701 inline Iterator& operator-=(ptrdiff_t amount) { index -= amount; return *this; }
|
cannam@49
|
702 inline Iterator operator+ (ptrdiff_t amount) const { return Iterator(value, index + amount); }
|
cannam@49
|
703 inline Iterator operator- (ptrdiff_t amount) const { return Iterator(value, index - amount); }
|
cannam@49
|
704 inline ptrdiff_t operator- (const Iterator& other) const { return index - other.index; }
|
cannam@49
|
705
|
cannam@49
|
706 inline bool operator==(const Iterator& other) const { return index == other.index; }
|
cannam@49
|
707 inline bool operator!=(const Iterator& other) const { return index != other.index; }
|
cannam@49
|
708 inline bool operator<=(const Iterator& other) const { return index <= other.index; }
|
cannam@49
|
709 inline bool operator>=(const Iterator& other) const { return index >= other.index; }
|
cannam@49
|
710 inline bool operator< (const Iterator& other) const { return index < other.index; }
|
cannam@49
|
711 inline bool operator> (const Iterator& other) const { return index > other.index; }
|
cannam@49
|
712
|
cannam@49
|
713 private:
|
cannam@49
|
714 T value;
|
cannam@49
|
715 size_t index;
|
cannam@49
|
716 };
|
cannam@49
|
717
|
cannam@49
|
718 inline Iterator begin() const { return Iterator(value, 0); }
|
cannam@49
|
719 inline Iterator end() const { return Iterator(value, count); }
|
cannam@49
|
720
|
cannam@49
|
721 inline size_t size() const { return count; }
|
cannam@49
|
722
|
cannam@49
|
723 private:
|
cannam@49
|
724 T value;
|
cannam@49
|
725 size_t count;
|
cannam@49
|
726 };
|
cannam@49
|
727
|
cannam@49
|
728 template <typename T>
|
cannam@49
|
729 inline constexpr Repeat<Decay<T>> repeat(T&& value, size_t count) {
|
cannam@49
|
730 // Returns a fake iterable which contains `count` repeats of `value`. Useful for e.g. creating
|
cannam@49
|
731 // a bunch of spaces: `kj::repeat(' ', indent * 2)`
|
cannam@49
|
732
|
cannam@49
|
733 return Repeat<Decay<T>>(value, count);
|
cannam@49
|
734 }
|
cannam@49
|
735
|
cannam@49
|
736 // =======================================================================================
|
cannam@49
|
737 // Manually invoking constructors and destructors
|
cannam@49
|
738 //
|
cannam@49
|
739 // ctor(x, ...) and dtor(x) invoke x's constructor or destructor, respectively.
|
cannam@49
|
740
|
cannam@49
|
741 // We want placement new, but we don't want to #include <new>. operator new cannot be defined in
|
cannam@49
|
742 // a namespace, and defining it globally conflicts with the definition in <new>. So we have to
|
cannam@49
|
743 // define a dummy type and an operator new that uses it.
|
cannam@49
|
744
|
cannam@49
|
745 namespace _ { // private
|
cannam@49
|
746 struct PlacementNew {};
|
cannam@49
|
747 } // namespace _ (private)
|
cannam@49
|
748 } // namespace kj
|
cannam@49
|
749
|
cannam@49
|
750 inline void* operator new(size_t, kj::_::PlacementNew, void* __p) noexcept {
|
cannam@49
|
751 return __p;
|
cannam@49
|
752 }
|
cannam@49
|
753
|
cannam@49
|
754 inline void operator delete(void*, kj::_::PlacementNew, void* __p) noexcept {}
|
cannam@49
|
755
|
cannam@49
|
756 namespace kj {
|
cannam@49
|
757
|
cannam@49
|
758 template <typename T, typename... Params>
|
cannam@49
|
759 inline void ctor(T& location, Params&&... params) {
|
cannam@49
|
760 new (_::PlacementNew(), &location) T(kj::fwd<Params>(params)...);
|
cannam@49
|
761 }
|
cannam@49
|
762
|
cannam@49
|
763 template <typename T>
|
cannam@49
|
764 inline void dtor(T& location) {
|
cannam@49
|
765 location.~T();
|
cannam@49
|
766 }
|
cannam@49
|
767
|
cannam@49
|
768 // =======================================================================================
|
cannam@49
|
769 // Maybe
|
cannam@49
|
770 //
|
cannam@49
|
771 // Use in cases where you want to indicate that a value may be null. Using Maybe<T&> instead of T*
|
cannam@49
|
772 // forces the caller to handle the null case in order to satisfy the compiler, thus reliably
|
cannam@49
|
773 // preventing null pointer dereferences at runtime.
|
cannam@49
|
774 //
|
cannam@49
|
775 // Maybe<T> can be implicitly constructed from T and from nullptr. Additionally, it can be
|
cannam@49
|
776 // implicitly constructed from T*, in which case the pointer is checked for nullness at runtime.
|
cannam@49
|
777 // To read the value of a Maybe<T>, do:
|
cannam@49
|
778 //
|
cannam@49
|
779 // KJ_IF_MAYBE(value, someFuncReturningMaybe()) {
|
cannam@49
|
780 // doSomething(*value);
|
cannam@49
|
781 // } else {
|
cannam@49
|
782 // maybeWasNull();
|
cannam@49
|
783 // }
|
cannam@49
|
784 //
|
cannam@49
|
785 // KJ_IF_MAYBE's first parameter is a variable name which will be defined within the following
|
cannam@49
|
786 // block. The variable will behave like a (guaranteed non-null) pointer to the Maybe's value,
|
cannam@49
|
787 // though it may or may not actually be a pointer.
|
cannam@49
|
788 //
|
cannam@49
|
789 // Note that Maybe<T&> actually just wraps a pointer, whereas Maybe<T> wraps a T and a boolean
|
cannam@49
|
790 // indicating nullness.
|
cannam@49
|
791
|
cannam@49
|
792 template <typename T>
|
cannam@49
|
793 class Maybe;
|
cannam@49
|
794
|
cannam@49
|
795 namespace _ { // private
|
cannam@49
|
796
|
cannam@49
|
797 #if _MSC_VER
|
cannam@49
|
798 // TODO(msvc): MSVC barfs on noexcept(instance<T&>().~T()) where T = kj::Exception and
|
cannam@49
|
799 // kj::_::Void. It and every other factorization I've tried produces:
|
cannam@49
|
800 // error C2325: 'kj::Blah' unexpected type to the right of '.~': expected 'void'
|
cannam@49
|
801 #define MSVC_NOEXCEPT_DTOR_WORKAROUND(T) __is_nothrow_destructible(T)
|
cannam@49
|
802 #else
|
cannam@49
|
803 #define MSVC_NOEXCEPT_DTOR_WORKAROUND(T) noexcept(instance<T&>().~T())
|
cannam@49
|
804 #endif
|
cannam@49
|
805
|
cannam@49
|
806 template <typename T>
|
cannam@49
|
807 class NullableValue {
|
cannam@49
|
808 // Class whose interface behaves much like T*, but actually contains an instance of T and a
|
cannam@49
|
809 // boolean flag indicating nullness.
|
cannam@49
|
810
|
cannam@49
|
811 public:
|
cannam@49
|
812 inline NullableValue(NullableValue&& other) noexcept(noexcept(T(instance<T&&>())))
|
cannam@49
|
813 : isSet(other.isSet) {
|
cannam@49
|
814 if (isSet) {
|
cannam@49
|
815 ctor(value, kj::mv(other.value));
|
cannam@49
|
816 }
|
cannam@49
|
817 }
|
cannam@49
|
818 inline NullableValue(const NullableValue& other)
|
cannam@49
|
819 : isSet(other.isSet) {
|
cannam@49
|
820 if (isSet) {
|
cannam@49
|
821 ctor(value, other.value);
|
cannam@49
|
822 }
|
cannam@49
|
823 }
|
cannam@49
|
824 inline NullableValue(NullableValue& other)
|
cannam@49
|
825 : isSet(other.isSet) {
|
cannam@49
|
826 if (isSet) {
|
cannam@49
|
827 ctor(value, other.value);
|
cannam@49
|
828 }
|
cannam@49
|
829 }
|
cannam@49
|
830 inline ~NullableValue() noexcept(MSVC_NOEXCEPT_DTOR_WORKAROUND(T)) {
|
cannam@49
|
831 if (isSet) {
|
cannam@49
|
832 dtor(value);
|
cannam@49
|
833 }
|
cannam@49
|
834 }
|
cannam@49
|
835
|
cannam@49
|
836 inline T& operator*() & { return value; }
|
cannam@49
|
837 inline const T& operator*() const & { return value; }
|
cannam@49
|
838 inline T&& operator*() && { return kj::mv(value); }
|
cannam@49
|
839 inline const T&& operator*() const && { return kj::mv(value); }
|
cannam@49
|
840 inline T* operator->() { return &value; }
|
cannam@49
|
841 inline const T* operator->() const { return &value; }
|
cannam@49
|
842 inline operator T*() { return isSet ? &value : nullptr; }
|
cannam@49
|
843 inline operator const T*() const { return isSet ? &value : nullptr; }
|
cannam@49
|
844
|
cannam@49
|
845 template <typename... Params>
|
cannam@49
|
846 inline T& emplace(Params&&... params) {
|
cannam@49
|
847 if (isSet) {
|
cannam@49
|
848 isSet = false;
|
cannam@49
|
849 dtor(value);
|
cannam@49
|
850 }
|
cannam@49
|
851 ctor(value, kj::fwd<Params>(params)...);
|
cannam@49
|
852 isSet = true;
|
cannam@49
|
853 return value;
|
cannam@49
|
854 }
|
cannam@49
|
855
|
cannam@49
|
856 private: // internal interface used by friends only
|
cannam@49
|
857 inline NullableValue() noexcept: isSet(false) {}
|
cannam@49
|
858 inline NullableValue(T&& t) noexcept(noexcept(T(instance<T&&>())))
|
cannam@49
|
859 : isSet(true) {
|
cannam@49
|
860 ctor(value, kj::mv(t));
|
cannam@49
|
861 }
|
cannam@49
|
862 inline NullableValue(T& t)
|
cannam@49
|
863 : isSet(true) {
|
cannam@49
|
864 ctor(value, t);
|
cannam@49
|
865 }
|
cannam@49
|
866 inline NullableValue(const T& t)
|
cannam@49
|
867 : isSet(true) {
|
cannam@49
|
868 ctor(value, t);
|
cannam@49
|
869 }
|
cannam@49
|
870 inline NullableValue(const T* t)
|
cannam@49
|
871 : isSet(t != nullptr) {
|
cannam@49
|
872 if (isSet) ctor(value, *t);
|
cannam@49
|
873 }
|
cannam@49
|
874 template <typename U>
|
cannam@49
|
875 inline NullableValue(NullableValue<U>&& other) noexcept(noexcept(T(instance<U&&>())))
|
cannam@49
|
876 : isSet(other.isSet) {
|
cannam@49
|
877 if (isSet) {
|
cannam@49
|
878 ctor(value, kj::mv(other.value));
|
cannam@49
|
879 }
|
cannam@49
|
880 }
|
cannam@49
|
881 template <typename U>
|
cannam@49
|
882 inline NullableValue(const NullableValue<U>& other)
|
cannam@49
|
883 : isSet(other.isSet) {
|
cannam@49
|
884 if (isSet) {
|
cannam@49
|
885 ctor(value, other.value);
|
cannam@49
|
886 }
|
cannam@49
|
887 }
|
cannam@49
|
888 template <typename U>
|
cannam@49
|
889 inline NullableValue(const NullableValue<U&>& other)
|
cannam@49
|
890 : isSet(other.isSet) {
|
cannam@49
|
891 if (isSet) {
|
cannam@49
|
892 ctor(value, *other.ptr);
|
cannam@49
|
893 }
|
cannam@49
|
894 }
|
cannam@49
|
895 inline NullableValue(decltype(nullptr)): isSet(false) {}
|
cannam@49
|
896
|
cannam@49
|
897 inline NullableValue& operator=(NullableValue&& other) {
|
cannam@49
|
898 if (&other != this) {
|
cannam@49
|
899 // Careful about throwing destructors/constructors here.
|
cannam@49
|
900 if (isSet) {
|
cannam@49
|
901 isSet = false;
|
cannam@49
|
902 dtor(value);
|
cannam@49
|
903 }
|
cannam@49
|
904 if (other.isSet) {
|
cannam@49
|
905 ctor(value, kj::mv(other.value));
|
cannam@49
|
906 isSet = true;
|
cannam@49
|
907 }
|
cannam@49
|
908 }
|
cannam@49
|
909 return *this;
|
cannam@49
|
910 }
|
cannam@49
|
911
|
cannam@49
|
912 inline NullableValue& operator=(NullableValue& other) {
|
cannam@49
|
913 if (&other != this) {
|
cannam@49
|
914 // Careful about throwing destructors/constructors here.
|
cannam@49
|
915 if (isSet) {
|
cannam@49
|
916 isSet = false;
|
cannam@49
|
917 dtor(value);
|
cannam@49
|
918 }
|
cannam@49
|
919 if (other.isSet) {
|
cannam@49
|
920 ctor(value, other.value);
|
cannam@49
|
921 isSet = true;
|
cannam@49
|
922 }
|
cannam@49
|
923 }
|
cannam@49
|
924 return *this;
|
cannam@49
|
925 }
|
cannam@49
|
926
|
cannam@49
|
927 inline NullableValue& operator=(const NullableValue& other) {
|
cannam@49
|
928 if (&other != this) {
|
cannam@49
|
929 // Careful about throwing destructors/constructors here.
|
cannam@49
|
930 if (isSet) {
|
cannam@49
|
931 isSet = false;
|
cannam@49
|
932 dtor(value);
|
cannam@49
|
933 }
|
cannam@49
|
934 if (other.isSet) {
|
cannam@49
|
935 ctor(value, other.value);
|
cannam@49
|
936 isSet = true;
|
cannam@49
|
937 }
|
cannam@49
|
938 }
|
cannam@49
|
939 return *this;
|
cannam@49
|
940 }
|
cannam@49
|
941
|
cannam@49
|
942 inline bool operator==(decltype(nullptr)) const { return !isSet; }
|
cannam@49
|
943 inline bool operator!=(decltype(nullptr)) const { return isSet; }
|
cannam@49
|
944
|
cannam@49
|
945 private:
|
cannam@49
|
946 bool isSet;
|
cannam@49
|
947
|
cannam@49
|
948 #if _MSC_VER
|
cannam@49
|
949 #pragma warning(push)
|
cannam@49
|
950 #pragma warning(disable: 4624)
|
cannam@49
|
951 // Warns that the anonymous union has a deleted destructor when T is non-trivial. This warning
|
cannam@49
|
952 // seems broken.
|
cannam@49
|
953 #endif
|
cannam@49
|
954
|
cannam@49
|
955 union {
|
cannam@49
|
956 T value;
|
cannam@49
|
957 };
|
cannam@49
|
958
|
cannam@49
|
959 #if _MSC_VER
|
cannam@49
|
960 #pragma warning(pop)
|
cannam@49
|
961 #endif
|
cannam@49
|
962
|
cannam@49
|
963 friend class kj::Maybe<T>;
|
cannam@49
|
964 template <typename U>
|
cannam@49
|
965 friend NullableValue<U>&& readMaybe(Maybe<U>&& maybe);
|
cannam@49
|
966 };
|
cannam@49
|
967
|
cannam@49
|
968 template <typename T>
|
cannam@49
|
969 inline NullableValue<T>&& readMaybe(Maybe<T>&& maybe) { return kj::mv(maybe.ptr); }
|
cannam@49
|
970 template <typename T>
|
cannam@49
|
971 inline T* readMaybe(Maybe<T>& maybe) { return maybe.ptr; }
|
cannam@49
|
972 template <typename T>
|
cannam@49
|
973 inline const T* readMaybe(const Maybe<T>& maybe) { return maybe.ptr; }
|
cannam@49
|
974 template <typename T>
|
cannam@49
|
975 inline T* readMaybe(Maybe<T&>&& maybe) { return maybe.ptr; }
|
cannam@49
|
976 template <typename T>
|
cannam@49
|
977 inline T* readMaybe(const Maybe<T&>& maybe) { return maybe.ptr; }
|
cannam@49
|
978
|
cannam@49
|
979 template <typename T>
|
cannam@49
|
980 inline T* readMaybe(T* ptr) { return ptr; }
|
cannam@49
|
981 // Allow KJ_IF_MAYBE to work on regular pointers.
|
cannam@49
|
982
|
cannam@49
|
983 } // namespace _ (private)
|
cannam@49
|
984
|
cannam@49
|
985 #define KJ_IF_MAYBE(name, exp) if (auto name = ::kj::_::readMaybe(exp))
|
cannam@49
|
986
|
cannam@49
|
987 template <typename T>
|
cannam@49
|
988 class Maybe {
|
cannam@49
|
989 // A T, or nullptr.
|
cannam@49
|
990
|
cannam@49
|
991 // IF YOU CHANGE THIS CLASS: Note that there is a specialization of it in memory.h.
|
cannam@49
|
992
|
cannam@49
|
993 public:
|
cannam@49
|
994 Maybe(): ptr(nullptr) {}
|
cannam@49
|
995 Maybe(T&& t) noexcept(noexcept(T(instance<T&&>()))): ptr(kj::mv(t)) {}
|
cannam@49
|
996 Maybe(T& t): ptr(t) {}
|
cannam@49
|
997 Maybe(const T& t): ptr(t) {}
|
cannam@49
|
998 Maybe(const T* t) noexcept: ptr(t) {}
|
cannam@49
|
999 Maybe(Maybe&& other) noexcept(noexcept(T(instance<T&&>()))): ptr(kj::mv(other.ptr)) {}
|
cannam@49
|
1000 Maybe(const Maybe& other): ptr(other.ptr) {}
|
cannam@49
|
1001 Maybe(Maybe& other): ptr(other.ptr) {}
|
cannam@49
|
1002
|
cannam@49
|
1003 template <typename U>
|
cannam@49
|
1004 Maybe(Maybe<U>&& other) noexcept(noexcept(T(instance<U&&>()))) {
|
cannam@49
|
1005 KJ_IF_MAYBE(val, kj::mv(other)) {
|
cannam@49
|
1006 ptr = *val;
|
cannam@49
|
1007 }
|
cannam@49
|
1008 }
|
cannam@49
|
1009 template <typename U>
|
cannam@49
|
1010 Maybe(const Maybe<U>& other) {
|
cannam@49
|
1011 KJ_IF_MAYBE(val, other) {
|
cannam@49
|
1012 ptr = *val;
|
cannam@49
|
1013 }
|
cannam@49
|
1014 }
|
cannam@49
|
1015
|
cannam@49
|
1016 Maybe(decltype(nullptr)) noexcept: ptr(nullptr) {}
|
cannam@49
|
1017
|
cannam@49
|
1018 template <typename... Params>
|
cannam@49
|
1019 inline T& emplace(Params&&... params) {
|
cannam@49
|
1020 // Replace this Maybe's content with a new value constructed by passing the given parametrs to
|
cannam@49
|
1021 // T's constructor. This can be used to initialize a Maybe without copying or even moving a T.
|
cannam@49
|
1022 // Returns a reference to the newly-constructed value.
|
cannam@49
|
1023
|
cannam@49
|
1024 return ptr.emplace(kj::fwd<Params>(params)...);
|
cannam@49
|
1025 }
|
cannam@49
|
1026
|
cannam@49
|
1027 inline Maybe& operator=(Maybe&& other) { ptr = kj::mv(other.ptr); return *this; }
|
cannam@49
|
1028 inline Maybe& operator=(Maybe& other) { ptr = other.ptr; return *this; }
|
cannam@49
|
1029 inline Maybe& operator=(const Maybe& other) { ptr = other.ptr; return *this; }
|
cannam@49
|
1030
|
cannam@49
|
1031 inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; }
|
cannam@49
|
1032 inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; }
|
cannam@49
|
1033
|
cannam@49
|
1034 T& orDefault(T& defaultValue) {
|
cannam@49
|
1035 if (ptr == nullptr) {
|
cannam@49
|
1036 return defaultValue;
|
cannam@49
|
1037 } else {
|
cannam@49
|
1038 return *ptr;
|
cannam@49
|
1039 }
|
cannam@49
|
1040 }
|
cannam@49
|
1041 const T& orDefault(const T& defaultValue) const {
|
cannam@49
|
1042 if (ptr == nullptr) {
|
cannam@49
|
1043 return defaultValue;
|
cannam@49
|
1044 } else {
|
cannam@49
|
1045 return *ptr;
|
cannam@49
|
1046 }
|
cannam@49
|
1047 }
|
cannam@49
|
1048
|
cannam@49
|
1049 template <typename Func>
|
cannam@49
|
1050 auto map(Func&& f) & -> Maybe<decltype(f(instance<T&>()))> {
|
cannam@49
|
1051 if (ptr == nullptr) {
|
cannam@49
|
1052 return nullptr;
|
cannam@49
|
1053 } else {
|
cannam@49
|
1054 return f(*ptr);
|
cannam@49
|
1055 }
|
cannam@49
|
1056 }
|
cannam@49
|
1057
|
cannam@49
|
1058 template <typename Func>
|
cannam@49
|
1059 auto map(Func&& f) const & -> Maybe<decltype(f(instance<const T&>()))> {
|
cannam@49
|
1060 if (ptr == nullptr) {
|
cannam@49
|
1061 return nullptr;
|
cannam@49
|
1062 } else {
|
cannam@49
|
1063 return f(*ptr);
|
cannam@49
|
1064 }
|
cannam@49
|
1065 }
|
cannam@49
|
1066
|
cannam@49
|
1067 template <typename Func>
|
cannam@49
|
1068 auto map(Func&& f) && -> Maybe<decltype(f(instance<T&&>()))> {
|
cannam@49
|
1069 if (ptr == nullptr) {
|
cannam@49
|
1070 return nullptr;
|
cannam@49
|
1071 } else {
|
cannam@49
|
1072 return f(kj::mv(*ptr));
|
cannam@49
|
1073 }
|
cannam@49
|
1074 }
|
cannam@49
|
1075
|
cannam@49
|
1076 template <typename Func>
|
cannam@49
|
1077 auto map(Func&& f) const && -> Maybe<decltype(f(instance<const T&&>()))> {
|
cannam@49
|
1078 if (ptr == nullptr) {
|
cannam@49
|
1079 return nullptr;
|
cannam@49
|
1080 } else {
|
cannam@49
|
1081 return f(kj::mv(*ptr));
|
cannam@49
|
1082 }
|
cannam@49
|
1083 }
|
cannam@49
|
1084
|
cannam@49
|
1085 private:
|
cannam@49
|
1086 _::NullableValue<T> ptr;
|
cannam@49
|
1087
|
cannam@49
|
1088 template <typename U>
|
cannam@49
|
1089 friend class Maybe;
|
cannam@49
|
1090 template <typename U>
|
cannam@49
|
1091 friend _::NullableValue<U>&& _::readMaybe(Maybe<U>&& maybe);
|
cannam@49
|
1092 template <typename U>
|
cannam@49
|
1093 friend U* _::readMaybe(Maybe<U>& maybe);
|
cannam@49
|
1094 template <typename U>
|
cannam@49
|
1095 friend const U* _::readMaybe(const Maybe<U>& maybe);
|
cannam@49
|
1096 };
|
cannam@49
|
1097
|
cannam@49
|
1098 template <typename T>
|
cannam@49
|
1099 class Maybe<T&>: public DisallowConstCopyIfNotConst<T> {
|
cannam@49
|
1100 public:
|
cannam@49
|
1101 Maybe() noexcept: ptr(nullptr) {}
|
cannam@49
|
1102 Maybe(T& t) noexcept: ptr(&t) {}
|
cannam@49
|
1103 Maybe(T* t) noexcept: ptr(t) {}
|
cannam@49
|
1104
|
cannam@49
|
1105 template <typename U>
|
cannam@49
|
1106 inline Maybe(Maybe<U&>& other) noexcept: ptr(other.ptr) {}
|
cannam@49
|
1107 template <typename U>
|
cannam@49
|
1108 inline Maybe(const Maybe<const U&>& other) noexcept: ptr(other.ptr) {}
|
cannam@49
|
1109 inline Maybe(decltype(nullptr)) noexcept: ptr(nullptr) {}
|
cannam@49
|
1110
|
cannam@49
|
1111 inline Maybe& operator=(T& other) noexcept { ptr = &other; return *this; }
|
cannam@49
|
1112 inline Maybe& operator=(T* other) noexcept { ptr = other; return *this; }
|
cannam@49
|
1113 template <typename U>
|
cannam@49
|
1114 inline Maybe& operator=(Maybe<U&>& other) noexcept { ptr = other.ptr; return *this; }
|
cannam@49
|
1115 template <typename U>
|
cannam@49
|
1116 inline Maybe& operator=(const Maybe<const U&>& other) noexcept { ptr = other.ptr; return *this; }
|
cannam@49
|
1117
|
cannam@49
|
1118 inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; }
|
cannam@49
|
1119 inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; }
|
cannam@49
|
1120
|
cannam@49
|
1121 T& orDefault(T& defaultValue) {
|
cannam@49
|
1122 if (ptr == nullptr) {
|
cannam@49
|
1123 return defaultValue;
|
cannam@49
|
1124 } else {
|
cannam@49
|
1125 return *ptr;
|
cannam@49
|
1126 }
|
cannam@49
|
1127 }
|
cannam@49
|
1128 const T& orDefault(const T& defaultValue) const {
|
cannam@49
|
1129 if (ptr == nullptr) {
|
cannam@49
|
1130 return defaultValue;
|
cannam@49
|
1131 } else {
|
cannam@49
|
1132 return *ptr;
|
cannam@49
|
1133 }
|
cannam@49
|
1134 }
|
cannam@49
|
1135
|
cannam@49
|
1136 template <typename Func>
|
cannam@49
|
1137 auto map(Func&& f) -> Maybe<decltype(f(instance<T&>()))> {
|
cannam@49
|
1138 if (ptr == nullptr) {
|
cannam@49
|
1139 return nullptr;
|
cannam@49
|
1140 } else {
|
cannam@49
|
1141 return f(*ptr);
|
cannam@49
|
1142 }
|
cannam@49
|
1143 }
|
cannam@49
|
1144
|
cannam@49
|
1145 private:
|
cannam@49
|
1146 T* ptr;
|
cannam@49
|
1147
|
cannam@49
|
1148 template <typename U>
|
cannam@49
|
1149 friend class Maybe;
|
cannam@49
|
1150 template <typename U>
|
cannam@49
|
1151 friend U* _::readMaybe(Maybe<U&>&& maybe);
|
cannam@49
|
1152 template <typename U>
|
cannam@49
|
1153 friend U* _::readMaybe(const Maybe<U&>& maybe);
|
cannam@49
|
1154 };
|
cannam@49
|
1155
|
cannam@49
|
1156 // =======================================================================================
|
cannam@49
|
1157 // ArrayPtr
|
cannam@49
|
1158 //
|
cannam@49
|
1159 // So common that we put it in common.h rather than array.h.
|
cannam@49
|
1160
|
cannam@49
|
1161 template <typename T>
|
cannam@49
|
1162 class ArrayPtr: public DisallowConstCopyIfNotConst<T> {
|
cannam@49
|
1163 // A pointer to an array. Includes a size. Like any pointer, it doesn't own the target data,
|
cannam@49
|
1164 // and passing by value only copies the pointer, not the target.
|
cannam@49
|
1165
|
cannam@49
|
1166 public:
|
cannam@49
|
1167 inline constexpr ArrayPtr(): ptr(nullptr), size_(0) {}
|
cannam@49
|
1168 inline constexpr ArrayPtr(decltype(nullptr)): ptr(nullptr), size_(0) {}
|
cannam@49
|
1169 inline constexpr ArrayPtr(T* ptr, size_t size): ptr(ptr), size_(size) {}
|
cannam@49
|
1170 inline constexpr ArrayPtr(T* begin, T* end): ptr(begin), size_(end - begin) {}
|
cannam@49
|
1171 inline KJ_CONSTEXPR() ArrayPtr(::std::initializer_list<RemoveConstOrDisable<T>> init)
|
cannam@49
|
1172 : ptr(init.begin()), size_(init.size()) {}
|
cannam@49
|
1173
|
cannam@49
|
1174 template <size_t size>
|
cannam@49
|
1175 inline constexpr ArrayPtr(T (&native)[size]): ptr(native), size_(size) {}
|
cannam@49
|
1176 // Construct an ArrayPtr from a native C-style array.
|
cannam@49
|
1177
|
cannam@49
|
1178 inline operator ArrayPtr<const T>() const {
|
cannam@49
|
1179 return ArrayPtr<const T>(ptr, size_);
|
cannam@49
|
1180 }
|
cannam@49
|
1181 inline ArrayPtr<const T> asConst() const {
|
cannam@49
|
1182 return ArrayPtr<const T>(ptr, size_);
|
cannam@49
|
1183 }
|
cannam@49
|
1184
|
cannam@49
|
1185 inline size_t size() const { return size_; }
|
cannam@49
|
1186 inline const T& operator[](size_t index) const {
|
cannam@49
|
1187 KJ_IREQUIRE(index < size_, "Out-of-bounds ArrayPtr access.");
|
cannam@49
|
1188 return ptr[index];
|
cannam@49
|
1189 }
|
cannam@49
|
1190 inline T& operator[](size_t index) {
|
cannam@49
|
1191 KJ_IREQUIRE(index < size_, "Out-of-bounds ArrayPtr access.");
|
cannam@49
|
1192 return ptr[index];
|
cannam@49
|
1193 }
|
cannam@49
|
1194
|
cannam@49
|
1195 inline T* begin() { return ptr; }
|
cannam@49
|
1196 inline T* end() { return ptr + size_; }
|
cannam@49
|
1197 inline T& front() { return *ptr; }
|
cannam@49
|
1198 inline T& back() { return *(ptr + size_ - 1); }
|
cannam@49
|
1199 inline const T* begin() const { return ptr; }
|
cannam@49
|
1200 inline const T* end() const { return ptr + size_; }
|
cannam@49
|
1201 inline const T& front() const { return *ptr; }
|
cannam@49
|
1202 inline const T& back() const { return *(ptr + size_ - 1); }
|
cannam@49
|
1203
|
cannam@49
|
1204 inline ArrayPtr<const T> slice(size_t start, size_t end) const {
|
cannam@49
|
1205 KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice().");
|
cannam@49
|
1206 return ArrayPtr<const T>(ptr + start, end - start);
|
cannam@49
|
1207 }
|
cannam@49
|
1208 inline ArrayPtr slice(size_t start, size_t end) {
|
cannam@49
|
1209 KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice().");
|
cannam@49
|
1210 return ArrayPtr(ptr + start, end - start);
|
cannam@49
|
1211 }
|
cannam@49
|
1212
|
cannam@49
|
1213 inline ArrayPtr<PropagateConst<T, byte>> asBytes() const {
|
cannam@49
|
1214 // Reinterpret the array as a byte array. This is explicitly legal under C++ aliasing
|
cannam@49
|
1215 // rules.
|
cannam@49
|
1216 return { reinterpret_cast<PropagateConst<T, byte>*>(ptr), size_ * sizeof(T) };
|
cannam@49
|
1217 }
|
cannam@49
|
1218 inline ArrayPtr<PropagateConst<T, char>> asChars() const {
|
cannam@49
|
1219 // Reinterpret the array as a char array. This is explicitly legal under C++ aliasing
|
cannam@49
|
1220 // rules.
|
cannam@49
|
1221 return { reinterpret_cast<PropagateConst<T, char>*>(ptr), size_ * sizeof(T) };
|
cannam@49
|
1222 }
|
cannam@49
|
1223
|
cannam@49
|
1224 inline bool operator==(decltype(nullptr)) const { return size_ == 0; }
|
cannam@49
|
1225 inline bool operator!=(decltype(nullptr)) const { return size_ != 0; }
|
cannam@49
|
1226
|
cannam@49
|
1227 inline bool operator==(const ArrayPtr& other) const {
|
cannam@49
|
1228 if (size_ != other.size_) return false;
|
cannam@49
|
1229 for (size_t i = 0; i < size_; i++) {
|
cannam@49
|
1230 if (ptr[i] != other[i]) return false;
|
cannam@49
|
1231 }
|
cannam@49
|
1232 return true;
|
cannam@49
|
1233 }
|
cannam@49
|
1234 inline bool operator!=(const ArrayPtr& other) const { return !(*this == other); }
|
cannam@49
|
1235
|
cannam@49
|
1236 private:
|
cannam@49
|
1237 T* ptr;
|
cannam@49
|
1238 size_t size_;
|
cannam@49
|
1239 };
|
cannam@49
|
1240
|
cannam@49
|
1241 template <typename T>
|
cannam@49
|
1242 inline constexpr ArrayPtr<T> arrayPtr(T* ptr, size_t size) {
|
cannam@49
|
1243 // Use this function to construct ArrayPtrs without writing out the type name.
|
cannam@49
|
1244 return ArrayPtr<T>(ptr, size);
|
cannam@49
|
1245 }
|
cannam@49
|
1246
|
cannam@49
|
1247 template <typename T>
|
cannam@49
|
1248 inline constexpr ArrayPtr<T> arrayPtr(T* begin, T* end) {
|
cannam@49
|
1249 // Use this function to construct ArrayPtrs without writing out the type name.
|
cannam@49
|
1250 return ArrayPtr<T>(begin, end);
|
cannam@49
|
1251 }
|
cannam@49
|
1252
|
cannam@49
|
1253 // =======================================================================================
|
cannam@49
|
1254 // Casts
|
cannam@49
|
1255
|
cannam@49
|
1256 template <typename To, typename From>
|
cannam@49
|
1257 To implicitCast(From&& from) {
|
cannam@49
|
1258 // `implicitCast<T>(value)` casts `value` to type `T` only if the conversion is implicit. Useful
|
cannam@49
|
1259 // for e.g. resolving ambiguous overloads without sacrificing type-safety.
|
cannam@49
|
1260 return kj::fwd<From>(from);
|
cannam@49
|
1261 }
|
cannam@49
|
1262
|
cannam@49
|
1263 template <typename To, typename From>
|
cannam@49
|
1264 Maybe<To&> dynamicDowncastIfAvailable(From& from) {
|
cannam@49
|
1265 // If RTTI is disabled, always returns nullptr. Otherwise, works like dynamic_cast. Useful
|
cannam@49
|
1266 // in situations where dynamic_cast could allow an optimization, but isn't strictly necessary
|
cannam@49
|
1267 // for correctness. It is highly recommended that you try to arrange all your dynamic_casts
|
cannam@49
|
1268 // this way, as a dynamic_cast that is necessary for correctness implies a flaw in the interface
|
cannam@49
|
1269 // design.
|
cannam@49
|
1270
|
cannam@49
|
1271 // Force a compile error if To is not a subtype of From. Cross-casting is rare; if it is needed
|
cannam@49
|
1272 // we should have a separate cast function like dynamicCrosscastIfAvailable().
|
cannam@49
|
1273 if (false) {
|
cannam@49
|
1274 kj::implicitCast<From*>(kj::implicitCast<To*>(nullptr));
|
cannam@49
|
1275 }
|
cannam@49
|
1276
|
cannam@49
|
1277 #if KJ_NO_RTTI
|
cannam@49
|
1278 return nullptr;
|
cannam@49
|
1279 #else
|
cannam@49
|
1280 return dynamic_cast<To*>(&from);
|
cannam@49
|
1281 #endif
|
cannam@49
|
1282 }
|
cannam@49
|
1283
|
cannam@49
|
1284 template <typename To, typename From>
|
cannam@49
|
1285 To& downcast(From& from) {
|
cannam@49
|
1286 // Down-cast a value to a sub-type, asserting that the cast is valid. In opt mode this is a
|
cannam@49
|
1287 // static_cast, but in debug mode (when RTTI is enabled) a dynamic_cast will be used to verify
|
cannam@49
|
1288 // that the value really has the requested type.
|
cannam@49
|
1289
|
cannam@49
|
1290 // Force a compile error if To is not a subtype of From.
|
cannam@49
|
1291 if (false) {
|
cannam@49
|
1292 kj::implicitCast<From*>(kj::implicitCast<To*>(nullptr));
|
cannam@49
|
1293 }
|
cannam@49
|
1294
|
cannam@49
|
1295 #if !KJ_NO_RTTI
|
cannam@49
|
1296 KJ_IREQUIRE(dynamic_cast<To*>(&from) != nullptr, "Value cannot be downcast() to requested type.");
|
cannam@49
|
1297 #endif
|
cannam@49
|
1298
|
cannam@49
|
1299 return static_cast<To&>(from);
|
cannam@49
|
1300 }
|
cannam@49
|
1301
|
cannam@49
|
1302 // =======================================================================================
|
cannam@49
|
1303 // Defer
|
cannam@49
|
1304
|
cannam@49
|
1305 namespace _ { // private
|
cannam@49
|
1306
|
cannam@49
|
1307 template <typename Func>
|
cannam@49
|
1308 class Deferred {
|
cannam@49
|
1309 public:
|
cannam@49
|
1310 inline Deferred(Func&& func): func(kj::fwd<Func>(func)), canceled(false) {}
|
cannam@49
|
1311 inline ~Deferred() noexcept(false) { if (!canceled) func(); }
|
cannam@49
|
1312 KJ_DISALLOW_COPY(Deferred);
|
cannam@49
|
1313
|
cannam@49
|
1314 // This move constructor is usually optimized away by the compiler.
|
cannam@49
|
1315 inline Deferred(Deferred&& other): func(kj::mv(other.func)), canceled(false) {
|
cannam@49
|
1316 other.canceled = true;
|
cannam@49
|
1317 }
|
cannam@49
|
1318 private:
|
cannam@49
|
1319 Func func;
|
cannam@49
|
1320 bool canceled;
|
cannam@49
|
1321 };
|
cannam@49
|
1322
|
cannam@49
|
1323 } // namespace _ (private)
|
cannam@49
|
1324
|
cannam@49
|
1325 template <typename Func>
|
cannam@49
|
1326 _::Deferred<Func> defer(Func&& func) {
|
cannam@49
|
1327 // Returns an object which will invoke the given functor in its destructor. The object is not
|
cannam@49
|
1328 // copyable but is movable with the semantics you'd expect. Since the return type is private,
|
cannam@49
|
1329 // you need to assign to an `auto` variable.
|
cannam@49
|
1330 //
|
cannam@49
|
1331 // The KJ_DEFER macro provides slightly more convenient syntax for the common case where you
|
cannam@49
|
1332 // want some code to run at current scope exit.
|
cannam@49
|
1333
|
cannam@49
|
1334 return _::Deferred<Func>(kj::fwd<Func>(func));
|
cannam@49
|
1335 }
|
cannam@49
|
1336
|
cannam@49
|
1337 #define KJ_DEFER(code) auto KJ_UNIQUE_NAME(_kjDefer) = ::kj::defer([&](){code;})
|
cannam@49
|
1338 // Run the given code when the function exits, whether by return or exception.
|
cannam@49
|
1339
|
cannam@49
|
1340 } // namespace kj
|
cannam@49
|
1341
|
cannam@49
|
1342 #endif // KJ_COMMON_H_
|