annotate osx/include/capnp/common.h @ 83:ae30d91d2ffe

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