annotate win64-msvc/include/capnp/common.h @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +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_