annotate win64-msvc/include/capnp/common.h @ 77:4edcd14160a5 pa_catalina

Duplicate for patch testing
author Chris Cannam
date Wed, 30 Oct 2019 11:25:10 +0000
parents 0f2d93caa50c
children
rev   line source
Chris@63 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
Chris@63 2 // Licensed under the MIT License:
Chris@63 3 //
Chris@63 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
Chris@63 5 // of this software and associated documentation files (the "Software"), to deal
Chris@63 6 // in the Software without restriction, including without limitation the rights
Chris@63 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Chris@63 8 // copies of the Software, and to permit persons to whom the Software is
Chris@63 9 // furnished to do so, subject to the following conditions:
Chris@63 10 //
Chris@63 11 // The above copyright notice and this permission notice shall be included in
Chris@63 12 // all copies or substantial portions of the Software.
Chris@63 13 //
Chris@63 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Chris@63 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Chris@63 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Chris@63 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Chris@63 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Chris@63 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Chris@63 20 // THE SOFTWARE.
Chris@63 21
Chris@63 22 // This file contains types which are intended to help detect incorrect usage at compile
Chris@63 23 // time, but should then be optimized down to basic primitives (usually, integers) by the
Chris@63 24 // compiler.
Chris@63 25
Chris@63 26 #ifndef CAPNP_COMMON_H_
Chris@63 27 #define CAPNP_COMMON_H_
Chris@63 28
Chris@63 29 #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
Chris@63 30 #pragma GCC system_header
Chris@63 31 #endif
Chris@63 32
Chris@63 33 #include <inttypes.h>
Chris@63 34 #include <kj/string.h>
Chris@63 35 #include <kj/memory.h>
Chris@63 36
Chris@63 37 #if CAPNP_DEBUG_TYPES
Chris@63 38 #include <kj/units.h>
Chris@63 39 #endif
Chris@63 40
Chris@63 41 namespace capnp {
Chris@63 42
Chris@63 43 #define CAPNP_VERSION_MAJOR 0
Chris@63 44 #define CAPNP_VERSION_MINOR 6
Chris@63 45 #define CAPNP_VERSION_MICRO 0
Chris@63 46
Chris@63 47 #define CAPNP_VERSION \
Chris@63 48 (CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO)
Chris@63 49
Chris@63 50 #ifndef CAPNP_LITE
Chris@63 51 #define CAPNP_LITE 0
Chris@63 52 #endif
Chris@63 53
Chris@63 54 typedef unsigned int uint;
Chris@63 55
Chris@63 56 struct Void {
Chris@63 57 // Type used for Void fields. Using C++'s "void" type creates a bunch of issues since it behaves
Chris@63 58 // differently from other types.
Chris@63 59
Chris@63 60 inline constexpr bool operator==(Void other) const { return true; }
Chris@63 61 inline constexpr bool operator!=(Void other) const { return false; }
Chris@63 62 };
Chris@63 63
Chris@63 64 static constexpr Void VOID = Void();
Chris@63 65 // Constant value for `Void`, which is an empty struct.
Chris@63 66
Chris@63 67 inline kj::StringPtr KJ_STRINGIFY(Void) { return "void"; }
Chris@63 68
Chris@63 69 struct Text;
Chris@63 70 struct Data;
Chris@63 71
Chris@63 72 enum class Kind: uint8_t {
Chris@63 73 PRIMITIVE,
Chris@63 74 BLOB,
Chris@63 75 ENUM,
Chris@63 76 STRUCT,
Chris@63 77 UNION,
Chris@63 78 INTERFACE,
Chris@63 79 LIST,
Chris@63 80
Chris@63 81 OTHER
Chris@63 82 // Some other type which is often a type parameter to Cap'n Proto templates, but which needs
Chris@63 83 // special handling. This includes types like AnyPointer, Dynamic*, etc.
Chris@63 84 };
Chris@63 85
Chris@63 86 enum class Style: uint8_t {
Chris@63 87 PRIMITIVE,
Chris@63 88 POINTER, // other than struct
Chris@63 89 STRUCT,
Chris@63 90 CAPABILITY
Chris@63 91 };
Chris@63 92
Chris@63 93 enum class ElementSize: uint8_t {
Chris@63 94 // Size of a list element.
Chris@63 95
Chris@63 96 VOID = 0,
Chris@63 97 BIT = 1,
Chris@63 98 BYTE = 2,
Chris@63 99 TWO_BYTES = 3,
Chris@63 100 FOUR_BYTES = 4,
Chris@63 101 EIGHT_BYTES = 5,
Chris@63 102
Chris@63 103 POINTER = 6,
Chris@63 104
Chris@63 105 INLINE_COMPOSITE = 7
Chris@63 106 };
Chris@63 107
Chris@63 108 enum class PointerType {
Chris@63 109 // Various wire types a pointer field can take
Chris@63 110
Chris@63 111 NULL_,
Chris@63 112 // Should be NULL, but that's #defined in stddef.h
Chris@63 113
Chris@63 114 STRUCT,
Chris@63 115 LIST,
Chris@63 116 CAPABILITY
Chris@63 117 };
Chris@63 118
Chris@63 119 namespace schemas {
Chris@63 120
Chris@63 121 template <typename T>
Chris@63 122 struct EnumInfo;
Chris@63 123
Chris@63 124 } // namespace schemas
Chris@63 125
Chris@63 126 namespace _ { // private
Chris@63 127
Chris@63 128 template <typename T, typename = void> struct Kind_;
Chris@63 129
Chris@63 130 template <> struct Kind_<Void> { static constexpr Kind kind = Kind::PRIMITIVE; };
Chris@63 131 template <> struct Kind_<bool> { static constexpr Kind kind = Kind::PRIMITIVE; };
Chris@63 132 template <> struct Kind_<int8_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
Chris@63 133 template <> struct Kind_<int16_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
Chris@63 134 template <> struct Kind_<int32_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
Chris@63 135 template <> struct Kind_<int64_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
Chris@63 136 template <> struct Kind_<uint8_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
Chris@63 137 template <> struct Kind_<uint16_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
Chris@63 138 template <> struct Kind_<uint32_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
Chris@63 139 template <> struct Kind_<uint64_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
Chris@63 140 template <> struct Kind_<float> { static constexpr Kind kind = Kind::PRIMITIVE; };
Chris@63 141 template <> struct Kind_<double> { static constexpr Kind kind = Kind::PRIMITIVE; };
Chris@63 142 template <> struct Kind_<Text> { static constexpr Kind kind = Kind::BLOB; };
Chris@63 143 template <> struct Kind_<Data> { static constexpr Kind kind = Kind::BLOB; };
Chris@63 144
Chris@63 145 template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsStruct>> {
Chris@63 146 static constexpr Kind kind = Kind::STRUCT;
Chris@63 147 };
Chris@63 148 template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsInterface>> {
Chris@63 149 static constexpr Kind kind = Kind::INTERFACE;
Chris@63 150 };
Chris@63 151 template <typename T> struct Kind_<T, kj::VoidSfinae<typename schemas::EnumInfo<T>::IsEnum>> {
Chris@63 152 static constexpr Kind kind = Kind::ENUM;
Chris@63 153 };
Chris@63 154
Chris@63 155 } // namespace _ (private)
Chris@63 156
Chris@63 157 template <typename T, Kind k = _::Kind_<T>::kind>
Chris@63 158 inline constexpr Kind kind() {
Chris@63 159 // This overload of kind() matches types which have a Kind_ specialization.
Chris@63 160
Chris@63 161 return k;
Chris@63 162 }
Chris@63 163
Chris@63 164 #if CAPNP_LITE
Chris@63 165
Chris@63 166 #define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind
Chris@63 167 // Avoid constexpr methods in lite mode (MSVC is bad at constexpr).
Chris@63 168
Chris@63 169 #else // CAPNP_LITE
Chris@63 170
Chris@63 171 #define CAPNP_KIND(T) ::capnp::kind<T>()
Chris@63 172 // Use this macro rather than kind<T>() in any code which must work in lite mode.
Chris@63 173
Chris@63 174 template <typename T, Kind k = kind<T>()>
Chris@63 175 inline constexpr Style style() {
Chris@63 176 return k == Kind::PRIMITIVE || k == Kind::ENUM ? Style::PRIMITIVE
Chris@63 177 : k == Kind::STRUCT ? Style::STRUCT
Chris@63 178 : k == Kind::INTERFACE ? Style::CAPABILITY : Style::POINTER;
Chris@63 179 }
Chris@63 180
Chris@63 181 #endif // CAPNP_LITE, else
Chris@63 182
Chris@63 183 template <typename T, Kind k = CAPNP_KIND(T)>
Chris@63 184 struct List;
Chris@63 185
Chris@63 186 #if _MSC_VER
Chris@63 187
Chris@63 188 template <typename T, Kind k>
Chris@63 189 struct List {};
Chris@63 190 // For some reason, without this declaration, MSVC will error out on some uses of List
Chris@63 191 // claiming that "T" -- as used in the default initializer for the second template param, "k" --
Chris@63 192 // is not defined. I do not understand this error, but adding this empty default declaration fixes
Chris@63 193 // it.
Chris@63 194
Chris@63 195 #endif
Chris@63 196
Chris@63 197 template <typename T> struct ListElementType_;
Chris@63 198 template <typename T> struct ListElementType_<List<T>> { typedef T Type; };
Chris@63 199 template <typename T> using ListElementType = typename ListElementType_<T>::Type;
Chris@63 200
Chris@63 201 namespace _ { // private
Chris@63 202 template <typename T, Kind k> struct Kind_<List<T, k>> {
Chris@63 203 static constexpr Kind kind = Kind::LIST;
Chris@63 204 };
Chris@63 205 } // namespace _ (private)
Chris@63 206
Chris@63 207 template <typename T, Kind k = CAPNP_KIND(T)> struct ReaderFor_ { typedef typename T::Reader Type; };
Chris@63 208 template <typename T> struct ReaderFor_<T, Kind::PRIMITIVE> { typedef T Type; };
Chris@63 209 template <typename T> struct ReaderFor_<T, Kind::ENUM> { typedef T Type; };
Chris@63 210 template <typename T> struct ReaderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
Chris@63 211 template <typename T> using ReaderFor = typename ReaderFor_<T>::Type;
Chris@63 212 // The type returned by List<T>::Reader::operator[].
Chris@63 213
Chris@63 214 template <typename T, Kind k = CAPNP_KIND(T)> struct BuilderFor_ { typedef typename T::Builder Type; };
Chris@63 215 template <typename T> struct BuilderFor_<T, Kind::PRIMITIVE> { typedef T Type; };
Chris@63 216 template <typename T> struct BuilderFor_<T, Kind::ENUM> { typedef T Type; };
Chris@63 217 template <typename T> struct BuilderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
Chris@63 218 template <typename T> using BuilderFor = typename BuilderFor_<T>::Type;
Chris@63 219 // The type returned by List<T>::Builder::operator[].
Chris@63 220
Chris@63 221 template <typename T, Kind k = CAPNP_KIND(T)> struct PipelineFor_ { typedef typename T::Pipeline Type;};
Chris@63 222 template <typename T> struct PipelineFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
Chris@63 223 template <typename T> using PipelineFor = typename PipelineFor_<T>::Type;
Chris@63 224
Chris@63 225 template <typename T, Kind k = CAPNP_KIND(T)> struct TypeIfEnum_;
Chris@63 226 template <typename T> struct TypeIfEnum_<T, Kind::ENUM> { typedef T Type; };
Chris@63 227
Chris@63 228 template <typename T>
Chris@63 229 using TypeIfEnum = typename TypeIfEnum_<kj::Decay<T>>::Type;
Chris@63 230
Chris@63 231 template <typename T>
Chris@63 232 using FromReader = typename kj::Decay<T>::Reads;
Chris@63 233 // FromReader<MyType::Reader> = MyType (for any Cap'n Proto type).
Chris@63 234
Chris@63 235 template <typename T>
Chris@63 236 using FromBuilder = typename kj::Decay<T>::Builds;
Chris@63 237 // FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type).
Chris@63 238
Chris@63 239 template <typename T>
Chris@63 240 using FromPipeline = typename kj::Decay<T>::Pipelines;
Chris@63 241 // FromBuilder<MyType::Pipeline> = MyType (for any Cap'n Proto type).
Chris@63 242
Chris@63 243 template <typename T>
Chris@63 244 using FromClient = typename kj::Decay<T>::Calls;
Chris@63 245 // FromReader<MyType::Client> = MyType (for any Cap'n Proto interface type).
Chris@63 246
Chris@63 247 template <typename T>
Chris@63 248 using FromServer = typename kj::Decay<T>::Serves;
Chris@63 249 // FromBuilder<MyType::Server> = MyType (for any Cap'n Proto interface type).
Chris@63 250
Chris@63 251 template <typename T, typename = void>
Chris@63 252 struct FromAny_;
Chris@63 253
Chris@63 254 template <typename T>
Chris@63 255 struct FromAny_<T, kj::VoidSfinae<FromReader<T>>> {
Chris@63 256 using Type = FromReader<T>;
Chris@63 257 };
Chris@63 258
Chris@63 259 template <typename T>
Chris@63 260 struct FromAny_<T, kj::VoidSfinae<FromBuilder<T>>> {
Chris@63 261 using Type = FromBuilder<T>;
Chris@63 262 };
Chris@63 263
Chris@63 264 template <typename T>
Chris@63 265 struct FromAny_<T, kj::VoidSfinae<FromPipeline<T>>> {
Chris@63 266 using Type = FromPipeline<T>;
Chris@63 267 };
Chris@63 268
Chris@63 269 // Note that T::Client is covered by FromReader
Chris@63 270
Chris@63 271 template <typename T>
Chris@63 272 struct FromAny_<kj::Own<T>, kj::VoidSfinae<FromServer<T>>> {
Chris@63 273 using Type = FromServer<T>;
Chris@63 274 };
Chris@63 275
Chris@63 276 template <typename T>
Chris@63 277 struct FromAny_<T,
Chris@63 278 kj::EnableIf<_::Kind_<T>::kind == Kind::PRIMITIVE || _::Kind_<T>::kind == Kind::ENUM>> {
Chris@63 279 // TODO(msvc): Ideally the EnableIf condition would be `style<T>() == Style::PRIMITIVE`, but MSVC
Chris@63 280 // cannot yet use style<T>() in this constexpr context.
Chris@63 281
Chris@63 282 using Type = kj::Decay<T>;
Chris@63 283 };
Chris@63 284
Chris@63 285 template <typename T>
Chris@63 286 using FromAny = typename FromAny_<T>::Type;
Chris@63 287 // Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is:
Chris@63 288 //
Chris@63 289 // Foo::Reader -> Foo
Chris@63 290 // Foo::Builder -> Foo
Chris@63 291 // Foo::Pipeline -> Foo
Chris@63 292 // Foo::Client -> Foo
Chris@63 293 // Own<Foo::Server> -> Foo
Chris@63 294 // uint32_t -> uint32_t
Chris@63 295
Chris@63 296 namespace _ { // private
Chris@63 297
Chris@63 298 template <typename T, Kind k = CAPNP_KIND(T)>
Chris@63 299 struct PointerHelpers;
Chris@63 300
Chris@63 301 #if _MSC_VER
Chris@63 302
Chris@63 303 template <typename T, Kind k>
Chris@63 304 struct PointerHelpers {};
Chris@63 305 // For some reason, without this declaration, MSVC will error out on some uses of PointerHelpers
Chris@63 306 // claiming that "T" -- as used in the default initializer for the second template param, "k" --
Chris@63 307 // is not defined. I do not understand this error, but adding this empty default declaration fixes
Chris@63 308 // it.
Chris@63 309
Chris@63 310 #endif
Chris@63 311
Chris@63 312 } // namespace _ (private)
Chris@63 313
Chris@63 314 struct MessageSize {
Chris@63 315 // Size of a message. Every struct type has a method `.totalSize()` that returns this.
Chris@63 316 uint64_t wordCount;
Chris@63 317 uint capCount;
Chris@63 318 };
Chris@63 319
Chris@63 320 // =======================================================================================
Chris@63 321 // Raw memory types and measures
Chris@63 322
Chris@63 323 using kj::byte;
Chris@63 324
Chris@63 325 class word { uint64_t content KJ_UNUSED_MEMBER; KJ_DISALLOW_COPY(word); public: word() = default; };
Chris@63 326 // word is an opaque type with size of 64 bits. This type is useful only to make pointer
Chris@63 327 // arithmetic clearer. Since the contents are private, the only way to access them is to first
Chris@63 328 // reinterpret_cast to some other pointer type.
Chris@63 329 //
Chris@63 330 // Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of
Chris@63 331 // aliasing rules.
Chris@63 332 //
Chris@63 333 // A pointer of type word* should always be word-aligned even if won't actually be dereferenced as
Chris@63 334 // that type.
Chris@63 335
Chris@63 336 static_assert(sizeof(byte) == 1, "uint8_t is not one byte?");
Chris@63 337 static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?");
Chris@63 338
Chris@63 339 #if CAPNP_DEBUG_TYPES
Chris@63 340 // Set CAPNP_DEBUG_TYPES to 1 to use kj::Quantity for "count" types. Otherwise, plain integers are
Chris@63 341 // used. All the code should still operate exactly the same, we just lose compile-time checking.
Chris@63 342 // Note that this will also change symbol names, so it's important that the library and any clients
Chris@63 343 // be compiled with the same setting here.
Chris@63 344 //
Chris@63 345 // We disable this by default to reduce symbol name size and avoid any possibility of the compiler
Chris@63 346 // failing to fully-optimize the types, but anyone modifying Cap'n Proto itself should enable this
Chris@63 347 // during development and testing.
Chris@63 348
Chris@63 349 namespace _ { class BitLabel; class ElementLabel; struct WirePointer; }
Chris@63 350
Chris@63 351 template <uint width, typename T = uint>
Chris@63 352 using BitCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::BitLabel>;
Chris@63 353 template <uint width, typename T = uint>
Chris@63 354 using ByteCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, byte>;
Chris@63 355 template <uint width, typename T = uint>
Chris@63 356 using WordCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, word>;
Chris@63 357 template <uint width, typename T = uint>
Chris@63 358 using ElementCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::ElementLabel>;
Chris@63 359 template <uint width, typename T = uint>
Chris@63 360 using WirePointerCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::WirePointer>;
Chris@63 361
Chris@63 362 typedef BitCountN<8, uint8_t> BitCount8;
Chris@63 363 typedef BitCountN<16, uint16_t> BitCount16;
Chris@63 364 typedef BitCountN<32, uint32_t> BitCount32;
Chris@63 365 typedef BitCountN<64, uint64_t> BitCount64;
Chris@63 366 typedef BitCountN<sizeof(uint) * 8, uint> BitCount;
Chris@63 367
Chris@63 368 typedef ByteCountN<8, uint8_t> ByteCount8;
Chris@63 369 typedef ByteCountN<16, uint16_t> ByteCount16;
Chris@63 370 typedef ByteCountN<32, uint32_t> ByteCount32;
Chris@63 371 typedef ByteCountN<64, uint64_t> ByteCount64;
Chris@63 372 typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount;
Chris@63 373
Chris@63 374 typedef WordCountN<8, uint8_t> WordCount8;
Chris@63 375 typedef WordCountN<16, uint16_t> WordCount16;
Chris@63 376 typedef WordCountN<32, uint32_t> WordCount32;
Chris@63 377 typedef WordCountN<64, uint64_t> WordCount64;
Chris@63 378 typedef WordCountN<sizeof(uint) * 8, uint> WordCount;
Chris@63 379
Chris@63 380 typedef ElementCountN<8, uint8_t> ElementCount8;
Chris@63 381 typedef ElementCountN<16, uint16_t> ElementCount16;
Chris@63 382 typedef ElementCountN<32, uint32_t> ElementCount32;
Chris@63 383 typedef ElementCountN<64, uint64_t> ElementCount64;
Chris@63 384 typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount;
Chris@63 385
Chris@63 386 typedef WirePointerCountN<8, uint8_t> WirePointerCount8;
Chris@63 387 typedef WirePointerCountN<16, uint16_t> WirePointerCount16;
Chris@63 388 typedef WirePointerCountN<32, uint32_t> WirePointerCount32;
Chris@63 389 typedef WirePointerCountN<64, uint64_t> WirePointerCount64;
Chris@63 390 typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount;
Chris@63 391
Chris@63 392 template <uint width>
Chris@63 393 using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>());
Chris@63 394 template <uint width>
Chris@63 395 using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>());
Chris@63 396 template <uint width>
Chris@63 397 using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>());
Chris@63 398 template <uint width>
Chris@63 399 using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>());
Chris@63 400
Chris@63 401 using kj::bounded;
Chris@63 402 using kj::unbound;
Chris@63 403 using kj::unboundAs;
Chris@63 404 using kj::unboundMax;
Chris@63 405 using kj::unboundMaxBits;
Chris@63 406 using kj::assertMax;
Chris@63 407 using kj::assertMaxBits;
Chris@63 408 using kj::upgradeBound;
Chris@63 409 using kj::ThrowOverflow;
Chris@63 410 using kj::assumeBits;
Chris@63 411 using kj::assumeMax;
Chris@63 412 using kj::subtractChecked;
Chris@63 413 using kj::trySubtract;
Chris@63 414
Chris@63 415 template <typename T, typename U>
Chris@63 416 inline constexpr U* operator+(U* ptr, kj::Quantity<T, U> offset) {
Chris@63 417 return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
Chris@63 418 }
Chris@63 419 template <typename T, typename U>
Chris@63 420 inline constexpr const U* operator+(const U* ptr, kj::Quantity<T, U> offset) {
Chris@63 421 return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
Chris@63 422 }
Chris@63 423 template <typename T, typename U>
Chris@63 424 inline constexpr U* operator+=(U*& ptr, kj::Quantity<T, U> offset) {
Chris@63 425 return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
Chris@63 426 }
Chris@63 427 template <typename T, typename U>
Chris@63 428 inline constexpr const U* operator+=(const U*& ptr, kj::Quantity<T, U> offset) {
Chris@63 429 return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
Chris@63 430 }
Chris@63 431
Chris@63 432 template <typename T, typename U>
Chris@63 433 inline constexpr U* operator-(U* ptr, kj::Quantity<T, U> offset) {
Chris@63 434 return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
Chris@63 435 }
Chris@63 436 template <typename T, typename U>
Chris@63 437 inline constexpr const U* operator-(const U* ptr, kj::Quantity<T, U> offset) {
Chris@63 438 return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
Chris@63 439 }
Chris@63 440 template <typename T, typename U>
Chris@63 441 inline constexpr U* operator-=(U*& ptr, kj::Quantity<T, U> offset) {
Chris@63 442 return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
Chris@63 443 }
Chris@63 444 template <typename T, typename U>
Chris@63 445 inline constexpr const U* operator-=(const U*& ptr, kj::Quantity<T, U> offset) {
Chris@63 446 return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
Chris@63 447 }
Chris@63 448
Chris@63 449 constexpr auto BITS = kj::unit<BitCountN<1>>();
Chris@63 450 constexpr auto BYTES = kj::unit<ByteCountN<1>>();
Chris@63 451 constexpr auto WORDS = kj::unit<WordCountN<1>>();
Chris@63 452 constexpr auto ELEMENTS = kj::unit<ElementCountN<1>>();
Chris@63 453 constexpr auto POINTERS = kj::unit<WirePointerCountN<1>>();
Chris@63 454
Chris@63 455 constexpr auto ZERO = kj::bounded<0>();
Chris@63 456 constexpr auto ONE = kj::bounded<1>();
Chris@63 457
Chris@63 458 // GCC 4.7 actually gives unused warnings on these constants in opt mode...
Chris@63 459 constexpr auto BITS_PER_BYTE KJ_UNUSED = bounded<8>() * BITS / BYTES;
Chris@63 460 constexpr auto BITS_PER_WORD KJ_UNUSED = bounded<64>() * BITS / WORDS;
Chris@63 461 constexpr auto BYTES_PER_WORD KJ_UNUSED = bounded<8>() * BYTES / WORDS;
Chris@63 462
Chris@63 463 constexpr auto BITS_PER_POINTER KJ_UNUSED = bounded<64>() * BITS / POINTERS;
Chris@63 464 constexpr auto BYTES_PER_POINTER KJ_UNUSED = bounded<8>() * BYTES / POINTERS;
Chris@63 465 constexpr auto WORDS_PER_POINTER KJ_UNUSED = ONE * WORDS / POINTERS;
Chris@63 466
Chris@63 467 constexpr auto POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER;
Chris@63 468
Chris@63 469 constexpr uint SEGMENT_WORD_COUNT_BITS = 29; // Number of words in a segment.
Chris@63 470 constexpr uint LIST_ELEMENT_COUNT_BITS = 29; // Number of elements in a list.
Chris@63 471 constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16; // Number of words in a Struct data section.
Chris@63 472 constexpr uint STRUCT_POINTER_COUNT_BITS = 16; // Number of pointers in a Struct pointer section.
Chris@63 473 constexpr uint BLOB_SIZE_BITS = 29; // Number of bytes in a blob.
Chris@63 474
Chris@63 475 typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount;
Chris@63 476 typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount;
Chris@63 477 typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount;
Chris@63 478 typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount;
Chris@63 479 typedef ByteCountN<BLOB_SIZE_BITS> BlobSize;
Chris@63 480
Chris@63 481 constexpr auto MAX_SEGMENT_WORDS =
Chris@63 482 bounded<kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>()>() * WORDS;
Chris@63 483 constexpr auto MAX_LIST_ELEMENTS =
Chris@63 484 bounded<kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>()>() * ELEMENTS;
Chris@63 485 constexpr auto MAX_STUCT_DATA_WORDS =
Chris@63 486 bounded<kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>()>() * WORDS;
Chris@63 487 constexpr auto MAX_STRUCT_POINTER_COUNT =
Chris@63 488 bounded<kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>()>() * POINTERS;
Chris@63 489
Chris@63 490 using StructDataBitCount = decltype(WordCountN<STRUCT_POINTER_COUNT_BITS>() * BITS_PER_WORD);
Chris@63 491 // Number of bits in a Struct data segment (should come out to BitCountN<22>).
Chris@63 492
Chris@63 493 using StructDataOffset = decltype(StructDataBitCount() * (ONE * ELEMENTS / BITS));
Chris@63 494 using StructPointerOffset = StructPointerCount;
Chris@63 495 // Type of a field offset.
Chris@63 496
Chris@63 497 inline StructDataOffset assumeDataOffset(uint32_t offset) {
Chris@63 498 return assumeMax(MAX_STUCT_DATA_WORDS * BITS_PER_WORD * (ONE * ELEMENTS / BITS),
Chris@63 499 bounded(offset) * ELEMENTS);
Chris@63 500 }
Chris@63 501
Chris@63 502 inline StructPointerOffset assumePointerOffset(uint32_t offset) {
Chris@63 503 return assumeMax(MAX_STRUCT_POINTER_COUNT, bounded(offset) * POINTERS);
Chris@63 504 }
Chris@63 505
Chris@63 506 constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1;
Chris@63 507 typedef kj::Quantity<kj::Bounded<MAX_TEXT_SIZE, uint>, byte> TextSize;
Chris@63 508 // Not including NUL terminator.
Chris@63 509
Chris@63 510 template <typename T>
Chris@63 511 inline KJ_CONSTEXPR() decltype(bounded<sizeof(T)>() * BYTES / ELEMENTS) bytesPerElement() {
Chris@63 512 return bounded<sizeof(T)>() * BYTES / ELEMENTS;
Chris@63 513 }
Chris@63 514
Chris@63 515 template <typename T>
Chris@63 516 inline KJ_CONSTEXPR() decltype(bounded<sizeof(T) * 8>() * BITS / ELEMENTS) bitsPerElement() {
Chris@63 517 return bounded<sizeof(T) * 8>() * BITS / ELEMENTS;
Chris@63 518 }
Chris@63 519
Chris@63 520 template <typename T, uint maxN>
Chris@63 521 inline constexpr kj::Quantity<kj::Bounded<maxN, size_t>, T>
Chris@63 522 intervalLength(const T* a, const T* b, kj::Quantity<kj::BoundedConst<maxN>, T>) {
Chris@63 523 return kj::assumeMax<maxN>(b - a) * kj::unit<kj::Quantity<kj::BoundedConst<1u>, T>>();
Chris@63 524 }
Chris@63 525
Chris@63 526 template <typename T, typename U>
Chris@63 527 inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, kj::Quantity<T, U> size) {
Chris@63 528 return kj::ArrayPtr<const U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>()));
Chris@63 529 }
Chris@63 530 template <typename T, typename U>
Chris@63 531 inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, kj::Quantity<T, U> size) {
Chris@63 532 return kj::ArrayPtr<U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>()));
Chris@63 533 }
Chris@63 534
Chris@63 535 #else
Chris@63 536
Chris@63 537 template <uint width, typename T = uint>
Chris@63 538 using BitCountN = T;
Chris@63 539 template <uint width, typename T = uint>
Chris@63 540 using ByteCountN = T;
Chris@63 541 template <uint width, typename T = uint>
Chris@63 542 using WordCountN = T;
Chris@63 543 template <uint width, typename T = uint>
Chris@63 544 using ElementCountN = T;
Chris@63 545 template <uint width, typename T = uint>
Chris@63 546 using WirePointerCountN = T;
Chris@63 547
Chris@63 548
Chris@63 549 // XXX
Chris@63 550 typedef BitCountN<8, uint8_t> BitCount8;
Chris@63 551 typedef BitCountN<16, uint16_t> BitCount16;
Chris@63 552 typedef BitCountN<32, uint32_t> BitCount32;
Chris@63 553 typedef BitCountN<64, uint64_t> BitCount64;
Chris@63 554 typedef BitCountN<sizeof(uint) * 8, uint> BitCount;
Chris@63 555
Chris@63 556 typedef ByteCountN<8, uint8_t> ByteCount8;
Chris@63 557 typedef ByteCountN<16, uint16_t> ByteCount16;
Chris@63 558 typedef ByteCountN<32, uint32_t> ByteCount32;
Chris@63 559 typedef ByteCountN<64, uint64_t> ByteCount64;
Chris@63 560 typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount;
Chris@63 561
Chris@63 562 typedef WordCountN<8, uint8_t> WordCount8;
Chris@63 563 typedef WordCountN<16, uint16_t> WordCount16;
Chris@63 564 typedef WordCountN<32, uint32_t> WordCount32;
Chris@63 565 typedef WordCountN<64, uint64_t> WordCount64;
Chris@63 566 typedef WordCountN<sizeof(uint) * 8, uint> WordCount;
Chris@63 567
Chris@63 568 typedef ElementCountN<8, uint8_t> ElementCount8;
Chris@63 569 typedef ElementCountN<16, uint16_t> ElementCount16;
Chris@63 570 typedef ElementCountN<32, uint32_t> ElementCount32;
Chris@63 571 typedef ElementCountN<64, uint64_t> ElementCount64;
Chris@63 572 typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount;
Chris@63 573
Chris@63 574 typedef WirePointerCountN<8, uint8_t> WirePointerCount8;
Chris@63 575 typedef WirePointerCountN<16, uint16_t> WirePointerCount16;
Chris@63 576 typedef WirePointerCountN<32, uint32_t> WirePointerCount32;
Chris@63 577 typedef WirePointerCountN<64, uint64_t> WirePointerCount64;
Chris@63 578 typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount;
Chris@63 579
Chris@63 580 template <uint width>
Chris@63 581 using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>());
Chris@63 582 template <uint width>
Chris@63 583 using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>());
Chris@63 584 template <uint width>
Chris@63 585 using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>());
Chris@63 586 template <uint width>
Chris@63 587 using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>());
Chris@63 588
Chris@63 589 using kj::ThrowOverflow;
Chris@63 590 // YYY
Chris@63 591
Chris@63 592 template <uint i> inline constexpr uint bounded() { return i; }
Chris@63 593 template <typename T> inline constexpr T bounded(T i) { return i; }
Chris@63 594 template <typename T> inline constexpr T unbound(T i) { return i; }
Chris@63 595
Chris@63 596 template <typename T, typename U> inline constexpr T unboundAs(U i) { return i; }
Chris@63 597
Chris@63 598 template <uint64_t requestedMax, typename T> inline constexpr uint unboundMax(T i) { return i; }
Chris@63 599 template <uint bits, typename T> inline constexpr uint unboundMaxBits(T i) { return i; }
Chris@63 600
Chris@63 601 template <uint newMax, typename T, typename ErrorFunc>
Chris@63 602 inline T assertMax(T value, ErrorFunc&& func) {
Chris@63 603 if (KJ_UNLIKELY(value > newMax)) func();
Chris@63 604 return value;
Chris@63 605 }
Chris@63 606
Chris@63 607 template <typename T, typename ErrorFunc>
Chris@63 608 inline T assertMax(uint newMax, T value, ErrorFunc&& func) {
Chris@63 609 if (KJ_UNLIKELY(value > newMax)) func();
Chris@63 610 return value;
Chris@63 611 }
Chris@63 612
Chris@63 613 template <uint bits, typename T, typename ErrorFunc = ThrowOverflow>
Chris@63 614 inline T assertMaxBits(T value, ErrorFunc&& func = ErrorFunc()) {
Chris@63 615 if (KJ_UNLIKELY(value > kj::maxValueForBits<bits>())) func();
Chris@63 616 return value;
Chris@63 617 }
Chris@63 618
Chris@63 619 template <typename T, typename ErrorFunc = ThrowOverflow>
Chris@63 620 inline T assertMaxBits(uint bits, T value, ErrorFunc&& func = ErrorFunc()) {
Chris@63 621 if (KJ_UNLIKELY(value > (1ull << bits) - 1)) func();
Chris@63 622 return value;
Chris@63 623 }
Chris@63 624
Chris@63 625 template <typename T, typename U> inline constexpr T upgradeBound(U i) { return i; }
Chris@63 626
Chris@63 627 template <uint bits, typename T> inline constexpr T assumeBits(T i) { return i; }
Chris@63 628 template <uint64_t max, typename T> inline constexpr T assumeMax(T i) { return i; }
Chris@63 629
Chris@63 630 template <typename T, typename U, typename ErrorFunc = ThrowOverflow>
Chris@63 631 inline auto subtractChecked(T a, U b, ErrorFunc&& errorFunc = ErrorFunc())
Chris@63 632 -> decltype(a - b) {
Chris@63 633 if (b > a) errorFunc();
Chris@63 634 return a - b;
Chris@63 635 }
Chris@63 636
Chris@63 637 template <typename T, typename U>
Chris@63 638 inline auto trySubtract(T a, U b) -> kj::Maybe<decltype(a - b)> {
Chris@63 639 if (b > a) {
Chris@63 640 return nullptr;
Chris@63 641 } else {
Chris@63 642 return a - b;
Chris@63 643 }
Chris@63 644 }
Chris@63 645
Chris@63 646 constexpr uint BITS = 1;
Chris@63 647 constexpr uint BYTES = 1;
Chris@63 648 constexpr uint WORDS = 1;
Chris@63 649 constexpr uint ELEMENTS = 1;
Chris@63 650 constexpr uint POINTERS = 1;
Chris@63 651
Chris@63 652 constexpr uint ZERO = 0;
Chris@63 653 constexpr uint ONE = 1;
Chris@63 654
Chris@63 655 // GCC 4.7 actually gives unused warnings on these constants in opt mode...
Chris@63 656 constexpr uint BITS_PER_BYTE KJ_UNUSED = 8;
Chris@63 657 constexpr uint BITS_PER_WORD KJ_UNUSED = 64;
Chris@63 658 constexpr uint BYTES_PER_WORD KJ_UNUSED = 8;
Chris@63 659
Chris@63 660 constexpr uint BITS_PER_POINTER KJ_UNUSED = 64;
Chris@63 661 constexpr uint BYTES_PER_POINTER KJ_UNUSED = 8;
Chris@63 662 constexpr uint WORDS_PER_POINTER KJ_UNUSED = 1;
Chris@63 663
Chris@63 664 // XXX
Chris@63 665 constexpr uint POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER;
Chris@63 666
Chris@63 667 constexpr uint SEGMENT_WORD_COUNT_BITS = 29; // Number of words in a segment.
Chris@63 668 constexpr uint LIST_ELEMENT_COUNT_BITS = 29; // Number of elements in a list.
Chris@63 669 constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16; // Number of words in a Struct data section.
Chris@63 670 constexpr uint STRUCT_POINTER_COUNT_BITS = 16; // Number of pointers in a Struct pointer section.
Chris@63 671 constexpr uint BLOB_SIZE_BITS = 29; // Number of bytes in a blob.
Chris@63 672
Chris@63 673 typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount;
Chris@63 674 typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount;
Chris@63 675 typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount;
Chris@63 676 typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount;
Chris@63 677 typedef ByteCountN<BLOB_SIZE_BITS> BlobSize;
Chris@63 678 // YYY
Chris@63 679
Chris@63 680 constexpr auto MAX_SEGMENT_WORDS = kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>();
Chris@63 681 constexpr auto MAX_LIST_ELEMENTS = kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>();
Chris@63 682 constexpr auto MAX_STUCT_DATA_WORDS = kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>();
Chris@63 683 constexpr auto MAX_STRUCT_POINTER_COUNT = kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>();
Chris@63 684
Chris@63 685 typedef uint StructDataBitCount;
Chris@63 686 typedef uint StructDataOffset;
Chris@63 687 typedef uint StructPointerOffset;
Chris@63 688
Chris@63 689 inline StructDataOffset assumeDataOffset(uint32_t offset) { return offset; }
Chris@63 690 inline StructPointerOffset assumePointerOffset(uint32_t offset) { return offset; }
Chris@63 691
Chris@63 692 constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1;
Chris@63 693 typedef uint TextSize;
Chris@63 694
Chris@63 695 template <typename T>
Chris@63 696 inline KJ_CONSTEXPR() size_t bytesPerElement() { return sizeof(T); }
Chris@63 697
Chris@63 698 template <typename T>
Chris@63 699 inline KJ_CONSTEXPR() size_t bitsPerElement() { return sizeof(T) * 8; }
Chris@63 700
Chris@63 701 template <typename T>
Chris@63 702 inline constexpr ptrdiff_t intervalLength(const T* a, const T* b, uint) {
Chris@63 703 return b - a;
Chris@63 704 }
Chris@63 705
Chris@63 706 template <typename T, typename U>
Chris@63 707 inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, T size) {
Chris@63 708 return kj::arrayPtr(ptr, size);
Chris@63 709 }
Chris@63 710 template <typename T, typename U>
Chris@63 711 inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, T size) {
Chris@63 712 return kj::arrayPtr(ptr, size);
Chris@63 713 }
Chris@63 714
Chris@63 715 #endif
Chris@63 716
Chris@63 717 } // namespace capnp
Chris@63 718
Chris@63 719 #endif // CAPNP_COMMON_H_