annotate win64-msvc/include/capnp/common.h @ 148:b4bfdf10c4b3

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