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