annotate win32-mingw/include/capnp/common.h @ 169:223a55898ab9 tip default

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