annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/include/kj/common.h @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
rev   line source
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