jpayne@69
|
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
jpayne@69
|
2 // Licensed under the MIT License:
|
jpayne@69
|
3 //
|
jpayne@69
|
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
jpayne@69
|
5 // of this software and associated documentation files (the "Software"), to deal
|
jpayne@69
|
6 // in the Software without restriction, including without limitation the rights
|
jpayne@69
|
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
jpayne@69
|
8 // copies of the Software, and to permit persons to whom the Software is
|
jpayne@69
|
9 // furnished to do so, subject to the following conditions:
|
jpayne@69
|
10 //
|
jpayne@69
|
11 // The above copyright notice and this permission notice shall be included in
|
jpayne@69
|
12 // all copies or substantial portions of the Software.
|
jpayne@69
|
13 //
|
jpayne@69
|
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
jpayne@69
|
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
jpayne@69
|
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
jpayne@69
|
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
jpayne@69
|
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
jpayne@69
|
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
jpayne@69
|
20 // THE SOFTWARE.
|
jpayne@69
|
21
|
jpayne@69
|
22 // Header that should be #included by everyone.
|
jpayne@69
|
23 //
|
jpayne@69
|
24 // This defines very simple utilities that are widely applicable.
|
jpayne@69
|
25
|
jpayne@69
|
26 #pragma once
|
jpayne@69
|
27
|
jpayne@69
|
28 #if defined(__GNUC__) || defined(__clang__)
|
jpayne@69
|
29 #define KJ_BEGIN_SYSTEM_HEADER _Pragma("GCC system_header")
|
jpayne@69
|
30 #elif defined(_MSC_VER)
|
jpayne@69
|
31 #define KJ_BEGIN_SYSTEM_HEADER __pragma(warning(push, 0))
|
jpayne@69
|
32 #define KJ_END_SYSTEM_HEADER __pragma(warning(pop))
|
jpayne@69
|
33 #endif
|
jpayne@69
|
34
|
jpayne@69
|
35 #ifndef KJ_BEGIN_SYSTEM_HEADER
|
jpayne@69
|
36 #define KJ_BEGIN_SYSTEM_HEADER
|
jpayne@69
|
37 #endif
|
jpayne@69
|
38
|
jpayne@69
|
39 #ifndef KJ_END_SYSTEM_HEADER
|
jpayne@69
|
40 #define KJ_END_SYSTEM_HEADER
|
jpayne@69
|
41 #endif
|
jpayne@69
|
42
|
jpayne@69
|
43 #if !defined(KJ_HEADER_WARNINGS) || !KJ_HEADER_WARNINGS
|
jpayne@69
|
44 #define KJ_BEGIN_HEADER KJ_BEGIN_SYSTEM_HEADER
|
jpayne@69
|
45 #define KJ_END_HEADER KJ_END_SYSTEM_HEADER
|
jpayne@69
|
46 #else
|
jpayne@69
|
47 #define KJ_BEGIN_HEADER
|
jpayne@69
|
48 #define KJ_END_HEADER
|
jpayne@69
|
49 #endif
|
jpayne@69
|
50
|
jpayne@69
|
51 #ifdef __has_cpp_attribute
|
jpayne@69
|
52 #define KJ_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
|
jpayne@69
|
53 #else
|
jpayne@69
|
54 #define KJ_HAS_CPP_ATTRIBUTE(x) 0
|
jpayne@69
|
55 #endif
|
jpayne@69
|
56
|
jpayne@69
|
57 #ifdef __has_feature
|
jpayne@69
|
58 #define KJ_HAS_COMPILER_FEATURE(x) __has_feature(x)
|
jpayne@69
|
59 #else
|
jpayne@69
|
60 #define KJ_HAS_COMPILER_FEATURE(x) 0
|
jpayne@69
|
61 #endif
|
jpayne@69
|
62
|
jpayne@69
|
63 #if defined(_MSVC_LANG) && !defined(__clang__)
|
jpayne@69
|
64 #define KJ_CPP_STD _MSVC_LANG
|
jpayne@69
|
65 #else
|
jpayne@69
|
66 #define KJ_CPP_STD __cplusplus
|
jpayne@69
|
67 #endif
|
jpayne@69
|
68
|
jpayne@69
|
69 KJ_BEGIN_HEADER
|
jpayne@69
|
70
|
jpayne@69
|
71 #ifndef KJ_NO_COMPILER_CHECK
|
jpayne@69
|
72 // Technically, __cplusplus should be 201402L for C++14, but GCC 4.9 -- which is supported -- still
|
jpayne@69
|
73 // had it defined to 201300L even with -std=c++14.
|
jpayne@69
|
74 #if KJ_CPP_STD < 201300L && !__CDT_PARSER__
|
jpayne@69
|
75 #error "This code requires C++14. Either your compiler does not support it or it is not enabled."
|
jpayne@69
|
76 #ifdef __GNUC__
|
jpayne@69
|
77 // Compiler claims compatibility with GCC, so presumably supports -std.
|
jpayne@69
|
78 #error "Pass -std=c++14 on the compiler command line to enable C++14."
|
jpayne@69
|
79 #endif
|
jpayne@69
|
80 #endif
|
jpayne@69
|
81
|
jpayne@69
|
82 #ifdef __GNUC__
|
jpayne@69
|
83 #if __clang__
|
jpayne@69
|
84 #if __clang_major__ < 5
|
jpayne@69
|
85 #warning "This library requires at least Clang 5.0."
|
jpayne@69
|
86 #elif KJ_CPP_STD >= 201402L && !__has_include(<initializer_list>)
|
jpayne@69
|
87 #warning "Your compiler supports C++14 but your C++ standard library does not. If your "\
|
jpayne@69
|
88 "system has libc++ installed (as should be the case on e.g. Mac OSX), try adding "\
|
jpayne@69
|
89 "-stdlib=libc++ to your CXXFLAGS."
|
jpayne@69
|
90 #endif
|
jpayne@69
|
91 #else
|
jpayne@69
|
92 #if __GNUC__ < 5
|
jpayne@69
|
93 #warning "This library requires at least GCC 5.0."
|
jpayne@69
|
94 #endif
|
jpayne@69
|
95 #endif
|
jpayne@69
|
96 #elif defined(_MSC_VER)
|
jpayne@69
|
97 #if _MSC_VER < 1910 && !defined(__clang__)
|
jpayne@69
|
98 #error "You need Visual Studio 2017 or better to compile this code."
|
jpayne@69
|
99 #endif
|
jpayne@69
|
100 #else
|
jpayne@69
|
101 #warning "I don't recognize your compiler. As of this writing, Clang, GCC, and Visual Studio "\
|
jpayne@69
|
102 "are the only known compilers with enough C++14 support for this library. "\
|
jpayne@69
|
103 "#define KJ_NO_COMPILER_CHECK to make this warning go away."
|
jpayne@69
|
104 #endif
|
jpayne@69
|
105 #endif
|
jpayne@69
|
106
|
jpayne@69
|
107 #include <stddef.h>
|
jpayne@69
|
108 #include <cstring>
|
jpayne@69
|
109 #include <initializer_list>
|
jpayne@69
|
110 #include <string.h>
|
jpayne@69
|
111
|
jpayne@69
|
112 #if __linux__ && KJ_CPP_STD > 201200L
|
jpayne@69
|
113 // Hack around stdlib bug with C++14 that exists on some Linux systems.
|
jpayne@69
|
114 // Apparently in this mode the C library decides not to define gets() but the C++ library still
|
jpayne@69
|
115 // tries to import it into the std namespace. This bug has been fixed at the source but is still
|
jpayne@69
|
116 // widely present in the wild e.g. on Ubuntu 14.04.
|
jpayne@69
|
117 #undef _GLIBCXX_HAVE_GETS
|
jpayne@69
|
118 #endif
|
jpayne@69
|
119
|
jpayne@69
|
120 #if _WIN32
|
jpayne@69
|
121 // Windows likes to define macros for min() and max(). We just can't deal with this.
|
jpayne@69
|
122 // If windows.h was included already, undef these.
|
jpayne@69
|
123 #undef min
|
jpayne@69
|
124 #undef max
|
jpayne@69
|
125 // If windows.h was not included yet, define the macro that prevents min() and max() from being
|
jpayne@69
|
126 // defined.
|
jpayne@69
|
127 #ifndef NOMINMAX
|
jpayne@69
|
128 #define NOMINMAX 1
|
jpayne@69
|
129 #endif
|
jpayne@69
|
130 #endif
|
jpayne@69
|
131
|
jpayne@69
|
132 #if defined(_MSC_VER)
|
jpayne@69
|
133 #include <intrin.h> // __popcnt
|
jpayne@69
|
134 #endif
|
jpayne@69
|
135
|
jpayne@69
|
136 // =======================================================================================
|
jpayne@69
|
137
|
jpayne@69
|
138 namespace kj {
|
jpayne@69
|
139
|
jpayne@69
|
140 typedef unsigned int uint;
|
jpayne@69
|
141 typedef unsigned char byte;
|
jpayne@69
|
142
|
jpayne@69
|
143 // =======================================================================================
|
jpayne@69
|
144 // Common macros, especially for common yet compiler-specific features.
|
jpayne@69
|
145
|
jpayne@69
|
146 // Detect whether RTTI and exceptions are enabled, assuming they are unless we have specific
|
jpayne@69
|
147 // evidence to the contrary. Clients can always define KJ_NO_RTTI or KJ_NO_EXCEPTIONS explicitly
|
jpayne@69
|
148 // to override these checks.
|
jpayne@69
|
149
|
jpayne@69
|
150 // TODO: Ideally we'd use __cpp_exceptions/__cpp_rtti not being defined as the first pass since
|
jpayne@69
|
151 // that is the standard compliant way. However, it's unclear how to use those macros (or any
|
jpayne@69
|
152 // others) to distinguish between the compiler supporting feature detection and the feature being
|
jpayne@69
|
153 // disabled vs the compiler not supporting feature detection at all.
|
jpayne@69
|
154 #if defined(__has_feature)
|
jpayne@69
|
155 #if !defined(KJ_NO_RTTI) && !__has_feature(cxx_rtti)
|
jpayne@69
|
156 #define KJ_NO_RTTI 1
|
jpayne@69
|
157 #endif
|
jpayne@69
|
158 #if !defined(KJ_NO_EXCEPTIONS) && !__has_feature(cxx_exceptions)
|
jpayne@69
|
159 #define KJ_NO_EXCEPTIONS 1
|
jpayne@69
|
160 #endif
|
jpayne@69
|
161 #elif defined(__GNUC__)
|
jpayne@69
|
162 #if !defined(KJ_NO_RTTI) && !__GXX_RTTI
|
jpayne@69
|
163 #define KJ_NO_RTTI 1
|
jpayne@69
|
164 #endif
|
jpayne@69
|
165 #if !defined(KJ_NO_EXCEPTIONS) && !__EXCEPTIONS
|
jpayne@69
|
166 #define KJ_NO_EXCEPTIONS 1
|
jpayne@69
|
167 #endif
|
jpayne@69
|
168 #elif defined(_MSC_VER)
|
jpayne@69
|
169 #if !defined(KJ_NO_RTTI) && !defined(_CPPRTTI)
|
jpayne@69
|
170 #define KJ_NO_RTTI 1
|
jpayne@69
|
171 #endif
|
jpayne@69
|
172 #if !defined(KJ_NO_EXCEPTIONS) && !defined(_CPPUNWIND)
|
jpayne@69
|
173 #define KJ_NO_EXCEPTIONS 1
|
jpayne@69
|
174 #endif
|
jpayne@69
|
175 #endif
|
jpayne@69
|
176
|
jpayne@69
|
177 #if !defined(KJ_DEBUG) && !defined(KJ_NDEBUG)
|
jpayne@69
|
178 // Heuristically decide whether to enable debug mode. If DEBUG or NDEBUG is defined, use that.
|
jpayne@69
|
179 // Otherwise, fall back to checking whether optimization is enabled.
|
jpayne@69
|
180 #if defined(DEBUG) || defined(_DEBUG)
|
jpayne@69
|
181 #define KJ_DEBUG
|
jpayne@69
|
182 #elif defined(NDEBUG)
|
jpayne@69
|
183 #define KJ_NDEBUG
|
jpayne@69
|
184 #elif __OPTIMIZE__
|
jpayne@69
|
185 #define KJ_NDEBUG
|
jpayne@69
|
186 #else
|
jpayne@69
|
187 #define KJ_DEBUG
|
jpayne@69
|
188 #endif
|
jpayne@69
|
189 #endif
|
jpayne@69
|
190
|
jpayne@69
|
191 #define KJ_DISALLOW_COPY(classname) \
|
jpayne@69
|
192 classname(const classname&) = delete; \
|
jpayne@69
|
193 classname& operator=(const classname&) = delete
|
jpayne@69
|
194 // Deletes the implicit copy constructor and assignment operator. This inhibits the compiler from
|
jpayne@69
|
195 // generating the implicit move constructor and assignment operator for this class, but allows the
|
jpayne@69
|
196 // code author to supply them, if they make sense to implement.
|
jpayne@69
|
197 //
|
jpayne@69
|
198 // This macro should not be your first choice. Instead, prefer using KJ_DISALLOW_COPY_AND_MOVE, and only use
|
jpayne@69
|
199 // this macro when you have determined that you must implement move semantics for your type.
|
jpayne@69
|
200
|
jpayne@69
|
201 #define KJ_DISALLOW_COPY_AND_MOVE(classname) \
|
jpayne@69
|
202 classname(const classname&) = delete; \
|
jpayne@69
|
203 classname& operator=(const classname&) = delete; \
|
jpayne@69
|
204 classname(classname&&) = delete; \
|
jpayne@69
|
205 classname& operator=(classname&&) = delete
|
jpayne@69
|
206 // Deletes the implicit copy and move constructors and assignment operators. This is useful in cases
|
jpayne@69
|
207 // where the code author wants to provide an additional compile-time guard against subsequent
|
jpayne@69
|
208 // maintainers casually adding move operations. This is particularly useful when implementing RAII
|
jpayne@69
|
209 // classes that are intended to be completely immobile.
|
jpayne@69
|
210
|
jpayne@69
|
211 #ifdef __GNUC__
|
jpayne@69
|
212 #define KJ_LIKELY(condition) __builtin_expect(condition, true)
|
jpayne@69
|
213 #define KJ_UNLIKELY(condition) __builtin_expect(condition, false)
|
jpayne@69
|
214 // Branch prediction macros. Evaluates to the condition given, but also tells the compiler that we
|
jpayne@69
|
215 // expect the condition to be true/false enough of the time that it's worth hard-coding branch
|
jpayne@69
|
216 // prediction.
|
jpayne@69
|
217 #else
|
jpayne@69
|
218 #define KJ_LIKELY(condition) (condition)
|
jpayne@69
|
219 #define KJ_UNLIKELY(condition) (condition)
|
jpayne@69
|
220 #endif
|
jpayne@69
|
221
|
jpayne@69
|
222 #if defined(KJ_DEBUG) || __NO_INLINE__
|
jpayne@69
|
223 #define KJ_ALWAYS_INLINE(...) inline __VA_ARGS__
|
jpayne@69
|
224 // Don't force inline in debug mode.
|
jpayne@69
|
225 #else
|
jpayne@69
|
226 #if defined(_MSC_VER) && !defined(__clang__)
|
jpayne@69
|
227 #define KJ_ALWAYS_INLINE(...) __forceinline __VA_ARGS__
|
jpayne@69
|
228 #else
|
jpayne@69
|
229 #define KJ_ALWAYS_INLINE(...) inline __VA_ARGS__ __attribute__((always_inline))
|
jpayne@69
|
230 #endif
|
jpayne@69
|
231 // Force a function to always be inlined. Apply only to the prototype, not to the definition.
|
jpayne@69
|
232 #endif
|
jpayne@69
|
233
|
jpayne@69
|
234 #if defined(_MSC_VER) && !defined(__clang__)
|
jpayne@69
|
235 #define KJ_NOINLINE __declspec(noinline)
|
jpayne@69
|
236 #else
|
jpayne@69
|
237 #define KJ_NOINLINE __attribute__((noinline))
|
jpayne@69
|
238 #endif
|
jpayne@69
|
239
|
jpayne@69
|
240 #if defined(_MSC_VER) && !__clang__
|
jpayne@69
|
241 #define KJ_NORETURN(prototype) __declspec(noreturn) prototype
|
jpayne@69
|
242 #define KJ_UNUSED
|
jpayne@69
|
243 #define KJ_WARN_UNUSED_RESULT
|
jpayne@69
|
244 // TODO(msvc): KJ_WARN_UNUSED_RESULT can use _Check_return_ on MSVC, but it's a prefix, so
|
jpayne@69
|
245 // wrapping the whole prototype is needed. http://msdn.microsoft.com/en-us/library/jj159529.aspx
|
jpayne@69
|
246 // Similarly, KJ_UNUSED could use __pragma(warning(suppress:...)), but again that's a prefix.
|
jpayne@69
|
247 #else
|
jpayne@69
|
248 #define KJ_NORETURN(prototype) prototype __attribute__((noreturn))
|
jpayne@69
|
249 #define KJ_UNUSED __attribute__((unused))
|
jpayne@69
|
250 #define KJ_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
jpayne@69
|
251 #endif
|
jpayne@69
|
252
|
jpayne@69
|
253 #if KJ_HAS_CPP_ATTRIBUTE(clang::lifetimebound)
|
jpayne@69
|
254 // If this is generating too many false-positives, the user is responsible for disabling the
|
jpayne@69
|
255 // problematic warning at the compiler switch level or by suppressing the place where the
|
jpayne@69
|
256 // false-positive is reported through compiler-specific pragmas if available.
|
jpayne@69
|
257 #define KJ_LIFETIMEBOUND [[clang::lifetimebound]]
|
jpayne@69
|
258 #else
|
jpayne@69
|
259 #define KJ_LIFETIMEBOUND
|
jpayne@69
|
260 #endif
|
jpayne@69
|
261 // Annotation that indicates the returned value is referencing a resource owned by this type (e.g.
|
jpayne@69
|
262 // cStr() on a std::string). Unfortunately this lifetime can only be superficial currently & cannot
|
jpayne@69
|
263 // track further. For example, there's no way to get `array.asPtr().slice(5, 6))` to warn if the
|
jpayne@69
|
264 // last slice exceeds the lifetime of `array`. That's because in the general case `ArrayPtr::slice`
|
jpayne@69
|
265 // can't have the lifetime bound annotation since it's not wrong to do something like:
|
jpayne@69
|
266 // ArrayPtr<char> doSomething(ArrayPtr<char> foo) {
|
jpayne@69
|
267 // ...
|
jpayne@69
|
268 // return foo.slice(5, 6);
|
jpayne@69
|
269 // }
|
jpayne@69
|
270 // If `ArrayPtr::slice` had a lifetime bound then the compiler would warn about this perfectly
|
jpayne@69
|
271 // legitimate method. Really there needs to be 2 more annotations. One to inherit the lifetime bound
|
jpayne@69
|
272 // and another to inherit the lifetime bound from a parameter (which really could be the same thing
|
jpayne@69
|
273 // by allowing a syntax like `[[clang::lifetimebound(*this)]]`.
|
jpayne@69
|
274 // https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
|
jpayne@69
|
275
|
jpayne@69
|
276 #if __clang__
|
jpayne@69
|
277 #define KJ_UNUSED_MEMBER __attribute__((unused))
|
jpayne@69
|
278 // Inhibits "unused" warning for member variables. Only Clang produces such a warning, while GCC
|
jpayne@69
|
279 // complains if the attribute is set on members.
|
jpayne@69
|
280 #else
|
jpayne@69
|
281 #define KJ_UNUSED_MEMBER
|
jpayne@69
|
282 #endif
|
jpayne@69
|
283
|
jpayne@69
|
284 #if KJ_CPP_STD > 201703L || (__clang__ && __clang_major__ >= 9 && KJ_CPP_STD >= 201103L)
|
jpayne@69
|
285 // Technically this was only added to C++20 but Clang allows it for >= C++11 and spelunking the
|
jpayne@69
|
286 // attributes manual indicates it first came in with Clang 9.
|
jpayne@69
|
287 #define KJ_NO_UNIQUE_ADDRESS [[no_unique_address]]
|
jpayne@69
|
288 #else
|
jpayne@69
|
289 #define KJ_NO_UNIQUE_ADDRESS
|
jpayne@69
|
290 #endif
|
jpayne@69
|
291
|
jpayne@69
|
292 #if KJ_HAS_COMPILER_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
|
jpayne@69
|
293 #define KJ_DISABLE_TSAN __attribute__((no_sanitize("thread"), noinline))
|
jpayne@69
|
294 #else
|
jpayne@69
|
295 #define KJ_DISABLE_TSAN
|
jpayne@69
|
296 #endif
|
jpayne@69
|
297
|
jpayne@69
|
298 #if __clang__
|
jpayne@69
|
299 #define KJ_DEPRECATED(reason) \
|
jpayne@69
|
300 __attribute__((deprecated(reason)))
|
jpayne@69
|
301 #define KJ_UNAVAILABLE(reason) \
|
jpayne@69
|
302 __attribute__((unavailable(reason)))
|
jpayne@69
|
303 #elif __GNUC__
|
jpayne@69
|
304 #define KJ_DEPRECATED(reason) \
|
jpayne@69
|
305 __attribute__((deprecated))
|
jpayne@69
|
306 #define KJ_UNAVAILABLE(reason) = delete
|
jpayne@69
|
307 // If the `unavailable` attribute is not supproted, just mark the method deleted, which at least
|
jpayne@69
|
308 // makes it a compile-time error to try to call it. Note that on Clang, marking a method deleted
|
jpayne@69
|
309 // *and* unavailable unfortunately defeats the purpose of the unavailable annotation, as the
|
jpayne@69
|
310 // generic "deleted" error is reported instead.
|
jpayne@69
|
311 #else
|
jpayne@69
|
312 #define KJ_DEPRECATED(reason)
|
jpayne@69
|
313 #define KJ_UNAVAILABLE(reason) = delete
|
jpayne@69
|
314 // TODO(msvc): Again, here, MSVC prefers a prefix, __declspec(deprecated).
|
jpayne@69
|
315 #endif
|
jpayne@69
|
316
|
jpayne@69
|
317 #if KJ_TESTING_KJ // defined in KJ's own unit tests; others should not define this
|
jpayne@69
|
318 #undef KJ_DEPRECATED
|
jpayne@69
|
319 #define KJ_DEPRECATED(reason)
|
jpayne@69
|
320 #endif
|
jpayne@69
|
321
|
jpayne@69
|
322 namespace _ { // private
|
jpayne@69
|
323
|
jpayne@69
|
324 KJ_NORETURN(void inlineRequireFailure(
|
jpayne@69
|
325 const char* file, int line, const char* expectation, const char* macroArgs,
|
jpayne@69
|
326 const char* message = nullptr));
|
jpayne@69
|
327
|
jpayne@69
|
328 KJ_NORETURN(void unreachable());
|
jpayne@69
|
329
|
jpayne@69
|
330 } // namespace _ (private)
|
jpayne@69
|
331
|
jpayne@69
|
332 #if _MSC_VER && !defined(__clang__) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)
|
jpayne@69
|
333 #define KJ_MSVC_TRADITIONAL_CPP 1
|
jpayne@69
|
334 #endif
|
jpayne@69
|
335
|
jpayne@69
|
336 #ifdef KJ_DEBUG
|
jpayne@69
|
337 #if KJ_MSVC_TRADITIONAL_CPP
|
jpayne@69
|
338 #define KJ_IREQUIRE(condition, ...) \
|
jpayne@69
|
339 if (KJ_LIKELY(condition)); else ::kj::_::inlineRequireFailure( \
|
jpayne@69
|
340 __FILE__, __LINE__, #condition, "" #__VA_ARGS__, __VA_ARGS__)
|
jpayne@69
|
341 // Version of KJ_DREQUIRE() which is safe to use in headers that are #included by users. Used to
|
jpayne@69
|
342 // check preconditions inside inline methods. KJ_IREQUIRE is particularly useful in that
|
jpayne@69
|
343 // it will be enabled depending on whether the application is compiled in debug mode rather than
|
jpayne@69
|
344 // whether libkj is.
|
jpayne@69
|
345 #else
|
jpayne@69
|
346 #define KJ_IREQUIRE(condition, ...) \
|
jpayne@69
|
347 if (KJ_LIKELY(condition)); else ::kj::_::inlineRequireFailure( \
|
jpayne@69
|
348 __FILE__, __LINE__, #condition, #__VA_ARGS__, ##__VA_ARGS__)
|
jpayne@69
|
349 // Version of KJ_DREQUIRE() which is safe to use in headers that are #included by users. Used to
|
jpayne@69
|
350 // check preconditions inside inline methods. KJ_IREQUIRE is particularly useful in that
|
jpayne@69
|
351 // it will be enabled depending on whether the application is compiled in debug mode rather than
|
jpayne@69
|
352 // whether libkj is.
|
jpayne@69
|
353 #endif
|
jpayne@69
|
354 #else
|
jpayne@69
|
355 #define KJ_IREQUIRE(condition, ...)
|
jpayne@69
|
356 #endif
|
jpayne@69
|
357
|
jpayne@69
|
358 #define KJ_IASSERT KJ_IREQUIRE
|
jpayne@69
|
359
|
jpayne@69
|
360 #define KJ_UNREACHABLE ::kj::_::unreachable();
|
jpayne@69
|
361 // Put this on code paths that cannot be reached to suppress compiler warnings about missing
|
jpayne@69
|
362 // returns.
|
jpayne@69
|
363
|
jpayne@69
|
364 #if __clang__
|
jpayne@69
|
365 #define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT
|
jpayne@69
|
366 #else
|
jpayne@69
|
367 #define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT KJ_UNREACHABLE
|
jpayne@69
|
368 #endif
|
jpayne@69
|
369
|
jpayne@69
|
370 #if __clang__
|
jpayne@69
|
371 #define KJ_KNOWN_UNREACHABLE(code) \
|
jpayne@69
|
372 do { \
|
jpayne@69
|
373 _Pragma("clang diagnostic push") \
|
jpayne@69
|
374 _Pragma("clang diagnostic ignored \"-Wunreachable-code\"") \
|
jpayne@69
|
375 code; \
|
jpayne@69
|
376 _Pragma("clang diagnostic pop") \
|
jpayne@69
|
377 } while (false)
|
jpayne@69
|
378 // Suppress "unreachable code" warnings on intentionally unreachable code.
|
jpayne@69
|
379 #else
|
jpayne@69
|
380 // TODO(someday): Add support for non-clang compilers.
|
jpayne@69
|
381 #define KJ_KNOWN_UNREACHABLE(code) do {code;} while(false)
|
jpayne@69
|
382 #endif
|
jpayne@69
|
383
|
jpayne@69
|
384 #if KJ_HAS_CPP_ATTRIBUTE(fallthrough)
|
jpayne@69
|
385 #define KJ_FALLTHROUGH [[fallthrough]]
|
jpayne@69
|
386 #else
|
jpayne@69
|
387 #define KJ_FALLTHROUGH
|
jpayne@69
|
388 #endif
|
jpayne@69
|
389
|
jpayne@69
|
390 // #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack)
|
jpayne@69
|
391 //
|
jpayne@69
|
392 // Allocate an array, preferably on the stack, unless it is too big. On GCC this will use
|
jpayne@69
|
393 // variable-sized arrays. For other compilers we could just use a fixed-size array. `minStack`
|
jpayne@69
|
394 // is the stack array size to use if variable-width arrays are not supported. `maxStack` is the
|
jpayne@69
|
395 // maximum stack array size if variable-width arrays *are* supported.
|
jpayne@69
|
396 #if __GNUC__ && !__clang__
|
jpayne@69
|
397 #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \
|
jpayne@69
|
398 size_t name##_size = (size); \
|
jpayne@69
|
399 bool name##_isOnStack = name##_size <= (maxStack); \
|
jpayne@69
|
400 type name##_stack[kj::max(1, name##_isOnStack ? name##_size : 0)]; \
|
jpayne@69
|
401 ::kj::Array<type> name##_heap = name##_isOnStack ? \
|
jpayne@69
|
402 nullptr : kj::heapArray<type>(name##_size); \
|
jpayne@69
|
403 ::kj::ArrayPtr<type> name = name##_isOnStack ? \
|
jpayne@69
|
404 kj::arrayPtr(name##_stack, name##_size) : name##_heap
|
jpayne@69
|
405 #else
|
jpayne@69
|
406 #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \
|
jpayne@69
|
407 size_t name##_size = (size); \
|
jpayne@69
|
408 bool name##_isOnStack = name##_size <= (minStack); \
|
jpayne@69
|
409 type name##_stack[minStack]; \
|
jpayne@69
|
410 ::kj::Array<type> name##_heap = name##_isOnStack ? \
|
jpayne@69
|
411 nullptr : kj::heapArray<type>(name##_size); \
|
jpayne@69
|
412 ::kj::ArrayPtr<type> name = name##_isOnStack ? \
|
jpayne@69
|
413 kj::arrayPtr(name##_stack, name##_size) : name##_heap
|
jpayne@69
|
414 #endif
|
jpayne@69
|
415
|
jpayne@69
|
416 #define KJ_CONCAT_(x, y) x##y
|
jpayne@69
|
417 #define KJ_CONCAT(x, y) KJ_CONCAT_(x, y)
|
jpayne@69
|
418 #define KJ_UNIQUE_NAME(prefix) KJ_CONCAT(prefix, __LINE__)
|
jpayne@69
|
419 // Create a unique identifier name. We use concatenate __LINE__ rather than __COUNTER__ so that
|
jpayne@69
|
420 // the name can be used multiple times in the same macro.
|
jpayne@69
|
421
|
jpayne@69
|
422 #if _MSC_VER && !defined(__clang__)
|
jpayne@69
|
423
|
jpayne@69
|
424 #define KJ_CONSTEXPR(...) __VA_ARGS__
|
jpayne@69
|
425 // Use in cases where MSVC barfs on constexpr. A replacement keyword (e.g. "const") can be
|
jpayne@69
|
426 // provided, or just leave blank to remove the keyword entirely.
|
jpayne@69
|
427 //
|
jpayne@69
|
428 // TODO(msvc): Remove this hack once MSVC fully supports constexpr.
|
jpayne@69
|
429
|
jpayne@69
|
430 #ifndef __restrict__
|
jpayne@69
|
431 #define __restrict__ __restrict
|
jpayne@69
|
432 // TODO(msvc): Would it be better to define a KJ_RESTRICT macro?
|
jpayne@69
|
433 #endif
|
jpayne@69
|
434
|
jpayne@69
|
435 #pragma warning(disable: 4521 4522)
|
jpayne@69
|
436 // This warning complains when there are two copy constructors, one for a const reference and
|
jpayne@69
|
437 // one for a non-const reference. It is often quite necessary to do this in wrapper templates,
|
jpayne@69
|
438 // therefore this warning is dumb and we disable it.
|
jpayne@69
|
439
|
jpayne@69
|
440 #pragma warning(disable: 4458)
|
jpayne@69
|
441 // Warns when a parameter name shadows a class member. Unfortunately my code does this a lot,
|
jpayne@69
|
442 // since I don't use a special name format for members.
|
jpayne@69
|
443
|
jpayne@69
|
444 #else // _MSC_VER
|
jpayne@69
|
445 #define KJ_CONSTEXPR(...) constexpr
|
jpayne@69
|
446 #endif
|
jpayne@69
|
447
|
jpayne@69
|
448 // =======================================================================================
|
jpayne@69
|
449 // Template metaprogramming helpers.
|
jpayne@69
|
450
|
jpayne@69
|
451 #define KJ_HAS_TRIVIAL_CONSTRUCTOR __is_trivially_constructible
|
jpayne@69
|
452 #if __GNUC__ && !__clang__
|
jpayne@69
|
453 #define KJ_HAS_NOTHROW_CONSTRUCTOR __has_nothrow_constructor
|
jpayne@69
|
454 #define KJ_HAS_TRIVIAL_DESTRUCTOR __has_trivial_destructor
|
jpayne@69
|
455 #else
|
jpayne@69
|
456 #define KJ_HAS_NOTHROW_CONSTRUCTOR __is_nothrow_constructible
|
jpayne@69
|
457 #define KJ_HAS_TRIVIAL_DESTRUCTOR __is_trivially_destructible
|
jpayne@69
|
458 #endif
|
jpayne@69
|
459
|
jpayne@69
|
460 template <typename T> struct NoInfer_ { typedef T Type; };
|
jpayne@69
|
461 template <typename T> using NoInfer = typename NoInfer_<T>::Type;
|
jpayne@69
|
462 // Use NoInfer<T>::Type in place of T for a template function parameter to prevent inference of
|
jpayne@69
|
463 // the type based on the parameter value.
|
jpayne@69
|
464
|
jpayne@69
|
465 template <typename T> struct RemoveConst_ { typedef T Type; };
|
jpayne@69
|
466 template <typename T> struct RemoveConst_<const T> { typedef T Type; };
|
jpayne@69
|
467 template <typename T> using RemoveConst = typename RemoveConst_<T>::Type;
|
jpayne@69
|
468
|
jpayne@69
|
469 template <typename> struct IsLvalueReference_ { static constexpr bool value = false; };
|
jpayne@69
|
470 template <typename T> struct IsLvalueReference_<T&> { static constexpr bool value = true; };
|
jpayne@69
|
471 template <typename T>
|
jpayne@69
|
472 inline constexpr bool isLvalueReference() { return IsLvalueReference_<T>::value; }
|
jpayne@69
|
473
|
jpayne@69
|
474 template <typename T> struct Decay_ { typedef T Type; };
|
jpayne@69
|
475 template <typename T> struct Decay_<T&> { typedef typename Decay_<T>::Type Type; };
|
jpayne@69
|
476 template <typename T> struct Decay_<T&&> { typedef typename Decay_<T>::Type Type; };
|
jpayne@69
|
477 template <typename T> struct Decay_<T[]> { typedef typename Decay_<T*>::Type Type; };
|
jpayne@69
|
478 template <typename T> struct Decay_<const T[]> { typedef typename Decay_<const T*>::Type Type; };
|
jpayne@69
|
479 template <typename T, size_t s> struct Decay_<T[s]> { typedef typename Decay_<T*>::Type Type; };
|
jpayne@69
|
480 template <typename T, size_t s> struct Decay_<const T[s]> { typedef typename Decay_<const T*>::Type Type; };
|
jpayne@69
|
481 template <typename T> struct Decay_<const T> { typedef typename Decay_<T>::Type Type; };
|
jpayne@69
|
482 template <typename T> struct Decay_<volatile T> { typedef typename Decay_<T>::Type Type; };
|
jpayne@69
|
483 template <typename T> using Decay = typename Decay_<T>::Type;
|
jpayne@69
|
484
|
jpayne@69
|
485 template <bool b> struct EnableIf_;
|
jpayne@69
|
486 template <> struct EnableIf_<true> { typedef void Type; };
|
jpayne@69
|
487 template <bool b> using EnableIf = typename EnableIf_<b>::Type;
|
jpayne@69
|
488 // Use like:
|
jpayne@69
|
489 //
|
jpayne@69
|
490 // template <typename T, typename = EnableIf<isValid<T>()>>
|
jpayne@69
|
491 // void func(T&& t);
|
jpayne@69
|
492
|
jpayne@69
|
493 template <typename...> struct VoidSfinae_ { using Type = void; };
|
jpayne@69
|
494 template <typename... Ts> using VoidSfinae = typename VoidSfinae_<Ts...>::Type;
|
jpayne@69
|
495 // Note: VoidSfinae is std::void_t from C++17.
|
jpayne@69
|
496
|
jpayne@69
|
497 template <typename T>
|
jpayne@69
|
498 T instance() noexcept;
|
jpayne@69
|
499 // Like std::declval, but doesn't transform T into an rvalue reference. If you want that, specify
|
jpayne@69
|
500 // instance<T&&>().
|
jpayne@69
|
501
|
jpayne@69
|
502 struct DisallowConstCopy {
|
jpayne@69
|
503 // Inherit from this, or declare a member variable of this type, to prevent the class from being
|
jpayne@69
|
504 // copyable from a const reference -- instead, it will only be copyable from non-const references.
|
jpayne@69
|
505 // This is useful for enforcing transitive constness of contained pointers.
|
jpayne@69
|
506 //
|
jpayne@69
|
507 // For example, say you have a type T which contains a pointer. T has non-const methods which
|
jpayne@69
|
508 // modify the value at that pointer, but T's const methods are designed to allow reading only.
|
jpayne@69
|
509 // Unfortunately, if T has a regular copy constructor, someone can simply make a copy of T and
|
jpayne@69
|
510 // then use it to modify the pointed-to value. However, if T inherits DisallowConstCopy, then
|
jpayne@69
|
511 // callers will only be able to copy non-const instances of T. Ideally, there is some
|
jpayne@69
|
512 // parallel type ImmutableT which is like a version of T that only has const methods, and can
|
jpayne@69
|
513 // be copied from a const T.
|
jpayne@69
|
514 //
|
jpayne@69
|
515 // Note that due to C++ rules about implicit copy constructors and assignment operators, any
|
jpayne@69
|
516 // type that contains or inherits from a type that disallows const copies will also automatically
|
jpayne@69
|
517 // disallow const copies. Hey, cool, that's exactly what we want.
|
jpayne@69
|
518
|
jpayne@69
|
519 #if CAPNP_DEBUG_TYPES
|
jpayne@69
|
520 // Alas! Declaring a defaulted non-const copy constructor tickles a bug which causes GCC and
|
jpayne@69
|
521 // Clang to disagree on ABI, using different calling conventions to pass this type, leading to
|
jpayne@69
|
522 // immediate segfaults. See:
|
jpayne@69
|
523 // https://bugs.llvm.org/show_bug.cgi?id=23764
|
jpayne@69
|
524 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58074
|
jpayne@69
|
525 //
|
jpayne@69
|
526 // Because of this, we can't use this technique. We guard it by CAPNP_DEBUG_TYPES so that it
|
jpayne@69
|
527 // still applies to the Cap'n Proto developers during internal testing.
|
jpayne@69
|
528
|
jpayne@69
|
529 DisallowConstCopy() = default;
|
jpayne@69
|
530 DisallowConstCopy(DisallowConstCopy&) = default;
|
jpayne@69
|
531 DisallowConstCopy(DisallowConstCopy&&) = default;
|
jpayne@69
|
532 DisallowConstCopy& operator=(DisallowConstCopy&) = default;
|
jpayne@69
|
533 DisallowConstCopy& operator=(DisallowConstCopy&&) = default;
|
jpayne@69
|
534 #endif
|
jpayne@69
|
535 };
|
jpayne@69
|
536
|
jpayne@69
|
537 #if _MSC_VER && !defined(__clang__)
|
jpayne@69
|
538
|
jpayne@69
|
539 #define KJ_CPCAP(obj) obj=::kj::cp(obj)
|
jpayne@69
|
540 // TODO(msvc): MSVC refuses to invoke non-const versions of copy constructors in by-value lambda
|
jpayne@69
|
541 // captures. Wrap your captured object in this macro to force the compiler to perform a copy.
|
jpayne@69
|
542 // Example:
|
jpayne@69
|
543 //
|
jpayne@69
|
544 // struct Foo: DisallowConstCopy {};
|
jpayne@69
|
545 // Foo foo;
|
jpayne@69
|
546 // auto lambda = [KJ_CPCAP(foo)] {};
|
jpayne@69
|
547
|
jpayne@69
|
548 #else
|
jpayne@69
|
549
|
jpayne@69
|
550 #define KJ_CPCAP(obj) obj
|
jpayne@69
|
551 // Clang and gcc both already perform copy capturing correctly with non-const copy constructors.
|
jpayne@69
|
552
|
jpayne@69
|
553 #endif
|
jpayne@69
|
554
|
jpayne@69
|
555 template <typename T>
|
jpayne@69
|
556 struct DisallowConstCopyIfNotConst: public DisallowConstCopy {
|
jpayne@69
|
557 // Inherit from this when implementing a template that contains a pointer to T and which should
|
jpayne@69
|
558 // enforce transitive constness. If T is a const type, this has no effect. Otherwise, it is
|
jpayne@69
|
559 // an alias for DisallowConstCopy.
|
jpayne@69
|
560 };
|
jpayne@69
|
561
|
jpayne@69
|
562 template <typename T>
|
jpayne@69
|
563 struct DisallowConstCopyIfNotConst<const T> {};
|
jpayne@69
|
564
|
jpayne@69
|
565 template <typename T> struct IsConst_ { static constexpr bool value = false; };
|
jpayne@69
|
566 template <typename T> struct IsConst_<const T> { static constexpr bool value = true; };
|
jpayne@69
|
567 template <typename T> constexpr bool isConst() { return IsConst_<T>::value; }
|
jpayne@69
|
568
|
jpayne@69
|
569 template <typename T> struct EnableIfNotConst_ { typedef T Type; };
|
jpayne@69
|
570 template <typename T> struct EnableIfNotConst_<const T>;
|
jpayne@69
|
571 template <typename T> using EnableIfNotConst = typename EnableIfNotConst_<T>::Type;
|
jpayne@69
|
572
|
jpayne@69
|
573 template <typename T> struct EnableIfConst_;
|
jpayne@69
|
574 template <typename T> struct EnableIfConst_<const T> { typedef T Type; };
|
jpayne@69
|
575 template <typename T> using EnableIfConst = typename EnableIfConst_<T>::Type;
|
jpayne@69
|
576
|
jpayne@69
|
577 template <typename T> struct RemoveConstOrDisable_ { struct Type; };
|
jpayne@69
|
578 template <typename T> struct RemoveConstOrDisable_<const T> { typedef T Type; };
|
jpayne@69
|
579 template <typename T> using RemoveConstOrDisable = typename RemoveConstOrDisable_<T>::Type;
|
jpayne@69
|
580
|
jpayne@69
|
581 template <typename T> struct IsReference_ { static constexpr bool value = false; };
|
jpayne@69
|
582 template <typename T> struct IsReference_<T&> { static constexpr bool value = true; };
|
jpayne@69
|
583 template <typename T> constexpr bool isReference() { return IsReference_<T>::value; }
|
jpayne@69
|
584
|
jpayne@69
|
585 template <typename From, typename To>
|
jpayne@69
|
586 struct PropagateConst_ { typedef To Type; };
|
jpayne@69
|
587 template <typename From, typename To>
|
jpayne@69
|
588 struct PropagateConst_<const From, To> { typedef const To Type; };
|
jpayne@69
|
589 template <typename From, typename To>
|
jpayne@69
|
590 using PropagateConst = typename PropagateConst_<From, To>::Type;
|
jpayne@69
|
591
|
jpayne@69
|
592 namespace _ { // private
|
jpayne@69
|
593
|
jpayne@69
|
594 template <typename T>
|
jpayne@69
|
595 T refIfLvalue(T&&);
|
jpayne@69
|
596
|
jpayne@69
|
597 } // namespace _ (private)
|
jpayne@69
|
598
|
jpayne@69
|
599 #define KJ_DECLTYPE_REF(exp) decltype(::kj::_::refIfLvalue(exp))
|
jpayne@69
|
600 // Like decltype(exp), but if exp is an lvalue, produces a reference type.
|
jpayne@69
|
601 //
|
jpayne@69
|
602 // int i;
|
jpayne@69
|
603 // decltype(i) i1(i); // i1 has type int.
|
jpayne@69
|
604 // KJ_DECLTYPE_REF(i + 1) i2(i + 1); // i2 has type int.
|
jpayne@69
|
605 // KJ_DECLTYPE_REF(i) i3(i); // i3 has type int&.
|
jpayne@69
|
606 // KJ_DECLTYPE_REF(kj::mv(i)) i4(kj::mv(i)); // i4 has type int.
|
jpayne@69
|
607
|
jpayne@69
|
608 template <typename T, typename U> struct IsSameType_ { static constexpr bool value = false; };
|
jpayne@69
|
609 template <typename T> struct IsSameType_<T, T> { static constexpr bool value = true; };
|
jpayne@69
|
610 template <typename T, typename U> constexpr bool isSameType() { return IsSameType_<T, U>::value; }
|
jpayne@69
|
611
|
jpayne@69
|
612 template <typename T> constexpr bool isIntegral() { return false; }
|
jpayne@69
|
613 template <> constexpr bool isIntegral<char>() { return true; }
|
jpayne@69
|
614 template <> constexpr bool isIntegral<signed char>() { return true; }
|
jpayne@69
|
615 template <> constexpr bool isIntegral<short>() { return true; }
|
jpayne@69
|
616 template <> constexpr bool isIntegral<int>() { return true; }
|
jpayne@69
|
617 template <> constexpr bool isIntegral<long>() { return true; }
|
jpayne@69
|
618 template <> constexpr bool isIntegral<long long>() { return true; }
|
jpayne@69
|
619 template <> constexpr bool isIntegral<unsigned char>() { return true; }
|
jpayne@69
|
620 template <> constexpr bool isIntegral<unsigned short>() { return true; }
|
jpayne@69
|
621 template <> constexpr bool isIntegral<unsigned int>() { return true; }
|
jpayne@69
|
622 template <> constexpr bool isIntegral<unsigned long>() { return true; }
|
jpayne@69
|
623 template <> constexpr bool isIntegral<unsigned long long>() { return true; }
|
jpayne@69
|
624
|
jpayne@69
|
625 template <typename T>
|
jpayne@69
|
626 struct CanConvert_ {
|
jpayne@69
|
627 static int sfinae(T);
|
jpayne@69
|
628 static bool sfinae(...);
|
jpayne@69
|
629 };
|
jpayne@69
|
630
|
jpayne@69
|
631 template <typename T, typename U>
|
jpayne@69
|
632 constexpr bool canConvert() {
|
jpayne@69
|
633 return sizeof(CanConvert_<U>::sfinae(instance<T>())) == sizeof(int);
|
jpayne@69
|
634 }
|
jpayne@69
|
635
|
jpayne@69
|
636 #if __GNUC__ && !__clang__ && __GNUC__ < 5
|
jpayne@69
|
637 template <typename T>
|
jpayne@69
|
638 constexpr bool canMemcpy() {
|
jpayne@69
|
639 // Returns true if T can be copied using memcpy instead of using the copy constructor or
|
jpayne@69
|
640 // assignment operator.
|
jpayne@69
|
641
|
jpayne@69
|
642 // GCC 4 does not have __is_trivially_constructible and friends, and there doesn't seem to be
|
jpayne@69
|
643 // any reliable alternative. __has_trivial_copy() and __has_trivial_assign() return the right
|
jpayne@69
|
644 // thing at one point but later on they changed such that a deleted copy constructor was
|
jpayne@69
|
645 // considered "trivial" (apparently technically correct, though useless). So, on GCC 4 we give up
|
jpayne@69
|
646 // and assume we can't memcpy() at all, and must explicitly copy-construct everything.
|
jpayne@69
|
647 return false;
|
jpayne@69
|
648 }
|
jpayne@69
|
649 #define KJ_ASSERT_CAN_MEMCPY(T)
|
jpayne@69
|
650 #else
|
jpayne@69
|
651 template <typename T>
|
jpayne@69
|
652 constexpr bool canMemcpy() {
|
jpayne@69
|
653 // Returns true if T can be copied using memcpy instead of using the copy constructor or
|
jpayne@69
|
654 // assignment operator.
|
jpayne@69
|
655
|
jpayne@69
|
656 return __is_trivially_constructible(T, const T&) && __is_trivially_assignable(T, const T&);
|
jpayne@69
|
657 }
|
jpayne@69
|
658 #define KJ_ASSERT_CAN_MEMCPY(T) \
|
jpayne@69
|
659 static_assert(kj::canMemcpy<T>(), "this code expects this type to be memcpy()-able");
|
jpayne@69
|
660 #endif
|
jpayne@69
|
661
|
jpayne@69
|
662 template <typename T>
|
jpayne@69
|
663 class Badge {
|
jpayne@69
|
664 // A pattern for marking individual methods such that they can only be called from a specific
|
jpayne@69
|
665 // caller class: Make the method public but give it a parameter of type `Badge<Caller>`. Only
|
jpayne@69
|
666 // `Caller` can construct one, so only `Caller` can call the method.
|
jpayne@69
|
667 //
|
jpayne@69
|
668 // // We only allow calls from the class `Bar`.
|
jpayne@69
|
669 // void foo(Badge<Bar>)
|
jpayne@69
|
670 //
|
jpayne@69
|
671 // The call site looks like:
|
jpayne@69
|
672 //
|
jpayne@69
|
673 // foo({});
|
jpayne@69
|
674 //
|
jpayne@69
|
675 // This pattern also works well for declaring private constructors, but still being able to use
|
jpayne@69
|
676 // them with `kj::heap()`, etc.
|
jpayne@69
|
677 //
|
jpayne@69
|
678 // Idea from: https://awesomekling.github.io/Serenity-C++-patterns-The-Badge/
|
jpayne@69
|
679 //
|
jpayne@69
|
680 // Note that some forms of this idea make the copy constructor private as well, in order to
|
jpayne@69
|
681 // prohibit `Badge<NotMe>(*(Badge<NotMe>*)nullptr)`. However, that would prevent badges from
|
jpayne@69
|
682 // being passed through forwarding functions like `kj::heap()`, which would ruin one of the main
|
jpayne@69
|
683 // use cases for this pattern in KJ. In any case, dereferencing a null pointer is UB; there are
|
jpayne@69
|
684 // plenty of other ways to get access to private members if you're willing to go UB. For one-off
|
jpayne@69
|
685 // debugging purposes, you might as well use `#define private public` at the top of the file.
|
jpayne@69
|
686 private:
|
jpayne@69
|
687 Badge() {}
|
jpayne@69
|
688 friend T;
|
jpayne@69
|
689 };
|
jpayne@69
|
690
|
jpayne@69
|
691 // =======================================================================================
|
jpayne@69
|
692 // Equivalents to std::move() and std::forward(), since these are very commonly needed and the
|
jpayne@69
|
693 // std header <utility> pulls in lots of other stuff.
|
jpayne@69
|
694 //
|
jpayne@69
|
695 // We use abbreviated names mv and fwd because these helpers (especially mv) are so commonly used
|
jpayne@69
|
696 // that the cost of typing more letters outweighs the cost of being slightly harder to understand
|
jpayne@69
|
697 // when first encountered.
|
jpayne@69
|
698
|
jpayne@69
|
699 template<typename T> constexpr T&& mv(T& t) noexcept { return static_cast<T&&>(t); }
|
jpayne@69
|
700 template<typename T> constexpr T&& fwd(NoInfer<T>& t) noexcept { return static_cast<T&&>(t); }
|
jpayne@69
|
701
|
jpayne@69
|
702 template<typename T> constexpr T cp(T& t) noexcept { return t; }
|
jpayne@69
|
703 template<typename T> constexpr T cp(const T& t) noexcept { return t; }
|
jpayne@69
|
704 // Useful to force a copy, particularly to pass into a function that expects T&&.
|
jpayne@69
|
705
|
jpayne@69
|
706 template <typename T, typename U, bool takeT, bool uOK = true> struct ChooseType_;
|
jpayne@69
|
707 template <typename T, typename U> struct ChooseType_<T, U, true, true> { typedef T Type; };
|
jpayne@69
|
708 template <typename T, typename U> struct ChooseType_<T, U, true, false> { typedef T Type; };
|
jpayne@69
|
709 template <typename T, typename U> struct ChooseType_<T, U, false, true> { typedef U Type; };
|
jpayne@69
|
710
|
jpayne@69
|
711 template <typename T, typename U>
|
jpayne@69
|
712 using WiderType = typename ChooseType_<T, U, sizeof(T) >= sizeof(U)>::Type;
|
jpayne@69
|
713
|
jpayne@69
|
714 template <typename T, typename U>
|
jpayne@69
|
715 inline constexpr auto min(T&& a, U&& b) -> WiderType<Decay<T>, Decay<U>> {
|
jpayne@69
|
716 return a < b ? WiderType<Decay<T>, Decay<U>>(a) : WiderType<Decay<T>, Decay<U>>(b);
|
jpayne@69
|
717 }
|
jpayne@69
|
718
|
jpayne@69
|
719 template <typename T, typename U>
|
jpayne@69
|
720 inline constexpr auto max(T&& a, U&& b) -> WiderType<Decay<T>, Decay<U>> {
|
jpayne@69
|
721 return a > b ? WiderType<Decay<T>, Decay<U>>(a) : WiderType<Decay<T>, Decay<U>>(b);
|
jpayne@69
|
722 }
|
jpayne@69
|
723
|
jpayne@69
|
724 template <typename T, size_t s>
|
jpayne@69
|
725 inline constexpr size_t size(T (&arr)[s]) { return s; }
|
jpayne@69
|
726 template <typename T>
|
jpayne@69
|
727 inline constexpr size_t size(T&& arr) { return arr.size(); }
|
jpayne@69
|
728 // Returns the size of the parameter, whether the parameter is a regular C array or a container
|
jpayne@69
|
729 // with a `.size()` method.
|
jpayne@69
|
730
|
jpayne@69
|
731 class MaxValue_ {
|
jpayne@69
|
732 private:
|
jpayne@69
|
733 template <typename T>
|
jpayne@69
|
734 inline constexpr T maxSigned() const {
|
jpayne@69
|
735 return (1ull << (sizeof(T) * 8 - 1)) - 1;
|
jpayne@69
|
736 }
|
jpayne@69
|
737 template <typename T>
|
jpayne@69
|
738 inline constexpr T maxUnsigned() const {
|
jpayne@69
|
739 return ~static_cast<T>(0u);
|
jpayne@69
|
740 }
|
jpayne@69
|
741
|
jpayne@69
|
742 public:
|
jpayne@69
|
743 #define _kJ_HANDLE_TYPE(T) \
|
jpayne@69
|
744 inline constexpr operator signed T() const { return MaxValue_::maxSigned < signed T>(); } \
|
jpayne@69
|
745 inline constexpr operator unsigned T() const { return MaxValue_::maxUnsigned<unsigned T>(); }
|
jpayne@69
|
746 _kJ_HANDLE_TYPE(char)
|
jpayne@69
|
747 _kJ_HANDLE_TYPE(short)
|
jpayne@69
|
748 _kJ_HANDLE_TYPE(int)
|
jpayne@69
|
749 _kJ_HANDLE_TYPE(long)
|
jpayne@69
|
750 _kJ_HANDLE_TYPE(long long)
|
jpayne@69
|
751 #undef _kJ_HANDLE_TYPE
|
jpayne@69
|
752
|
jpayne@69
|
753 inline constexpr operator char() const {
|
jpayne@69
|
754 // `char` is different from both `signed char` and `unsigned char`, and may be signed or
|
jpayne@69
|
755 // unsigned on different platforms. Ugh.
|
jpayne@69
|
756 return char(-1) < 0 ? MaxValue_::maxSigned<char>()
|
jpayne@69
|
757 : MaxValue_::maxUnsigned<char>();
|
jpayne@69
|
758 }
|
jpayne@69
|
759 };
|
jpayne@69
|
760
|
jpayne@69
|
761 class MinValue_ {
|
jpayne@69
|
762 private:
|
jpayne@69
|
763 template <typename T>
|
jpayne@69
|
764 inline constexpr T minSigned() const {
|
jpayne@69
|
765 return 1ull << (sizeof(T) * 8 - 1);
|
jpayne@69
|
766 }
|
jpayne@69
|
767 template <typename T>
|
jpayne@69
|
768 inline constexpr T minUnsigned() const {
|
jpayne@69
|
769 return 0u;
|
jpayne@69
|
770 }
|
jpayne@69
|
771
|
jpayne@69
|
772 public:
|
jpayne@69
|
773 #define _kJ_HANDLE_TYPE(T) \
|
jpayne@69
|
774 inline constexpr operator signed T() const { return MinValue_::minSigned < signed T>(); } \
|
jpayne@69
|
775 inline constexpr operator unsigned T() const { return MinValue_::minUnsigned<unsigned T>(); }
|
jpayne@69
|
776 _kJ_HANDLE_TYPE(char)
|
jpayne@69
|
777 _kJ_HANDLE_TYPE(short)
|
jpayne@69
|
778 _kJ_HANDLE_TYPE(int)
|
jpayne@69
|
779 _kJ_HANDLE_TYPE(long)
|
jpayne@69
|
780 _kJ_HANDLE_TYPE(long long)
|
jpayne@69
|
781 #undef _kJ_HANDLE_TYPE
|
jpayne@69
|
782
|
jpayne@69
|
783 inline constexpr operator char() const {
|
jpayne@69
|
784 // `char` is different from both `signed char` and `unsigned char`, and may be signed or
|
jpayne@69
|
785 // unsigned on different platforms. Ugh.
|
jpayne@69
|
786 return char(-1) < 0 ? MinValue_::minSigned<char>()
|
jpayne@69
|
787 : MinValue_::minUnsigned<char>();
|
jpayne@69
|
788 }
|
jpayne@69
|
789 };
|
jpayne@69
|
790
|
jpayne@69
|
791 static KJ_CONSTEXPR(const) MaxValue_ maxValue = MaxValue_();
|
jpayne@69
|
792 // A special constant which, when cast to an integer type, takes on the maximum possible value of
|
jpayne@69
|
793 // that type. This is useful to use as e.g. a parameter to a function because it will be robust
|
jpayne@69
|
794 // in the face of changes to the parameter's type.
|
jpayne@69
|
795 //
|
jpayne@69
|
796 // `char` is not supported, but `signed char` and `unsigned char` are.
|
jpayne@69
|
797
|
jpayne@69
|
798 static KJ_CONSTEXPR(const) MinValue_ minValue = MinValue_();
|
jpayne@69
|
799 // A special constant which, when cast to an integer type, takes on the minimum possible value
|
jpayne@69
|
800 // of that type. This is useful to use as e.g. a parameter to a function because it will be robust
|
jpayne@69
|
801 // in the face of changes to the parameter's type.
|
jpayne@69
|
802 //
|
jpayne@69
|
803 // `char` is not supported, but `signed char` and `unsigned char` are.
|
jpayne@69
|
804
|
jpayne@69
|
805 template <typename T>
|
jpayne@69
|
806 inline bool operator==(T t, MaxValue_) { return t == Decay<T>(maxValue); }
|
jpayne@69
|
807 template <typename T>
|
jpayne@69
|
808 inline bool operator==(T t, MinValue_) { return t == Decay<T>(minValue); }
|
jpayne@69
|
809
|
jpayne@69
|
810 template <uint bits>
|
jpayne@69
|
811 inline constexpr unsigned long long maxValueForBits() {
|
jpayne@69
|
812 // Get the maximum integer representable in the given number of bits.
|
jpayne@69
|
813
|
jpayne@69
|
814 // 1ull << 64 is unfortunately undefined.
|
jpayne@69
|
815 return (bits == 64 ? 0 : (1ull << bits)) - 1;
|
jpayne@69
|
816 }
|
jpayne@69
|
817
|
jpayne@69
|
818 struct ThrowOverflow {
|
jpayne@69
|
819 // Functor which throws an exception complaining about integer overflow. Usually this is used
|
jpayne@69
|
820 // with the interfaces in units.h, but is defined here because Cap'n Proto wants to avoid
|
jpayne@69
|
821 // including units.h when not using CAPNP_DEBUG_TYPES.
|
jpayne@69
|
822 [[noreturn]] void operator()() const;
|
jpayne@69
|
823 };
|
jpayne@69
|
824
|
jpayne@69
|
825 #if __GNUC__ || __clang__ || _MSC_VER
|
jpayne@69
|
826 inline constexpr float inf() { return __builtin_huge_valf(); }
|
jpayne@69
|
827 inline constexpr float nan() { return __builtin_nanf(""); }
|
jpayne@69
|
828
|
jpayne@69
|
829 #else
|
jpayne@69
|
830 #error "Not sure how to support your compiler."
|
jpayne@69
|
831 #endif
|
jpayne@69
|
832
|
jpayne@69
|
833 inline constexpr bool isNaN(float f) { return f != f; }
|
jpayne@69
|
834 inline constexpr bool isNaN(double f) { return f != f; }
|
jpayne@69
|
835
|
jpayne@69
|
836 inline int popCount(unsigned int x) {
|
jpayne@69
|
837 #if defined(_MSC_VER) && !defined(__clang__)
|
jpayne@69
|
838 return __popcnt(x);
|
jpayne@69
|
839 // Note: __popcnt returns unsigned int, but the value is clearly guaranteed to fit into an int
|
jpayne@69
|
840 #else
|
jpayne@69
|
841 return __builtin_popcount(x);
|
jpayne@69
|
842 #endif
|
jpayne@69
|
843 }
|
jpayne@69
|
844
|
jpayne@69
|
845 // =======================================================================================
|
jpayne@69
|
846 // Useful fake containers
|
jpayne@69
|
847
|
jpayne@69
|
848 template <typename T>
|
jpayne@69
|
849 class Range {
|
jpayne@69
|
850 public:
|
jpayne@69
|
851 inline constexpr Range(const T& begin, const T& end): begin_(begin), end_(end) {}
|
jpayne@69
|
852 inline explicit constexpr Range(const T& end): begin_(0), end_(end) {}
|
jpayne@69
|
853
|
jpayne@69
|
854 class Iterator {
|
jpayne@69
|
855 public:
|
jpayne@69
|
856 Iterator() = default;
|
jpayne@69
|
857 inline Iterator(const T& value): value(value) {}
|
jpayne@69
|
858
|
jpayne@69
|
859 inline const T& operator* () const { return value; }
|
jpayne@69
|
860 inline const T& operator[](size_t index) const { return value + index; }
|
jpayne@69
|
861 inline Iterator& operator++() { ++value; return *this; }
|
jpayne@69
|
862 inline Iterator operator++(int) { return Iterator(value++); }
|
jpayne@69
|
863 inline Iterator& operator--() { --value; return *this; }
|
jpayne@69
|
864 inline Iterator operator--(int) { return Iterator(value--); }
|
jpayne@69
|
865 inline Iterator& operator+=(ptrdiff_t amount) { value += amount; return *this; }
|
jpayne@69
|
866 inline Iterator& operator-=(ptrdiff_t amount) { value -= amount; return *this; }
|
jpayne@69
|
867 inline Iterator operator+ (ptrdiff_t amount) const { return Iterator(value + amount); }
|
jpayne@69
|
868 inline Iterator operator- (ptrdiff_t amount) const { return Iterator(value - amount); }
|
jpayne@69
|
869 inline ptrdiff_t operator- (const Iterator& other) const { return value - other.value; }
|
jpayne@69
|
870
|
jpayne@69
|
871 inline bool operator==(const Iterator& other) const { return value == other.value; }
|
jpayne@69
|
872 inline bool operator!=(const Iterator& other) const { return value != other.value; }
|
jpayne@69
|
873 inline bool operator<=(const Iterator& other) const { return value <= other.value; }
|
jpayne@69
|
874 inline bool operator>=(const Iterator& other) const { return value >= other.value; }
|
jpayne@69
|
875 inline bool operator< (const Iterator& other) const { return value < other.value; }
|
jpayne@69
|
876 inline bool operator> (const Iterator& other) const { return value > other.value; }
|
jpayne@69
|
877
|
jpayne@69
|
878 private:
|
jpayne@69
|
879 T value;
|
jpayne@69
|
880 };
|
jpayne@69
|
881
|
jpayne@69
|
882 inline Iterator begin() const { return Iterator(begin_); }
|
jpayne@69
|
883 inline Iterator end() const { return Iterator(end_); }
|
jpayne@69
|
884
|
jpayne@69
|
885 inline auto size() const -> decltype(instance<T>() - instance<T>()) { return end_ - begin_; }
|
jpayne@69
|
886
|
jpayne@69
|
887 private:
|
jpayne@69
|
888 T begin_;
|
jpayne@69
|
889 T end_;
|
jpayne@69
|
890 };
|
jpayne@69
|
891
|
jpayne@69
|
892 template <typename T, typename U>
|
jpayne@69
|
893 inline constexpr Range<WiderType<Decay<T>, Decay<U>>> range(T begin, U end) {
|
jpayne@69
|
894 return Range<WiderType<Decay<T>, Decay<U>>>(begin, end);
|
jpayne@69
|
895 }
|
jpayne@69
|
896
|
jpayne@69
|
897 template <typename T>
|
jpayne@69
|
898 inline constexpr Range<Decay<T>> range(T begin, T end) { return Range<Decay<T>>(begin, end); }
|
jpayne@69
|
899 // Returns a fake iterable container containing all values of T from `begin` (inclusive) to `end`
|
jpayne@69
|
900 // (exclusive). Example:
|
jpayne@69
|
901 //
|
jpayne@69
|
902 // // Prints 1, 2, 3, 4, 5, 6, 7, 8, 9.
|
jpayne@69
|
903 // for (int i: kj::range(1, 10)) { print(i); }
|
jpayne@69
|
904
|
jpayne@69
|
905 template <typename T>
|
jpayne@69
|
906 inline constexpr Range<Decay<T>> zeroTo(T end) { return Range<Decay<T>>(end); }
|
jpayne@69
|
907 // Returns a fake iterable container containing all values of T from zero (inclusive) to `end`
|
jpayne@69
|
908 // (exclusive). Example:
|
jpayne@69
|
909 //
|
jpayne@69
|
910 // // Prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
|
jpayne@69
|
911 // for (int i: kj::zeroTo(10)) { print(i); }
|
jpayne@69
|
912
|
jpayne@69
|
913 template <typename T>
|
jpayne@69
|
914 inline constexpr Range<size_t> indices(T&& container) {
|
jpayne@69
|
915 // Shortcut for iterating over the indices of a container:
|
jpayne@69
|
916 //
|
jpayne@69
|
917 // for (size_t i: kj::indices(myArray)) { handle(myArray[i]); }
|
jpayne@69
|
918
|
jpayne@69
|
919 return range<size_t>(0, kj::size(container));
|
jpayne@69
|
920 }
|
jpayne@69
|
921
|
jpayne@69
|
922 template <typename T>
|
jpayne@69
|
923 class Repeat {
|
jpayne@69
|
924 public:
|
jpayne@69
|
925 inline constexpr Repeat(const T& value, size_t count): value(value), count(count) {}
|
jpayne@69
|
926
|
jpayne@69
|
927 class Iterator {
|
jpayne@69
|
928 public:
|
jpayne@69
|
929 Iterator() = default;
|
jpayne@69
|
930 inline Iterator(const T& value, size_t index): value(value), index(index) {}
|
jpayne@69
|
931
|
jpayne@69
|
932 inline const T& operator* () const { return value; }
|
jpayne@69
|
933 inline const T& operator[](ptrdiff_t index) const { return value; }
|
jpayne@69
|
934 inline Iterator& operator++() { ++index; return *this; }
|
jpayne@69
|
935 inline Iterator operator++(int) { return Iterator(value, index++); }
|
jpayne@69
|
936 inline Iterator& operator--() { --index; return *this; }
|
jpayne@69
|
937 inline Iterator operator--(int) { return Iterator(value, index--); }
|
jpayne@69
|
938 inline Iterator& operator+=(ptrdiff_t amount) { index += amount; return *this; }
|
jpayne@69
|
939 inline Iterator& operator-=(ptrdiff_t amount) { index -= amount; return *this; }
|
jpayne@69
|
940 inline Iterator operator+ (ptrdiff_t amount) const { return Iterator(value, index + amount); }
|
jpayne@69
|
941 inline Iterator operator- (ptrdiff_t amount) const { return Iterator(value, index - amount); }
|
jpayne@69
|
942 inline ptrdiff_t operator- (const Iterator& other) const { return index - other.index; }
|
jpayne@69
|
943
|
jpayne@69
|
944 inline bool operator==(const Iterator& other) const { return index == other.index; }
|
jpayne@69
|
945 inline bool operator!=(const Iterator& other) const { return index != other.index; }
|
jpayne@69
|
946 inline bool operator<=(const Iterator& other) const { return index <= other.index; }
|
jpayne@69
|
947 inline bool operator>=(const Iterator& other) const { return index >= other.index; }
|
jpayne@69
|
948 inline bool operator< (const Iterator& other) const { return index < other.index; }
|
jpayne@69
|
949 inline bool operator> (const Iterator& other) const { return index > other.index; }
|
jpayne@69
|
950
|
jpayne@69
|
951 private:
|
jpayne@69
|
952 T value;
|
jpayne@69
|
953 size_t index;
|
jpayne@69
|
954 };
|
jpayne@69
|
955
|
jpayne@69
|
956 inline Iterator begin() const { return Iterator(value, 0); }
|
jpayne@69
|
957 inline Iterator end() const { return Iterator(value, count); }
|
jpayne@69
|
958
|
jpayne@69
|
959 inline size_t size() const { return count; }
|
jpayne@69
|
960 inline const T& operator[](ptrdiff_t) const { return value; }
|
jpayne@69
|
961
|
jpayne@69
|
962 private:
|
jpayne@69
|
963 T value;
|
jpayne@69
|
964 size_t count;
|
jpayne@69
|
965 };
|
jpayne@69
|
966
|
jpayne@69
|
967 template <typename T>
|
jpayne@69
|
968 inline constexpr Repeat<Decay<T>> repeat(T&& value, size_t count) {
|
jpayne@69
|
969 // Returns a fake iterable which contains `count` repeats of `value`. Useful for e.g. creating
|
jpayne@69
|
970 // a bunch of spaces: `kj::repeat(' ', indent * 2)`
|
jpayne@69
|
971
|
jpayne@69
|
972 return Repeat<Decay<T>>(value, count);
|
jpayne@69
|
973 }
|
jpayne@69
|
974
|
jpayne@69
|
975 template <typename Inner, class Mapping>
|
jpayne@69
|
976 class MappedIterator: private Mapping {
|
jpayne@69
|
977 // An iterator that wraps some other iterator and maps the values through a mapping function.
|
jpayne@69
|
978 // The type `Mapping` must define a method `map()` which performs this mapping.
|
jpayne@69
|
979
|
jpayne@69
|
980 public:
|
jpayne@69
|
981 template <typename... Params>
|
jpayne@69
|
982 MappedIterator(Inner inner, Params&&... params)
|
jpayne@69
|
983 : Mapping(kj::fwd<Params>(params)...), inner(inner) {}
|
jpayne@69
|
984
|
jpayne@69
|
985 inline auto operator->() const { return &Mapping::map(*inner); }
|
jpayne@69
|
986 inline decltype(auto) operator* () const { return Mapping::map(*inner); }
|
jpayne@69
|
987 inline decltype(auto) operator[](size_t index) const { return Mapping::map(inner[index]); }
|
jpayne@69
|
988 inline MappedIterator& operator++() { ++inner; return *this; }
|
jpayne@69
|
989 inline MappedIterator operator++(int) { return MappedIterator(inner++, *this); }
|
jpayne@69
|
990 inline MappedIterator& operator--() { --inner; return *this; }
|
jpayne@69
|
991 inline MappedIterator operator--(int) { return MappedIterator(inner--, *this); }
|
jpayne@69
|
992 inline MappedIterator& operator+=(ptrdiff_t amount) { inner += amount; return *this; }
|
jpayne@69
|
993 inline MappedIterator& operator-=(ptrdiff_t amount) { inner -= amount; return *this; }
|
jpayne@69
|
994 inline MappedIterator operator+ (ptrdiff_t amount) const {
|
jpayne@69
|
995 return MappedIterator(inner + amount, *this);
|
jpayne@69
|
996 }
|
jpayne@69
|
997 inline MappedIterator operator- (ptrdiff_t amount) const {
|
jpayne@69
|
998 return MappedIterator(inner - amount, *this);
|
jpayne@69
|
999 }
|
jpayne@69
|
1000 inline ptrdiff_t operator- (const MappedIterator& other) const { return inner - other.inner; }
|
jpayne@69
|
1001
|
jpayne@69
|
1002 inline bool operator==(const MappedIterator& other) const { return inner == other.inner; }
|
jpayne@69
|
1003 inline bool operator!=(const MappedIterator& other) const { return inner != other.inner; }
|
jpayne@69
|
1004 inline bool operator<=(const MappedIterator& other) const { return inner <= other.inner; }
|
jpayne@69
|
1005 inline bool operator>=(const MappedIterator& other) const { return inner >= other.inner; }
|
jpayne@69
|
1006 inline bool operator< (const MappedIterator& other) const { return inner < other.inner; }
|
jpayne@69
|
1007 inline bool operator> (const MappedIterator& other) const { return inner > other.inner; }
|
jpayne@69
|
1008
|
jpayne@69
|
1009 private:
|
jpayne@69
|
1010 Inner inner;
|
jpayne@69
|
1011 };
|
jpayne@69
|
1012
|
jpayne@69
|
1013 template <typename Inner, typename Mapping>
|
jpayne@69
|
1014 class MappedIterable: private Mapping {
|
jpayne@69
|
1015 // An iterable that wraps some other iterable and maps the values through a mapping function.
|
jpayne@69
|
1016 // The type `Mapping` must define a method `map()` which performs this mapping.
|
jpayne@69
|
1017
|
jpayne@69
|
1018 public:
|
jpayne@69
|
1019 template <typename... Params>
|
jpayne@69
|
1020 MappedIterable(Inner inner, Params&&... params)
|
jpayne@69
|
1021 : Mapping(kj::fwd<Params>(params)...), inner(inner) {}
|
jpayne@69
|
1022
|
jpayne@69
|
1023 typedef Decay<decltype(instance<Inner>().begin())> InnerIterator;
|
jpayne@69
|
1024 typedef MappedIterator<InnerIterator, Mapping> Iterator;
|
jpayne@69
|
1025 typedef Decay<decltype(instance<const Inner>().begin())> InnerConstIterator;
|
jpayne@69
|
1026 typedef MappedIterator<InnerConstIterator, Mapping> ConstIterator;
|
jpayne@69
|
1027
|
jpayne@69
|
1028 inline Iterator begin() { return { inner.begin(), (Mapping&)*this }; }
|
jpayne@69
|
1029 inline Iterator end() { return { inner.end(), (Mapping&)*this }; }
|
jpayne@69
|
1030 inline ConstIterator begin() const { return { inner.begin(), (const Mapping&)*this }; }
|
jpayne@69
|
1031 inline ConstIterator end() const { return { inner.end(), (const Mapping&)*this }; }
|
jpayne@69
|
1032
|
jpayne@69
|
1033 private:
|
jpayne@69
|
1034 Inner inner;
|
jpayne@69
|
1035 };
|
jpayne@69
|
1036
|
jpayne@69
|
1037 // =======================================================================================
|
jpayne@69
|
1038 // Manually invoking constructors and destructors
|
jpayne@69
|
1039 //
|
jpayne@69
|
1040 // ctor(x, ...) and dtor(x) invoke x's constructor or destructor, respectively.
|
jpayne@69
|
1041
|
jpayne@69
|
1042 // We want placement new, but we don't want to #include <new>. operator new cannot be defined in
|
jpayne@69
|
1043 // a namespace, and defining it globally conflicts with the definition in <new>. So we have to
|
jpayne@69
|
1044 // define a dummy type and an operator new that uses it.
|
jpayne@69
|
1045
|
jpayne@69
|
1046 namespace _ { // private
|
jpayne@69
|
1047 struct PlacementNew {};
|
jpayne@69
|
1048 } // namespace _ (private)
|
jpayne@69
|
1049 } // namespace kj
|
jpayne@69
|
1050
|
jpayne@69
|
1051 inline void* operator new(size_t, kj::_::PlacementNew, void* __p) noexcept {
|
jpayne@69
|
1052 return __p;
|
jpayne@69
|
1053 }
|
jpayne@69
|
1054
|
jpayne@69
|
1055 inline void operator delete(void*, kj::_::PlacementNew, void* __p) noexcept {}
|
jpayne@69
|
1056
|
jpayne@69
|
1057 namespace kj {
|
jpayne@69
|
1058
|
jpayne@69
|
1059 template <typename T, typename... Params>
|
jpayne@69
|
1060 inline void ctor(T& location, Params&&... params) {
|
jpayne@69
|
1061 new (_::PlacementNew(), &location) T(kj::fwd<Params>(params)...);
|
jpayne@69
|
1062 }
|
jpayne@69
|
1063
|
jpayne@69
|
1064 template <typename T>
|
jpayne@69
|
1065 inline void dtor(T& location) {
|
jpayne@69
|
1066 location.~T();
|
jpayne@69
|
1067 }
|
jpayne@69
|
1068
|
jpayne@69
|
1069 // =======================================================================================
|
jpayne@69
|
1070 // Maybe
|
jpayne@69
|
1071 //
|
jpayne@69
|
1072 // Use in cases where you want to indicate that a value may be null. Using Maybe<T&> instead of T*
|
jpayne@69
|
1073 // forces the caller to handle the null case in order to satisfy the compiler, thus reliably
|
jpayne@69
|
1074 // preventing null pointer dereferences at runtime.
|
jpayne@69
|
1075 //
|
jpayne@69
|
1076 // Maybe<T> can be implicitly constructed from T and from nullptr.
|
jpayne@69
|
1077 // To read the value of a Maybe<T>, do:
|
jpayne@69
|
1078 //
|
jpayne@69
|
1079 // KJ_IF_MAYBE(value, someFuncReturningMaybe()) {
|
jpayne@69
|
1080 // doSomething(*value);
|
jpayne@69
|
1081 // } else {
|
jpayne@69
|
1082 // maybeWasNull();
|
jpayne@69
|
1083 // }
|
jpayne@69
|
1084 //
|
jpayne@69
|
1085 // KJ_IF_MAYBE's first parameter is a variable name which will be defined within the following
|
jpayne@69
|
1086 // block. The variable will behave like a (guaranteed non-null) pointer to the Maybe's value,
|
jpayne@69
|
1087 // though it may or may not actually be a pointer.
|
jpayne@69
|
1088 //
|
jpayne@69
|
1089 // Note that Maybe<T&> actually just wraps a pointer, whereas Maybe<T> wraps a T and a boolean
|
jpayne@69
|
1090 // indicating nullness.
|
jpayne@69
|
1091
|
jpayne@69
|
1092 template <typename T>
|
jpayne@69
|
1093 class Maybe;
|
jpayne@69
|
1094
|
jpayne@69
|
1095 namespace _ { // private
|
jpayne@69
|
1096
|
jpayne@69
|
1097 template <typename T>
|
jpayne@69
|
1098 class NullableValue {
|
jpayne@69
|
1099 // Class whose interface behaves much like T*, but actually contains an instance of T and a
|
jpayne@69
|
1100 // boolean flag indicating nullness.
|
jpayne@69
|
1101
|
jpayne@69
|
1102 public:
|
jpayne@69
|
1103 inline NullableValue(NullableValue&& other)
|
jpayne@69
|
1104 : isSet(other.isSet) {
|
jpayne@69
|
1105 if (isSet) {
|
jpayne@69
|
1106 ctor(value, kj::mv(other.value));
|
jpayne@69
|
1107 }
|
jpayne@69
|
1108 }
|
jpayne@69
|
1109 inline NullableValue(const NullableValue& other)
|
jpayne@69
|
1110 : isSet(other.isSet) {
|
jpayne@69
|
1111 if (isSet) {
|
jpayne@69
|
1112 ctor(value, other.value);
|
jpayne@69
|
1113 }
|
jpayne@69
|
1114 }
|
jpayne@69
|
1115 inline NullableValue(NullableValue& other)
|
jpayne@69
|
1116 : isSet(other.isSet) {
|
jpayne@69
|
1117 if (isSet) {
|
jpayne@69
|
1118 ctor(value, other.value);
|
jpayne@69
|
1119 }
|
jpayne@69
|
1120 }
|
jpayne@69
|
1121 inline ~NullableValue()
|
jpayne@69
|
1122 #if _MSC_VER && !defined(__clang__)
|
jpayne@69
|
1123 // TODO(msvc): MSVC has a hard time with noexcept specifier expressions that are more complex
|
jpayne@69
|
1124 // than `true` or `false`. We had a workaround for VS2015, but VS2017 regressed.
|
jpayne@69
|
1125 noexcept(false)
|
jpayne@69
|
1126 #else
|
jpayne@69
|
1127 noexcept(noexcept(instance<T&>().~T()))
|
jpayne@69
|
1128 #endif
|
jpayne@69
|
1129 {
|
jpayne@69
|
1130 if (isSet) {
|
jpayne@69
|
1131 dtor(value);
|
jpayne@69
|
1132 }
|
jpayne@69
|
1133 }
|
jpayne@69
|
1134
|
jpayne@69
|
1135 inline T& operator*() & { return value; }
|
jpayne@69
|
1136 inline const T& operator*() const & { return value; }
|
jpayne@69
|
1137 inline T&& operator*() && { return kj::mv(value); }
|
jpayne@69
|
1138 inline const T&& operator*() const && { return kj::mv(value); }
|
jpayne@69
|
1139 inline T* operator->() { return &value; }
|
jpayne@69
|
1140 inline const T* operator->() const { return &value; }
|
jpayne@69
|
1141 inline operator T*() { return isSet ? &value : nullptr; }
|
jpayne@69
|
1142 inline operator const T*() const { return isSet ? &value : nullptr; }
|
jpayne@69
|
1143
|
jpayne@69
|
1144 template <typename... Params>
|
jpayne@69
|
1145 inline T& emplace(Params&&... params) {
|
jpayne@69
|
1146 if (isSet) {
|
jpayne@69
|
1147 isSet = false;
|
jpayne@69
|
1148 dtor(value);
|
jpayne@69
|
1149 }
|
jpayne@69
|
1150 ctor(value, kj::fwd<Params>(params)...);
|
jpayne@69
|
1151 isSet = true;
|
jpayne@69
|
1152 return value;
|
jpayne@69
|
1153 }
|
jpayne@69
|
1154
|
jpayne@69
|
1155 inline NullableValue(): isSet(false) {}
|
jpayne@69
|
1156 inline NullableValue(T&& t)
|
jpayne@69
|
1157 : isSet(true) {
|
jpayne@69
|
1158 ctor(value, kj::mv(t));
|
jpayne@69
|
1159 }
|
jpayne@69
|
1160 inline NullableValue(T& t)
|
jpayne@69
|
1161 : isSet(true) {
|
jpayne@69
|
1162 ctor(value, t);
|
jpayne@69
|
1163 }
|
jpayne@69
|
1164 inline NullableValue(const T& t)
|
jpayne@69
|
1165 : isSet(true) {
|
jpayne@69
|
1166 ctor(value, t);
|
jpayne@69
|
1167 }
|
jpayne@69
|
1168 template <typename U>
|
jpayne@69
|
1169 inline NullableValue(NullableValue<U>&& other)
|
jpayne@69
|
1170 : isSet(other.isSet) {
|
jpayne@69
|
1171 if (isSet) {
|
jpayne@69
|
1172 ctor(value, kj::mv(other.value));
|
jpayne@69
|
1173 }
|
jpayne@69
|
1174 }
|
jpayne@69
|
1175 template <typename U>
|
jpayne@69
|
1176 inline NullableValue(const NullableValue<U>& other)
|
jpayne@69
|
1177 : isSet(other.isSet) {
|
jpayne@69
|
1178 if (isSet) {
|
jpayne@69
|
1179 ctor(value, other.value);
|
jpayne@69
|
1180 }
|
jpayne@69
|
1181 }
|
jpayne@69
|
1182 template <typename U>
|
jpayne@69
|
1183 inline NullableValue(const NullableValue<U&>& other)
|
jpayne@69
|
1184 : isSet(other.isSet) {
|
jpayne@69
|
1185 if (isSet) {
|
jpayne@69
|
1186 ctor(value, *other.ptr);
|
jpayne@69
|
1187 }
|
jpayne@69
|
1188 }
|
jpayne@69
|
1189 inline NullableValue(decltype(nullptr)): isSet(false) {}
|
jpayne@69
|
1190
|
jpayne@69
|
1191 inline NullableValue& operator=(NullableValue&& other) {
|
jpayne@69
|
1192 if (&other != this) {
|
jpayne@69
|
1193 // Careful about throwing destructors/constructors here.
|
jpayne@69
|
1194 if (isSet) {
|
jpayne@69
|
1195 isSet = false;
|
jpayne@69
|
1196 dtor(value);
|
jpayne@69
|
1197 }
|
jpayne@69
|
1198 if (other.isSet) {
|
jpayne@69
|
1199 ctor(value, kj::mv(other.value));
|
jpayne@69
|
1200 isSet = true;
|
jpayne@69
|
1201 }
|
jpayne@69
|
1202 }
|
jpayne@69
|
1203 return *this;
|
jpayne@69
|
1204 }
|
jpayne@69
|
1205
|
jpayne@69
|
1206 inline NullableValue& operator=(NullableValue& other) {
|
jpayne@69
|
1207 if (&other != this) {
|
jpayne@69
|
1208 // Careful about throwing destructors/constructors here.
|
jpayne@69
|
1209 if (isSet) {
|
jpayne@69
|
1210 isSet = false;
|
jpayne@69
|
1211 dtor(value);
|
jpayne@69
|
1212 }
|
jpayne@69
|
1213 if (other.isSet) {
|
jpayne@69
|
1214 ctor(value, other.value);
|
jpayne@69
|
1215 isSet = true;
|
jpayne@69
|
1216 }
|
jpayne@69
|
1217 }
|
jpayne@69
|
1218 return *this;
|
jpayne@69
|
1219 }
|
jpayne@69
|
1220
|
jpayne@69
|
1221 inline NullableValue& operator=(const NullableValue& other) {
|
jpayne@69
|
1222 if (&other != this) {
|
jpayne@69
|
1223 // Careful about throwing destructors/constructors here.
|
jpayne@69
|
1224 if (isSet) {
|
jpayne@69
|
1225 isSet = false;
|
jpayne@69
|
1226 dtor(value);
|
jpayne@69
|
1227 }
|
jpayne@69
|
1228 if (other.isSet) {
|
jpayne@69
|
1229 ctor(value, other.value);
|
jpayne@69
|
1230 isSet = true;
|
jpayne@69
|
1231 }
|
jpayne@69
|
1232 }
|
jpayne@69
|
1233 return *this;
|
jpayne@69
|
1234 }
|
jpayne@69
|
1235
|
jpayne@69
|
1236 inline NullableValue& operator=(T&& other) { emplace(kj::mv(other)); return *this; }
|
jpayne@69
|
1237 inline NullableValue& operator=(T& other) { emplace(other); return *this; }
|
jpayne@69
|
1238 inline NullableValue& operator=(const T& other) { emplace(other); return *this; }
|
jpayne@69
|
1239 template <typename U>
|
jpayne@69
|
1240 inline NullableValue& operator=(NullableValue<U>&& other) {
|
jpayne@69
|
1241 if (other.isSet) {
|
jpayne@69
|
1242 emplace(kj::mv(other.value));
|
jpayne@69
|
1243 } else {
|
jpayne@69
|
1244 *this = nullptr;
|
jpayne@69
|
1245 }
|
jpayne@69
|
1246 return *this;
|
jpayne@69
|
1247 }
|
jpayne@69
|
1248 template <typename U>
|
jpayne@69
|
1249 inline NullableValue& operator=(const NullableValue<U>& other) {
|
jpayne@69
|
1250 if (other.isSet) {
|
jpayne@69
|
1251 emplace(other.value);
|
jpayne@69
|
1252 } else {
|
jpayne@69
|
1253 *this = nullptr;
|
jpayne@69
|
1254 }
|
jpayne@69
|
1255 return *this;
|
jpayne@69
|
1256 }
|
jpayne@69
|
1257 template <typename U>
|
jpayne@69
|
1258 inline NullableValue& operator=(const NullableValue<U&>& other) {
|
jpayne@69
|
1259 if (other.isSet) {
|
jpayne@69
|
1260 emplace(other.value);
|
jpayne@69
|
1261 } else {
|
jpayne@69
|
1262 *this = nullptr;
|
jpayne@69
|
1263 }
|
jpayne@69
|
1264 return *this;
|
jpayne@69
|
1265 }
|
jpayne@69
|
1266 inline NullableValue& operator=(decltype(nullptr)) {
|
jpayne@69
|
1267 if (isSet) {
|
jpayne@69
|
1268 isSet = false;
|
jpayne@69
|
1269 dtor(value);
|
jpayne@69
|
1270 }
|
jpayne@69
|
1271 return *this;
|
jpayne@69
|
1272 }
|
jpayne@69
|
1273
|
jpayne@69
|
1274 inline bool operator==(decltype(nullptr)) const { return !isSet; }
|
jpayne@69
|
1275 inline bool operator!=(decltype(nullptr)) const { return isSet; }
|
jpayne@69
|
1276
|
jpayne@69
|
1277 NullableValue(const T* t) = delete;
|
jpayne@69
|
1278 NullableValue& operator=(const T* other) = delete;
|
jpayne@69
|
1279 // We used to permit assigning a Maybe<T> directly from a T*, and the assignment would check for
|
jpayne@69
|
1280 // nullness. This turned out never to be useful, and sometimes to be dangerous.
|
jpayne@69
|
1281
|
jpayne@69
|
1282 private:
|
jpayne@69
|
1283 bool isSet;
|
jpayne@69
|
1284
|
jpayne@69
|
1285 #if _MSC_VER && !defined(__clang__)
|
jpayne@69
|
1286 #pragma warning(push)
|
jpayne@69
|
1287 #pragma warning(disable: 4624)
|
jpayne@69
|
1288 // Warns that the anonymous union has a deleted destructor when T is non-trivial. This warning
|
jpayne@69
|
1289 // seems broken.
|
jpayne@69
|
1290 #endif
|
jpayne@69
|
1291
|
jpayne@69
|
1292 union {
|
jpayne@69
|
1293 T value;
|
jpayne@69
|
1294 };
|
jpayne@69
|
1295
|
jpayne@69
|
1296 #if _MSC_VER && !defined(__clang__)
|
jpayne@69
|
1297 #pragma warning(pop)
|
jpayne@69
|
1298 #endif
|
jpayne@69
|
1299
|
jpayne@69
|
1300 friend class kj::Maybe<T>;
|
jpayne@69
|
1301 template <typename U>
|
jpayne@69
|
1302 friend NullableValue<U>&& readMaybe(Maybe<U>&& maybe);
|
jpayne@69
|
1303 };
|
jpayne@69
|
1304
|
jpayne@69
|
1305 template <typename T>
|
jpayne@69
|
1306 inline NullableValue<T>&& readMaybe(Maybe<T>&& maybe) { return kj::mv(maybe.ptr); }
|
jpayne@69
|
1307 template <typename T>
|
jpayne@69
|
1308 inline T* readMaybe(Maybe<T>& maybe) { return maybe.ptr; }
|
jpayne@69
|
1309 template <typename T>
|
jpayne@69
|
1310 inline const T* readMaybe(const Maybe<T>& maybe) { return maybe.ptr; }
|
jpayne@69
|
1311 template <typename T>
|
jpayne@69
|
1312 inline T* readMaybe(Maybe<T&>&& maybe) { return maybe.ptr; }
|
jpayne@69
|
1313 template <typename T>
|
jpayne@69
|
1314 inline T* readMaybe(const Maybe<T&>& maybe) { return maybe.ptr; }
|
jpayne@69
|
1315
|
jpayne@69
|
1316 template <typename T>
|
jpayne@69
|
1317 inline T* readMaybe(T* ptr) { return ptr; }
|
jpayne@69
|
1318 // Allow KJ_IF_MAYBE to work on regular pointers.
|
jpayne@69
|
1319
|
jpayne@69
|
1320 } // namespace _ (private)
|
jpayne@69
|
1321
|
jpayne@69
|
1322 #define KJ_IF_MAYBE(name, exp) if (auto name = ::kj::_::readMaybe(exp))
|
jpayne@69
|
1323
|
jpayne@69
|
1324 #if __GNUC__ || __clang__
|
jpayne@69
|
1325 // These two macros provide a friendly syntax to extract the value of a Maybe or return early.
|
jpayne@69
|
1326 //
|
jpayne@69
|
1327 // Use KJ_UNWRAP_OR_RETURN if you just want to return a simple value when the Maybe is null:
|
jpayne@69
|
1328 //
|
jpayne@69
|
1329 // int foo(Maybe<int> maybe) {
|
jpayne@69
|
1330 // int value = KJ_UNWRAP_OR_RETURN(maybe, -1);
|
jpayne@69
|
1331 // // ... use value ...
|
jpayne@69
|
1332 // }
|
jpayne@69
|
1333 //
|
jpayne@69
|
1334 // For functions returning void, omit the second parameter to KJ_UNWRAP_OR_RETURN:
|
jpayne@69
|
1335 //
|
jpayne@69
|
1336 // void foo(Maybe<int> maybe) {
|
jpayne@69
|
1337 // int value = KJ_UNWRAP_OR_RETURN(maybe);
|
jpayne@69
|
1338 // // ... use value ...
|
jpayne@69
|
1339 // }
|
jpayne@69
|
1340 //
|
jpayne@69
|
1341 // Use KJ_UNWRAP_OR if you want to execute a block with multiple statements.
|
jpayne@69
|
1342 //
|
jpayne@69
|
1343 // int foo(Maybe<int> maybe) {
|
jpayne@69
|
1344 // int value = KJ_UNWRAP_OR(maybe, {
|
jpayne@69
|
1345 // KJ_LOG(ERROR, "problem!!!");
|
jpayne@69
|
1346 // return -1;
|
jpayne@69
|
1347 // });
|
jpayne@69
|
1348 // // ... use value ...
|
jpayne@69
|
1349 // }
|
jpayne@69
|
1350 //
|
jpayne@69
|
1351 // The block MUST return at the end or you will get a compiler error
|
jpayne@69
|
1352 //
|
jpayne@69
|
1353 // Unfortunately, these macros seem impossible to express without using GCC's non-standard
|
jpayne@69
|
1354 // "statement expressions" extension. IIFEs don't do the trick here because a lambda cannot
|
jpayne@69
|
1355 // return out of the parent scope. These macros should therefore only be used in projects that
|
jpayne@69
|
1356 // target GCC or GCC-compatible compilers.
|
jpayne@69
|
1357 //
|
jpayne@69
|
1358 // `__GNUC__` is not defined when using LLVM's MSVC-compatible compiler driver `clang-cl` (even
|
jpayne@69
|
1359 // though clang supports the required extension), hence the additional `|| __clang__`.
|
jpayne@69
|
1360
|
jpayne@69
|
1361 #define KJ_UNWRAP_OR_RETURN(value, ...) \
|
jpayne@69
|
1362 (*({ \
|
jpayne@69
|
1363 auto _kj_result = ::kj::_::readMaybe(value); \
|
jpayne@69
|
1364 if (!_kj_result) { \
|
jpayne@69
|
1365 return __VA_ARGS__; \
|
jpayne@69
|
1366 } \
|
jpayne@69
|
1367 kj::mv(_kj_result); \
|
jpayne@69
|
1368 }))
|
jpayne@69
|
1369
|
jpayne@69
|
1370 #define KJ_UNWRAP_OR(value, block) \
|
jpayne@69
|
1371 (*({ \
|
jpayne@69
|
1372 auto _kj_result = ::kj::_::readMaybe(value); \
|
jpayne@69
|
1373 if (!_kj_result) { \
|
jpayne@69
|
1374 block; \
|
jpayne@69
|
1375 asm("KJ_UNWRAP_OR_block_is_missing_return_statement\n"); \
|
jpayne@69
|
1376 } \
|
jpayne@69
|
1377 kj::mv(_kj_result); \
|
jpayne@69
|
1378 }))
|
jpayne@69
|
1379 #endif
|
jpayne@69
|
1380
|
jpayne@69
|
1381 template <typename T>
|
jpayne@69
|
1382 class Maybe {
|
jpayne@69
|
1383 // A T, or nullptr.
|
jpayne@69
|
1384
|
jpayne@69
|
1385 // IF YOU CHANGE THIS CLASS: Note that there is a specialization of it in memory.h.
|
jpayne@69
|
1386
|
jpayne@69
|
1387 public:
|
jpayne@69
|
1388 Maybe(): ptr(nullptr) {}
|
jpayne@69
|
1389 Maybe(T&& t): ptr(kj::mv(t)) {}
|
jpayne@69
|
1390 Maybe(T& t): ptr(t) {}
|
jpayne@69
|
1391 Maybe(const T& t): ptr(t) {}
|
jpayne@69
|
1392 Maybe(Maybe&& other): ptr(kj::mv(other.ptr)) { other = nullptr; }
|
jpayne@69
|
1393 Maybe(const Maybe& other): ptr(other.ptr) {}
|
jpayne@69
|
1394 Maybe(Maybe& other): ptr(other.ptr) {}
|
jpayne@69
|
1395
|
jpayne@69
|
1396 template <typename U>
|
jpayne@69
|
1397 Maybe(Maybe<U>&& other) {
|
jpayne@69
|
1398 KJ_IF_MAYBE(val, kj::mv(other)) {
|
jpayne@69
|
1399 ptr.emplace(kj::mv(*val));
|
jpayne@69
|
1400 other = nullptr;
|
jpayne@69
|
1401 }
|
jpayne@69
|
1402 }
|
jpayne@69
|
1403 template <typename U>
|
jpayne@69
|
1404 Maybe(Maybe<U&>&& other) {
|
jpayne@69
|
1405 KJ_IF_MAYBE(val, other) {
|
jpayne@69
|
1406 ptr.emplace(*val);
|
jpayne@69
|
1407 other = nullptr;
|
jpayne@69
|
1408 }
|
jpayne@69
|
1409 }
|
jpayne@69
|
1410 template <typename U>
|
jpayne@69
|
1411 Maybe(const Maybe<U>& other) {
|
jpayne@69
|
1412 KJ_IF_MAYBE(val, other) {
|
jpayne@69
|
1413 ptr.emplace(*val);
|
jpayne@69
|
1414 }
|
jpayne@69
|
1415 }
|
jpayne@69
|
1416
|
jpayne@69
|
1417 Maybe(decltype(nullptr)): ptr(nullptr) {}
|
jpayne@69
|
1418
|
jpayne@69
|
1419 template <typename... Params>
|
jpayne@69
|
1420 inline T& emplace(Params&&... params) {
|
jpayne@69
|
1421 // Replace this Maybe's content with a new value constructed by passing the given parameters to
|
jpayne@69
|
1422 // T's constructor. This can be used to initialize a Maybe without copying or even moving a T.
|
jpayne@69
|
1423 // Returns a reference to the newly-constructed value.
|
jpayne@69
|
1424
|
jpayne@69
|
1425 return ptr.emplace(kj::fwd<Params>(params)...);
|
jpayne@69
|
1426 }
|
jpayne@69
|
1427
|
jpayne@69
|
1428 inline Maybe& operator=(T&& other) { ptr = kj::mv(other); return *this; }
|
jpayne@69
|
1429 inline Maybe& operator=(T& other) { ptr = other; return *this; }
|
jpayne@69
|
1430 inline Maybe& operator=(const T& other) { ptr = other; return *this; }
|
jpayne@69
|
1431
|
jpayne@69
|
1432 inline Maybe& operator=(Maybe&& other) { ptr = kj::mv(other.ptr); other = nullptr; return *this; }
|
jpayne@69
|
1433 inline Maybe& operator=(Maybe& other) { ptr = other.ptr; return *this; }
|
jpayne@69
|
1434 inline Maybe& operator=(const Maybe& other) { ptr = other.ptr; return *this; }
|
jpayne@69
|
1435
|
jpayne@69
|
1436 template <typename U>
|
jpayne@69
|
1437 Maybe& operator=(Maybe<U>&& other) {
|
jpayne@69
|
1438 KJ_IF_MAYBE(val, kj::mv(other)) {
|
jpayne@69
|
1439 ptr.emplace(kj::mv(*val));
|
jpayne@69
|
1440 other = nullptr;
|
jpayne@69
|
1441 } else {
|
jpayne@69
|
1442 ptr = nullptr;
|
jpayne@69
|
1443 }
|
jpayne@69
|
1444 return *this;
|
jpayne@69
|
1445 }
|
jpayne@69
|
1446 template <typename U>
|
jpayne@69
|
1447 Maybe& operator=(const Maybe<U>& other) {
|
jpayne@69
|
1448 KJ_IF_MAYBE(val, other) {
|
jpayne@69
|
1449 ptr.emplace(*val);
|
jpayne@69
|
1450 } else {
|
jpayne@69
|
1451 ptr = nullptr;
|
jpayne@69
|
1452 }
|
jpayne@69
|
1453 return *this;
|
jpayne@69
|
1454 }
|
jpayne@69
|
1455
|
jpayne@69
|
1456 inline Maybe& operator=(decltype(nullptr)) { ptr = nullptr; return *this; }
|
jpayne@69
|
1457
|
jpayne@69
|
1458 inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; }
|
jpayne@69
|
1459 inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; }
|
jpayne@69
|
1460
|
jpayne@69
|
1461 inline bool operator==(const Maybe<T>& other) const {
|
jpayne@69
|
1462 if (ptr == nullptr) {
|
jpayne@69
|
1463 return other == nullptr;
|
jpayne@69
|
1464 } else {
|
jpayne@69
|
1465 return other.ptr != nullptr && *ptr == *other.ptr;
|
jpayne@69
|
1466 }
|
jpayne@69
|
1467 }
|
jpayne@69
|
1468 inline bool operator!=(const Maybe<T>& other) const { return !(*this == other); }
|
jpayne@69
|
1469
|
jpayne@69
|
1470 Maybe(const T* t) = delete;
|
jpayne@69
|
1471 Maybe& operator=(const T* other) = delete;
|
jpayne@69
|
1472 // We used to permit assigning a Maybe<T> directly from a T*, and the assignment would check for
|
jpayne@69
|
1473 // nullness. This turned out never to be useful, and sometimes to be dangerous.
|
jpayne@69
|
1474
|
jpayne@69
|
1475 T& orDefault(T& defaultValue) & {
|
jpayne@69
|
1476 if (ptr == nullptr) {
|
jpayne@69
|
1477 return defaultValue;
|
jpayne@69
|
1478 } else {
|
jpayne@69
|
1479 return *ptr;
|
jpayne@69
|
1480 }
|
jpayne@69
|
1481 }
|
jpayne@69
|
1482 const T& orDefault(const T& defaultValue) const & {
|
jpayne@69
|
1483 if (ptr == nullptr) {
|
jpayne@69
|
1484 return defaultValue;
|
jpayne@69
|
1485 } else {
|
jpayne@69
|
1486 return *ptr;
|
jpayne@69
|
1487 }
|
jpayne@69
|
1488 }
|
jpayne@69
|
1489 T&& orDefault(T&& defaultValue) && {
|
jpayne@69
|
1490 if (ptr == nullptr) {
|
jpayne@69
|
1491 return kj::mv(defaultValue);
|
jpayne@69
|
1492 } else {
|
jpayne@69
|
1493 return kj::mv(*ptr);
|
jpayne@69
|
1494 }
|
jpayne@69
|
1495 }
|
jpayne@69
|
1496 const T&& orDefault(const T&& defaultValue) const && {
|
jpayne@69
|
1497 if (ptr == nullptr) {
|
jpayne@69
|
1498 return kj::mv(defaultValue);
|
jpayne@69
|
1499 } else {
|
jpayne@69
|
1500 return kj::mv(*ptr);
|
jpayne@69
|
1501 }
|
jpayne@69
|
1502 }
|
jpayne@69
|
1503
|
jpayne@69
|
1504 template <typename F,
|
jpayne@69
|
1505 typename Result = decltype(instance<bool>() ? instance<T&>() : instance<F>()())>
|
jpayne@69
|
1506 Result orDefault(F&& lazyDefaultValue) & {
|
jpayne@69
|
1507 if (ptr == nullptr) {
|
jpayne@69
|
1508 return lazyDefaultValue();
|
jpayne@69
|
1509 } else {
|
jpayne@69
|
1510 return *ptr;
|
jpayne@69
|
1511 }
|
jpayne@69
|
1512 }
|
jpayne@69
|
1513
|
jpayne@69
|
1514 template <typename F,
|
jpayne@69
|
1515 typename Result = decltype(instance<bool>() ? instance<const T&>() : instance<F>()())>
|
jpayne@69
|
1516 Result orDefault(F&& lazyDefaultValue) const & {
|
jpayne@69
|
1517 if (ptr == nullptr) {
|
jpayne@69
|
1518 return lazyDefaultValue();
|
jpayne@69
|
1519 } else {
|
jpayne@69
|
1520 return *ptr;
|
jpayne@69
|
1521 }
|
jpayne@69
|
1522 }
|
jpayne@69
|
1523
|
jpayne@69
|
1524 template <typename F,
|
jpayne@69
|
1525 typename Result = decltype(instance<bool>() ? instance<T&&>() : instance<F>()())>
|
jpayne@69
|
1526 Result orDefault(F&& lazyDefaultValue) && {
|
jpayne@69
|
1527 if (ptr == nullptr) {
|
jpayne@69
|
1528 return lazyDefaultValue();
|
jpayne@69
|
1529 } else {
|
jpayne@69
|
1530 return kj::mv(*ptr);
|
jpayne@69
|
1531 }
|
jpayne@69
|
1532 }
|
jpayne@69
|
1533
|
jpayne@69
|
1534 template <typename F,
|
jpayne@69
|
1535 typename Result = decltype(instance<bool>() ? instance<const T&&>() : instance<F>()())>
|
jpayne@69
|
1536 Result orDefault(F&& lazyDefaultValue) const && {
|
jpayne@69
|
1537 if (ptr == nullptr) {
|
jpayne@69
|
1538 return lazyDefaultValue();
|
jpayne@69
|
1539 } else {
|
jpayne@69
|
1540 return kj::mv(*ptr);
|
jpayne@69
|
1541 }
|
jpayne@69
|
1542 }
|
jpayne@69
|
1543
|
jpayne@69
|
1544 template <typename Func>
|
jpayne@69
|
1545 auto map(Func&& f) & -> Maybe<decltype(f(instance<T&>()))> {
|
jpayne@69
|
1546 if (ptr == nullptr) {
|
jpayne@69
|
1547 return nullptr;
|
jpayne@69
|
1548 } else {
|
jpayne@69
|
1549 return f(*ptr);
|
jpayne@69
|
1550 }
|
jpayne@69
|
1551 }
|
jpayne@69
|
1552
|
jpayne@69
|
1553 template <typename Func>
|
jpayne@69
|
1554 auto map(Func&& f) const & -> Maybe<decltype(f(instance<const T&>()))> {
|
jpayne@69
|
1555 if (ptr == nullptr) {
|
jpayne@69
|
1556 return nullptr;
|
jpayne@69
|
1557 } else {
|
jpayne@69
|
1558 return f(*ptr);
|
jpayne@69
|
1559 }
|
jpayne@69
|
1560 }
|
jpayne@69
|
1561
|
jpayne@69
|
1562 template <typename Func>
|
jpayne@69
|
1563 auto map(Func&& f) && -> Maybe<decltype(f(instance<T&&>()))> {
|
jpayne@69
|
1564 if (ptr == nullptr) {
|
jpayne@69
|
1565 return nullptr;
|
jpayne@69
|
1566 } else {
|
jpayne@69
|
1567 return f(kj::mv(*ptr));
|
jpayne@69
|
1568 }
|
jpayne@69
|
1569 }
|
jpayne@69
|
1570
|
jpayne@69
|
1571 template <typename Func>
|
jpayne@69
|
1572 auto map(Func&& f) const && -> Maybe<decltype(f(instance<const T&&>()))> {
|
jpayne@69
|
1573 if (ptr == nullptr) {
|
jpayne@69
|
1574 return nullptr;
|
jpayne@69
|
1575 } else {
|
jpayne@69
|
1576 return f(kj::mv(*ptr));
|
jpayne@69
|
1577 }
|
jpayne@69
|
1578 }
|
jpayne@69
|
1579
|
jpayne@69
|
1580 private:
|
jpayne@69
|
1581 _::NullableValue<T> ptr;
|
jpayne@69
|
1582
|
jpayne@69
|
1583 template <typename U>
|
jpayne@69
|
1584 friend class Maybe;
|
jpayne@69
|
1585 template <typename U>
|
jpayne@69
|
1586 friend _::NullableValue<U>&& _::readMaybe(Maybe<U>&& maybe);
|
jpayne@69
|
1587 template <typename U>
|
jpayne@69
|
1588 friend U* _::readMaybe(Maybe<U>& maybe);
|
jpayne@69
|
1589 template <typename U>
|
jpayne@69
|
1590 friend const U* _::readMaybe(const Maybe<U>& maybe);
|
jpayne@69
|
1591 };
|
jpayne@69
|
1592
|
jpayne@69
|
1593 template <typename T>
|
jpayne@69
|
1594 class Maybe<T&> {
|
jpayne@69
|
1595 public:
|
jpayne@69
|
1596 constexpr Maybe(): ptr(nullptr) {}
|
jpayne@69
|
1597 constexpr Maybe(T& t): ptr(&t) {}
|
jpayne@69
|
1598 constexpr Maybe(T* t): ptr(t) {}
|
jpayne@69
|
1599
|
jpayne@69
|
1600 inline constexpr Maybe(PropagateConst<T, Maybe>& other): ptr(other.ptr) {}
|
jpayne@69
|
1601 // Allow const copy only if `T` itself is const. Otherwise allow only non-const copy, to
|
jpayne@69
|
1602 // protect transitive constness. Clang is happy for this constructor to be declared `= default`
|
jpayne@69
|
1603 // since, after evaluation of `PropagateConst`, it does end up being a default-able constructor.
|
jpayne@69
|
1604 // But, GCC and MSVC both complain about that, claiming this constructor cannot be declared
|
jpayne@69
|
1605 // default. I don't know who is correct, but whatever, we'll write out an implementation, fine.
|
jpayne@69
|
1606 //
|
jpayne@69
|
1607 // Note that we can't solve this by inheriting DisallowConstCopyIfNotConst<T> because we want
|
jpayne@69
|
1608 // to override the move constructor, and if we override the move constructor then we must define
|
jpayne@69
|
1609 // the copy constructor here.
|
jpayne@69
|
1610
|
jpayne@69
|
1611 inline constexpr Maybe(Maybe&& other): ptr(other.ptr) { other.ptr = nullptr; }
|
jpayne@69
|
1612
|
jpayne@69
|
1613 template <typename U>
|
jpayne@69
|
1614 inline constexpr Maybe(Maybe<U&>& other): ptr(other.ptr) {}
|
jpayne@69
|
1615 template <typename U>
|
jpayne@69
|
1616 inline constexpr Maybe(const Maybe<U&>& other): ptr(const_cast<const U*>(other.ptr)) {}
|
jpayne@69
|
1617 template <typename U>
|
jpayne@69
|
1618 inline constexpr Maybe(Maybe<U&>&& other): ptr(other.ptr) { other.ptr = nullptr; }
|
jpayne@69
|
1619 template <typename U>
|
jpayne@69
|
1620 inline constexpr Maybe(const Maybe<U&>&& other) = delete;
|
jpayne@69
|
1621 template <typename U, typename = EnableIf<canConvert<U*, T*>()>>
|
jpayne@69
|
1622 constexpr Maybe(Maybe<U>& other): ptr(other.ptr.operator U*()) {}
|
jpayne@69
|
1623 template <typename U, typename = EnableIf<canConvert<const U*, T*>()>>
|
jpayne@69
|
1624 constexpr Maybe(const Maybe<U>& other): ptr(other.ptr.operator const U*()) {}
|
jpayne@69
|
1625 inline constexpr Maybe(decltype(nullptr)): ptr(nullptr) {}
|
jpayne@69
|
1626
|
jpayne@69
|
1627 inline Maybe& operator=(T& other) { ptr = &other; return *this; }
|
jpayne@69
|
1628 inline Maybe& operator=(T* other) { ptr = other; return *this; }
|
jpayne@69
|
1629 inline Maybe& operator=(PropagateConst<T, Maybe>& other) { ptr = other.ptr; return *this; }
|
jpayne@69
|
1630 inline Maybe& operator=(Maybe&& other) { ptr = other.ptr; other.ptr = nullptr; return *this; }
|
jpayne@69
|
1631 template <typename U>
|
jpayne@69
|
1632 inline Maybe& operator=(Maybe<U&>& other) { ptr = other.ptr; return *this; }
|
jpayne@69
|
1633 template <typename U>
|
jpayne@69
|
1634 inline Maybe& operator=(const Maybe<const U&>& other) { ptr = other.ptr; return *this; }
|
jpayne@69
|
1635 template <typename U>
|
jpayne@69
|
1636 inline Maybe& operator=(Maybe<U&>&& other) { ptr = other.ptr; other.ptr = nullptr; return *this; }
|
jpayne@69
|
1637 template <typename U>
|
jpayne@69
|
1638 inline Maybe& operator=(const Maybe<U&>&& other) = delete;
|
jpayne@69
|
1639
|
jpayne@69
|
1640 inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; }
|
jpayne@69
|
1641 inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; }
|
jpayne@69
|
1642
|
jpayne@69
|
1643 T& orDefault(T& defaultValue) {
|
jpayne@69
|
1644 if (ptr == nullptr) {
|
jpayne@69
|
1645 return defaultValue;
|
jpayne@69
|
1646 } else {
|
jpayne@69
|
1647 return *ptr;
|
jpayne@69
|
1648 }
|
jpayne@69
|
1649 }
|
jpayne@69
|
1650 const T& orDefault(const T& defaultValue) const {
|
jpayne@69
|
1651 if (ptr == nullptr) {
|
jpayne@69
|
1652 return defaultValue;
|
jpayne@69
|
1653 } else {
|
jpayne@69
|
1654 return *ptr;
|
jpayne@69
|
1655 }
|
jpayne@69
|
1656 }
|
jpayne@69
|
1657
|
jpayne@69
|
1658 template <typename Func>
|
jpayne@69
|
1659 auto map(Func&& f) -> Maybe<decltype(f(instance<T&>()))> {
|
jpayne@69
|
1660 if (ptr == nullptr) {
|
jpayne@69
|
1661 return nullptr;
|
jpayne@69
|
1662 } else {
|
jpayne@69
|
1663 return f(*ptr);
|
jpayne@69
|
1664 }
|
jpayne@69
|
1665 }
|
jpayne@69
|
1666
|
jpayne@69
|
1667 template <typename Func>
|
jpayne@69
|
1668 auto map(Func&& f) const -> Maybe<decltype(f(instance<const T&>()))> {
|
jpayne@69
|
1669 if (ptr == nullptr) {
|
jpayne@69
|
1670 return nullptr;
|
jpayne@69
|
1671 } else {
|
jpayne@69
|
1672 const T& ref = *ptr;
|
jpayne@69
|
1673 return f(ref);
|
jpayne@69
|
1674 }
|
jpayne@69
|
1675 }
|
jpayne@69
|
1676
|
jpayne@69
|
1677 private:
|
jpayne@69
|
1678 T* ptr;
|
jpayne@69
|
1679
|
jpayne@69
|
1680 template <typename U>
|
jpayne@69
|
1681 friend class Maybe;
|
jpayne@69
|
1682 template <typename U>
|
jpayne@69
|
1683 friend U* _::readMaybe(Maybe<U&>&& maybe);
|
jpayne@69
|
1684 template <typename U>
|
jpayne@69
|
1685 friend U* _::readMaybe(const Maybe<U&>& maybe);
|
jpayne@69
|
1686 };
|
jpayne@69
|
1687
|
jpayne@69
|
1688 // =======================================================================================
|
jpayne@69
|
1689 // ArrayPtr
|
jpayne@69
|
1690 //
|
jpayne@69
|
1691 // So common that we put it in common.h rather than array.h.
|
jpayne@69
|
1692
|
jpayne@69
|
1693 template <typename T>
|
jpayne@69
|
1694 class Array;
|
jpayne@69
|
1695
|
jpayne@69
|
1696 template <typename T>
|
jpayne@69
|
1697 class ArrayPtr: public DisallowConstCopyIfNotConst<T> {
|
jpayne@69
|
1698 // A pointer to an array. Includes a size. Like any pointer, it doesn't own the target data,
|
jpayne@69
|
1699 // and passing by value only copies the pointer, not the target.
|
jpayne@69
|
1700
|
jpayne@69
|
1701 public:
|
jpayne@69
|
1702 inline constexpr ArrayPtr(): ptr(nullptr), size_(0) {}
|
jpayne@69
|
1703 inline constexpr ArrayPtr(decltype(nullptr)): ptr(nullptr), size_(0) {}
|
jpayne@69
|
1704 inline constexpr ArrayPtr(T* ptr KJ_LIFETIMEBOUND, size_t size): ptr(ptr), size_(size) {}
|
jpayne@69
|
1705 inline constexpr ArrayPtr(T* begin KJ_LIFETIMEBOUND, T* end KJ_LIFETIMEBOUND)
|
jpayne@69
|
1706 : ptr(begin), size_(end - begin) {}
|
jpayne@69
|
1707 ArrayPtr<T>& operator=(Array<T>&&) = delete;
|
jpayne@69
|
1708 ArrayPtr<T>& operator=(decltype(nullptr)) {
|
jpayne@69
|
1709 ptr = nullptr;
|
jpayne@69
|
1710 size_ = 0;
|
jpayne@69
|
1711 return *this;
|
jpayne@69
|
1712 }
|
jpayne@69
|
1713
|
jpayne@69
|
1714 #if __GNUC__ && !__clang__ && __GNUC__ >= 9
|
jpayne@69
|
1715 // GCC 9 added a warning when we take an initializer_list as a constructor parameter and save a
|
jpayne@69
|
1716 // pointer to its content in a class member. GCC apparently imagines we're going to do something
|
jpayne@69
|
1717 // dumb like this:
|
jpayne@69
|
1718 // ArrayPtr<const int> ptr = { 1, 2, 3 };
|
jpayne@69
|
1719 // foo(ptr[1]); // undefined behavior!
|
jpayne@69
|
1720 // Any KJ programmer should be able to recognize that this is UB, because an ArrayPtr does not own
|
jpayne@69
|
1721 // its content. That's not what this constructor is for, tohugh. This constructor is meant to allow
|
jpayne@69
|
1722 // code like this:
|
jpayne@69
|
1723 // int foo(ArrayPtr<const int> p);
|
jpayne@69
|
1724 // // ... later ...
|
jpayne@69
|
1725 // foo({1, 2, 3});
|
jpayne@69
|
1726 // In this case, the initializer_list's backing array, like any temporary, lives until the end of
|
jpayne@69
|
1727 // the statement `foo({1, 2, 3});`. Therefore, it lives at least until the call to foo() has
|
jpayne@69
|
1728 // returned, which is exactly what we care about. This usage is fine! GCC is wrong to warn.
|
jpayne@69
|
1729 //
|
jpayne@69
|
1730 // Amusingly, Clang's implementation has a similar type that they call ArrayRef which apparently
|
jpayne@69
|
1731 // triggers this same GCC warning. My guess is that Clang will not introduce a similar warning
|
jpayne@69
|
1732 // given that it triggers on their own, legitimate code.
|
jpayne@69
|
1733 #pragma GCC diagnostic push
|
jpayne@69
|
1734 #pragma GCC diagnostic ignored "-Winit-list-lifetime"
|
jpayne@69
|
1735 #endif
|
jpayne@69
|
1736 inline KJ_CONSTEXPR() ArrayPtr(
|
jpayne@69
|
1737 ::std::initializer_list<RemoveConstOrDisable<T>> init KJ_LIFETIMEBOUND)
|
jpayne@69
|
1738 : ptr(init.begin()), size_(init.size()) {}
|
jpayne@69
|
1739 #if __GNUC__ && !__clang__ && __GNUC__ >= 9
|
jpayne@69
|
1740 #pragma GCC diagnostic pop
|
jpayne@69
|
1741 #endif
|
jpayne@69
|
1742
|
jpayne@69
|
1743 template <size_t size>
|
jpayne@69
|
1744 inline constexpr ArrayPtr(KJ_LIFETIMEBOUND T (&native)[size]): ptr(native), size_(size) {
|
jpayne@69
|
1745 // Construct an ArrayPtr from a native C-style array.
|
jpayne@69
|
1746 //
|
jpayne@69
|
1747 // We disable this constructor for const char arrays because otherwise you would be able to
|
jpayne@69
|
1748 // implicitly convert a character literal to ArrayPtr<const char>, which sounds really great,
|
jpayne@69
|
1749 // except that the NUL terminator would be included, which probably isn't what you intended.
|
jpayne@69
|
1750 //
|
jpayne@69
|
1751 // TODO(someday): Maybe we should support character literals but explicitly chop off the NUL
|
jpayne@69
|
1752 // terminator. This could do the wrong thing if someone tries to construct an
|
jpayne@69
|
1753 // ArrayPtr<const char> from a non-NUL-terminated char array, but evidence suggests that all
|
jpayne@69
|
1754 // real use cases are in fact intending to remove the NUL terminator. It's convenient to be
|
jpayne@69
|
1755 // able to specify ArrayPtr<const char> as a parameter type and be able to accept strings
|
jpayne@69
|
1756 // as input in addition to arrays. Currently, you'll need overloading to support string
|
jpayne@69
|
1757 // literals in this case, but if you overload StringPtr, then you'll find that several
|
jpayne@69
|
1758 // conversions (e.g. from String and from a literal char array) become ambiguous! You end up
|
jpayne@69
|
1759 // having to overload for literal char arrays specifically which is cumbersome.
|
jpayne@69
|
1760
|
jpayne@69
|
1761 static_assert(!isSameType<T, const char>(),
|
jpayne@69
|
1762 "Can't implicitly convert literal char array to ArrayPtr because we don't know if "
|
jpayne@69
|
1763 "you meant to include the NUL terminator. We may change this in the future to "
|
jpayne@69
|
1764 "automatically drop the NUL terminator. For now, try explicitly converting to StringPtr, "
|
jpayne@69
|
1765 "which can in turn implicitly convert to ArrayPtr<const char>.");
|
jpayne@69
|
1766 static_assert(!isSameType<T, const char16_t>(), "see above");
|
jpayne@69
|
1767 static_assert(!isSameType<T, const char32_t>(), "see above");
|
jpayne@69
|
1768 }
|
jpayne@69
|
1769
|
jpayne@69
|
1770 inline operator ArrayPtr<const T>() const {
|
jpayne@69
|
1771 return ArrayPtr<const T>(ptr, size_);
|
jpayne@69
|
1772 }
|
jpayne@69
|
1773 inline ArrayPtr<const T> asConst() const {
|
jpayne@69
|
1774 return ArrayPtr<const T>(ptr, size_);
|
jpayne@69
|
1775 }
|
jpayne@69
|
1776
|
jpayne@69
|
1777 inline constexpr size_t size() const { return size_; }
|
jpayne@69
|
1778 inline const T& operator[](size_t index) const {
|
jpayne@69
|
1779 KJ_IREQUIRE(index < size_, "Out-of-bounds ArrayPtr access.");
|
jpayne@69
|
1780 return ptr[index];
|
jpayne@69
|
1781 }
|
jpayne@69
|
1782 inline T& operator[](size_t index) {
|
jpayne@69
|
1783 KJ_IREQUIRE(index < size_, "Out-of-bounds ArrayPtr access.");
|
jpayne@69
|
1784 return ptr[index];
|
jpayne@69
|
1785 }
|
jpayne@69
|
1786
|
jpayne@69
|
1787 inline T* begin() { return ptr; }
|
jpayne@69
|
1788 inline T* end() { return ptr + size_; }
|
jpayne@69
|
1789 inline T& front() { return *ptr; }
|
jpayne@69
|
1790 inline T& back() { return *(ptr + size_ - 1); }
|
jpayne@69
|
1791 inline constexpr const T* begin() const { return ptr; }
|
jpayne@69
|
1792 inline constexpr const T* end() const { return ptr + size_; }
|
jpayne@69
|
1793 inline const T& front() const { return *ptr; }
|
jpayne@69
|
1794 inline const T& back() const { return *(ptr + size_ - 1); }
|
jpayne@69
|
1795
|
jpayne@69
|
1796 inline ArrayPtr<const T> slice(size_t start, size_t end) const {
|
jpayne@69
|
1797 KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice().");
|
jpayne@69
|
1798 return ArrayPtr<const T>(ptr + start, end - start);
|
jpayne@69
|
1799 }
|
jpayne@69
|
1800 inline ArrayPtr slice(size_t start, size_t end) {
|
jpayne@69
|
1801 KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice().");
|
jpayne@69
|
1802 return ArrayPtr(ptr + start, end - start);
|
jpayne@69
|
1803 }
|
jpayne@69
|
1804 inline bool startsWith(const ArrayPtr<const T>& other) const {
|
jpayne@69
|
1805 return other.size() <= size_ && slice(0, other.size()) == other;
|
jpayne@69
|
1806 }
|
jpayne@69
|
1807 inline bool endsWith(const ArrayPtr<const T>& other) const {
|
jpayne@69
|
1808 return other.size() <= size_ && slice(size_ - other.size(), size_) == other;
|
jpayne@69
|
1809 }
|
jpayne@69
|
1810
|
jpayne@69
|
1811 inline Maybe<size_t> findFirst(const T& match) const {
|
jpayne@69
|
1812 for (size_t i = 0; i < size_; i++) {
|
jpayne@69
|
1813 if (ptr[i] == match) {
|
jpayne@69
|
1814 return i;
|
jpayne@69
|
1815 }
|
jpayne@69
|
1816 }
|
jpayne@69
|
1817 return nullptr;
|
jpayne@69
|
1818 }
|
jpayne@69
|
1819 inline Maybe<size_t> findLast(const T& match) const {
|
jpayne@69
|
1820 for (size_t i = size_; i--;) {
|
jpayne@69
|
1821 if (ptr[i] == match) {
|
jpayne@69
|
1822 return i;
|
jpayne@69
|
1823 }
|
jpayne@69
|
1824 }
|
jpayne@69
|
1825 return nullptr;
|
jpayne@69
|
1826 }
|
jpayne@69
|
1827
|
jpayne@69
|
1828 inline ArrayPtr<PropagateConst<T, byte>> asBytes() const {
|
jpayne@69
|
1829 // Reinterpret the array as a byte array. This is explicitly legal under C++ aliasing
|
jpayne@69
|
1830 // rules.
|
jpayne@69
|
1831 return { reinterpret_cast<PropagateConst<T, byte>*>(ptr), size_ * sizeof(T) };
|
jpayne@69
|
1832 }
|
jpayne@69
|
1833 inline ArrayPtr<PropagateConst<T, char>> asChars() const {
|
jpayne@69
|
1834 // Reinterpret the array as a char array. This is explicitly legal under C++ aliasing
|
jpayne@69
|
1835 // rules.
|
jpayne@69
|
1836 return { reinterpret_cast<PropagateConst<T, char>*>(ptr), size_ * sizeof(T) };
|
jpayne@69
|
1837 }
|
jpayne@69
|
1838
|
jpayne@69
|
1839 inline bool operator==(decltype(nullptr)) const { return size_ == 0; }
|
jpayne@69
|
1840 inline bool operator!=(decltype(nullptr)) const { return size_ != 0; }
|
jpayne@69
|
1841
|
jpayne@69
|
1842 inline bool operator==(const ArrayPtr& other) const {
|
jpayne@69
|
1843 if (size_ != other.size_) return false;
|
jpayne@69
|
1844 if (isIntegral<RemoveConst<T>>()) {
|
jpayne@69
|
1845 if (size_ == 0) return true;
|
jpayne@69
|
1846 return memcmp(ptr, other.ptr, size_ * sizeof(T)) == 0;
|
jpayne@69
|
1847 }
|
jpayne@69
|
1848 for (size_t i = 0; i < size_; i++) {
|
jpayne@69
|
1849 if (ptr[i] != other[i]) return false;
|
jpayne@69
|
1850 }
|
jpayne@69
|
1851 return true;
|
jpayne@69
|
1852 }
|
jpayne@69
|
1853 #if !__cpp_impl_three_way_comparison
|
jpayne@69
|
1854 inline bool operator!=(const ArrayPtr& other) const { return !(*this == other); }
|
jpayne@69
|
1855 #endif
|
jpayne@69
|
1856
|
jpayne@69
|
1857 template <typename U>
|
jpayne@69
|
1858 inline bool operator==(const ArrayPtr<U>& other) const {
|
jpayne@69
|
1859 if (size_ != other.size()) return false;
|
jpayne@69
|
1860 for (size_t i = 0; i < size_; i++) {
|
jpayne@69
|
1861 if (ptr[i] != other[i]) return false;
|
jpayne@69
|
1862 }
|
jpayne@69
|
1863 return true;
|
jpayne@69
|
1864 }
|
jpayne@69
|
1865 #if !__cpp_impl_three_way_comparison
|
jpayne@69
|
1866 template <typename U>
|
jpayne@69
|
1867 inline bool operator!=(const ArrayPtr<U>& other) const { return !(*this == other); }
|
jpayne@69
|
1868 #endif
|
jpayne@69
|
1869
|
jpayne@69
|
1870 template <typename... Attachments>
|
jpayne@69
|
1871 Array<T> attach(Attachments&&... attachments) const KJ_WARN_UNUSED_RESULT;
|
jpayne@69
|
1872 // Like Array<T>::attach(), but also promotes an ArrayPtr to an Array. Generally the attachment
|
jpayne@69
|
1873 // should be an object that actually owns the array that the ArrayPtr is pointing at.
|
jpayne@69
|
1874 //
|
jpayne@69
|
1875 // You must include kj/array.h to call this.
|
jpayne@69
|
1876
|
jpayne@69
|
1877 private:
|
jpayne@69
|
1878 T* ptr;
|
jpayne@69
|
1879 size_t size_;
|
jpayne@69
|
1880 };
|
jpayne@69
|
1881
|
jpayne@69
|
1882 template <>
|
jpayne@69
|
1883 inline Maybe<size_t> ArrayPtr<const char>::findFirst(const char& c) const {
|
jpayne@69
|
1884 const char* pos = reinterpret_cast<const char*>(memchr(ptr, c, size_));
|
jpayne@69
|
1885 if (pos == nullptr) {
|
jpayne@69
|
1886 return nullptr;
|
jpayne@69
|
1887 } else {
|
jpayne@69
|
1888 return pos - ptr;
|
jpayne@69
|
1889 }
|
jpayne@69
|
1890 }
|
jpayne@69
|
1891
|
jpayne@69
|
1892 template <>
|
jpayne@69
|
1893 inline Maybe<size_t> ArrayPtr<char>::findFirst(const char& c) const {
|
jpayne@69
|
1894 char* pos = reinterpret_cast<char*>(memchr(ptr, c, size_));
|
jpayne@69
|
1895 if (pos == nullptr) {
|
jpayne@69
|
1896 return nullptr;
|
jpayne@69
|
1897 } else {
|
jpayne@69
|
1898 return pos - ptr;
|
jpayne@69
|
1899 }
|
jpayne@69
|
1900 }
|
jpayne@69
|
1901
|
jpayne@69
|
1902 template <>
|
jpayne@69
|
1903 inline Maybe<size_t> ArrayPtr<const byte>::findFirst(const byte& c) const {
|
jpayne@69
|
1904 const byte* pos = reinterpret_cast<const byte*>(memchr(ptr, c, size_));
|
jpayne@69
|
1905 if (pos == nullptr) {
|
jpayne@69
|
1906 return nullptr;
|
jpayne@69
|
1907 } else {
|
jpayne@69
|
1908 return pos - ptr;
|
jpayne@69
|
1909 }
|
jpayne@69
|
1910 }
|
jpayne@69
|
1911
|
jpayne@69
|
1912 template <>
|
jpayne@69
|
1913 inline Maybe<size_t> ArrayPtr<byte>::findFirst(const byte& c) const {
|
jpayne@69
|
1914 byte* pos = reinterpret_cast<byte*>(memchr(ptr, c, size_));
|
jpayne@69
|
1915 if (pos == nullptr) {
|
jpayne@69
|
1916 return nullptr;
|
jpayne@69
|
1917 } else {
|
jpayne@69
|
1918 return pos - ptr;
|
jpayne@69
|
1919 }
|
jpayne@69
|
1920 }
|
jpayne@69
|
1921
|
jpayne@69
|
1922 // glibc has a memrchr() for reverse search but it's non-standard, so we don't bother optimizing
|
jpayne@69
|
1923 // findLast(), which isn't used much anyway.
|
jpayne@69
|
1924
|
jpayne@69
|
1925 template <typename T>
|
jpayne@69
|
1926 inline constexpr ArrayPtr<T> arrayPtr(T* ptr KJ_LIFETIMEBOUND, size_t size) {
|
jpayne@69
|
1927 // Use this function to construct ArrayPtrs without writing out the type name.
|
jpayne@69
|
1928 return ArrayPtr<T>(ptr, size);
|
jpayne@69
|
1929 }
|
jpayne@69
|
1930
|
jpayne@69
|
1931 template <typename T>
|
jpayne@69
|
1932 inline constexpr ArrayPtr<T> arrayPtr(T* begin KJ_LIFETIMEBOUND, T* end KJ_LIFETIMEBOUND) {
|
jpayne@69
|
1933 // Use this function to construct ArrayPtrs without writing out the type name.
|
jpayne@69
|
1934 return ArrayPtr<T>(begin, end);
|
jpayne@69
|
1935 }
|
jpayne@69
|
1936
|
jpayne@69
|
1937 // =======================================================================================
|
jpayne@69
|
1938 // Casts
|
jpayne@69
|
1939
|
jpayne@69
|
1940 template <typename To, typename From>
|
jpayne@69
|
1941 To implicitCast(From&& from) {
|
jpayne@69
|
1942 // `implicitCast<T>(value)` casts `value` to type `T` only if the conversion is implicit. Useful
|
jpayne@69
|
1943 // for e.g. resolving ambiguous overloads without sacrificing type-safety.
|
jpayne@69
|
1944 return kj::fwd<From>(from);
|
jpayne@69
|
1945 }
|
jpayne@69
|
1946
|
jpayne@69
|
1947 template <typename To, typename From>
|
jpayne@69
|
1948 Maybe<To&> dynamicDowncastIfAvailable(From& from) {
|
jpayne@69
|
1949 // If RTTI is disabled, always returns nullptr. Otherwise, works like dynamic_cast. Useful
|
jpayne@69
|
1950 // in situations where dynamic_cast could allow an optimization, but isn't strictly necessary
|
jpayne@69
|
1951 // for correctness. It is highly recommended that you try to arrange all your dynamic_casts
|
jpayne@69
|
1952 // this way, as a dynamic_cast that is necessary for correctness implies a flaw in the interface
|
jpayne@69
|
1953 // design.
|
jpayne@69
|
1954
|
jpayne@69
|
1955 // Force a compile error if To is not a subtype of From. Cross-casting is rare; if it is needed
|
jpayne@69
|
1956 // we should have a separate cast function like dynamicCrosscastIfAvailable().
|
jpayne@69
|
1957 if (false) {
|
jpayne@69
|
1958 kj::implicitCast<From*>(kj::implicitCast<To*>(nullptr));
|
jpayne@69
|
1959 }
|
jpayne@69
|
1960
|
jpayne@69
|
1961 #if KJ_NO_RTTI
|
jpayne@69
|
1962 return nullptr;
|
jpayne@69
|
1963 #else
|
jpayne@69
|
1964 return dynamic_cast<To*>(&from);
|
jpayne@69
|
1965 #endif
|
jpayne@69
|
1966 }
|
jpayne@69
|
1967
|
jpayne@69
|
1968 template <typename To, typename From>
|
jpayne@69
|
1969 To& downcast(From& from) {
|
jpayne@69
|
1970 // Down-cast a value to a sub-type, asserting that the cast is valid. In opt mode this is a
|
jpayne@69
|
1971 // static_cast, but in debug mode (when RTTI is enabled) a dynamic_cast will be used to verify
|
jpayne@69
|
1972 // that the value really has the requested type.
|
jpayne@69
|
1973
|
jpayne@69
|
1974 // Force a compile error if To is not a subtype of From.
|
jpayne@69
|
1975 if (false) {
|
jpayne@69
|
1976 kj::implicitCast<From*>(kj::implicitCast<To*>(nullptr));
|
jpayne@69
|
1977 }
|
jpayne@69
|
1978
|
jpayne@69
|
1979 #if !KJ_NO_RTTI
|
jpayne@69
|
1980 KJ_IREQUIRE(dynamic_cast<To*>(&from) != nullptr, "Value cannot be downcast() to requested type.");
|
jpayne@69
|
1981 #endif
|
jpayne@69
|
1982
|
jpayne@69
|
1983 return static_cast<To&>(from);
|
jpayne@69
|
1984 }
|
jpayne@69
|
1985
|
jpayne@69
|
1986 // =======================================================================================
|
jpayne@69
|
1987 // Defer
|
jpayne@69
|
1988
|
jpayne@69
|
1989 namespace _ { // private
|
jpayne@69
|
1990
|
jpayne@69
|
1991 template <typename Func>
|
jpayne@69
|
1992 class Deferred {
|
jpayne@69
|
1993 public:
|
jpayne@69
|
1994 Deferred(Func&& func): maybeFunc(kj::fwd<Func>(func)) {}
|
jpayne@69
|
1995 ~Deferred() noexcept(false) {
|
jpayne@69
|
1996 run();
|
jpayne@69
|
1997 }
|
jpayne@69
|
1998 KJ_DISALLOW_COPY(Deferred);
|
jpayne@69
|
1999
|
jpayne@69
|
2000 Deferred(Deferred&&) = default;
|
jpayne@69
|
2001 // Since we use a kj::Maybe, the default move constructor does exactly what we want it to do.
|
jpayne@69
|
2002
|
jpayne@69
|
2003 void run() {
|
jpayne@69
|
2004 // Move `maybeFunc` to the local scope so that even if we throw, we destroy the functor we had.
|
jpayne@69
|
2005 auto maybeLocalFunc = kj::mv(maybeFunc);
|
jpayne@69
|
2006 KJ_IF_MAYBE(func, maybeLocalFunc) {
|
jpayne@69
|
2007 (*func)();
|
jpayne@69
|
2008 }
|
jpayne@69
|
2009 }
|
jpayne@69
|
2010
|
jpayne@69
|
2011 void cancel() {
|
jpayne@69
|
2012 maybeFunc = nullptr;
|
jpayne@69
|
2013 }
|
jpayne@69
|
2014
|
jpayne@69
|
2015 private:
|
jpayne@69
|
2016 kj::Maybe<Func> maybeFunc;
|
jpayne@69
|
2017 // Note that `Func` may actually be an lvalue reference because `kj::defer` takes its argument via
|
jpayne@69
|
2018 // universal reference. `kj::Maybe` has specializations for lvalue reference types, so this works
|
jpayne@69
|
2019 // out.
|
jpayne@69
|
2020 };
|
jpayne@69
|
2021
|
jpayne@69
|
2022 } // namespace _ (private)
|
jpayne@69
|
2023
|
jpayne@69
|
2024 template <typename Func>
|
jpayne@69
|
2025 _::Deferred<Func> defer(Func&& func) {
|
jpayne@69
|
2026 // Returns an object which will invoke the given functor in its destructor. The object is not
|
jpayne@69
|
2027 // copyable but is move-constructable with the semantics you'd expect. Since the return type is
|
jpayne@69
|
2028 // private, you need to assign to an `auto` variable.
|
jpayne@69
|
2029 //
|
jpayne@69
|
2030 // The KJ_DEFER macro provides slightly more convenient syntax for the common case where you
|
jpayne@69
|
2031 // want some code to run at current scope exit.
|
jpayne@69
|
2032 //
|
jpayne@69
|
2033 // KJ_DEFER does not support move-assignment for its returned objects. If you need to reuse the
|
jpayne@69
|
2034 // variable for your deferred function object, then you will want to write your own class for that
|
jpayne@69
|
2035 // purpose.
|
jpayne@69
|
2036
|
jpayne@69
|
2037 return _::Deferred<Func>(kj::fwd<Func>(func));
|
jpayne@69
|
2038 }
|
jpayne@69
|
2039
|
jpayne@69
|
2040 #define KJ_DEFER(code) auto KJ_UNIQUE_NAME(_kjDefer) = ::kj::defer([&](){code;})
|
jpayne@69
|
2041 // Run the given code when the function exits, whether by return or exception.
|
jpayne@69
|
2042
|
jpayne@69
|
2043 } // namespace kj
|
jpayne@69
|
2044
|
jpayne@69
|
2045 KJ_END_HEADER
|