annotate osx/include/capnp/common.h @ 62:0994c39f1e94

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