common.h 26.2 KB
Newer Older
Kenton Varda's avatar
Kenton Varda committed
1 2
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
3
//
Kenton Varda's avatar
Kenton Varda committed
4 5 6 7 8 9
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
10
//
Kenton Varda's avatar
Kenton Varda committed
11 12
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
13
//
Kenton Varda's avatar
Kenton Varda committed
14 15 16 17 18 19 20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
21 22 23 24 25

// This file contains types which are intended to help detect incorrect usage at compile
// time, but should then be optimized down to basic primitives (usually, integers) by the
// compiler.

Kenton Varda's avatar
Kenton Varda committed
26 27
#ifndef CAPNP_COMMON_H_
#define CAPNP_COMMON_H_
28

29
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
30 31 32
#pragma GCC system_header
#endif

Kenton Varda's avatar
Kenton Varda committed
33
#include <inttypes.h>
34
#include <kj/string.h>
35
#include <kj/memory.h>
36

37 38 39 40
#if CAPNP_DEBUG_TYPES
#include <kj/units.h>
#endif

41
namespace capnp {
42

43
#define CAPNP_VERSION_MAJOR 0
44
#define CAPNP_VERSION_MINOR 7
45 46 47 48 49
#define CAPNP_VERSION_MICRO 0

#define CAPNP_VERSION \
  (CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO)

50 51 52 53
#ifndef CAPNP_LITE
#define CAPNP_LITE 0
#endif

54 55
typedef unsigned int uint;

56 57 58 59 60 61
struct Void {
  // Type used for Void fields.  Using C++'s "void" type creates a bunch of issues since it behaves
  // differently from other types.

  inline constexpr bool operator==(Void other) const { return true; }
  inline constexpr bool operator!=(Void other) const { return false; }
62
};
63

64
static constexpr Void VOID = Void();
65 66
// Constant value for `Void`,  which is an empty struct.

67
inline kj::StringPtr KJ_STRINGIFY(Void) { return "void"; }
68

69 70 71 72 73 74 75 76 77 78 79
struct Text;
struct Data;

enum class Kind: uint8_t {
  PRIMITIVE,
  BLOB,
  ENUM,
  STRUCT,
  UNION,
  INTERFACE,
  LIST,
80 81 82 83

  OTHER
  // Some other type which is often a type parameter to Cap'n Proto templates, but which needs
  // special handling. This includes types like AnyPointer, Dynamic*, etc.
84 85
};

86 87 88 89 90 91 92
enum class Style: uint8_t {
  PRIMITIVE,
  POINTER,      // other than struct
  STRUCT,
  CAPABILITY
};

93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
enum class ElementSize: uint8_t {
  // Size of a list element.

  VOID = 0,
  BIT = 1,
  BYTE = 2,
  TWO_BYTES = 3,
  FOUR_BYTES = 4,
  EIGHT_BYTES = 5,

  POINTER = 6,

  INLINE_COMPOSITE = 7
};

108 109 110 111 112 113 114 115
enum class PointerType {
  // Various wire types a pointer field can take

  NULL_,
  // Should be NULL, but that's #defined in stddef.h

  STRUCT,
  LIST,
116
  CAPABILITY
117 118
};

119 120 121 122 123 124 125
namespace schemas {

template <typename T>
struct EnumInfo;

}  // namespace schemas

126 127
namespace _ {  // private

128
template <typename T, typename = void> struct Kind_;
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

template <> struct Kind_<Void> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<bool> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<int8_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<int16_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<int32_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<int64_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<uint8_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<uint16_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<uint32_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<uint64_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<float> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<double> { static constexpr Kind kind = Kind::PRIMITIVE; };
template <> struct Kind_<Text> { static constexpr Kind kind = Kind::BLOB; };
template <> struct Kind_<Data> { static constexpr Kind kind = Kind::BLOB; };

145 146 147 148 149 150 151 152 153
template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsStruct>> {
  static constexpr Kind kind = Kind::STRUCT;
};
template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsInterface>> {
  static constexpr Kind kind = Kind::INTERFACE;
};
template <typename T> struct Kind_<T, kj::VoidSfinae<typename schemas::EnumInfo<T>::IsEnum>> {
  static constexpr Kind kind = Kind::ENUM;
};
154

155 156
}  // namespace _ (private)

157 158 159 160 161 162 163
template <typename T, Kind k = _::Kind_<T>::kind>
inline constexpr Kind kind() {
  // This overload of kind() matches types which have a Kind_ specialization.

  return k;
}

164 165 166 167 168 169 170
#if CAPNP_LITE

#define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind
// Avoid constexpr methods in lite mode (MSVC is bad at constexpr).

#else  // CAPNP_LITE

171 172
#define CAPNP_KIND(T) ::capnp::kind<T>()
// Use this macro rather than kind<T>() in any code which must work in lite mode.
173

174 175 176 177 178 179 180
template <typename T, Kind k = kind<T>()>
inline constexpr Style style() {
  return k == Kind::PRIMITIVE || k == Kind::ENUM ? Style::PRIMITIVE
       : k == Kind::STRUCT ? Style::STRUCT
       : k == Kind::INTERFACE ? Style::CAPABILITY : Style::POINTER;
}

181
#endif  // CAPNP_LITE, else
182

183
template <typename T, Kind k = CAPNP_KIND(T)>
184 185
struct List;

186 187 188 189 190 191 192 193 194 195 196
#if _MSC_VER

template <typename T, Kind k>
struct List {};
// For some reason, without this declaration, MSVC will error out on some uses of List
// claiming that "T" -- as used in the default initializer for the second template param, "k" --
// is not defined. I do not understand this error, but adding this empty default declaration fixes
// it.

#endif

197 198 199 200
template <typename T> struct ListElementType_;
template <typename T> struct ListElementType_<List<T>> { typedef T Type; };
template <typename T> using ListElementType = typename ListElementType_<T>::Type;

201
namespace _ {  // private
202
template <typename T, Kind k> struct Kind_<List<T, k>> {
203 204
  static constexpr Kind kind = Kind::LIST;
};
205 206
}  // namespace _ (private)

207
template <typename T, Kind k = CAPNP_KIND(T)> struct ReaderFor_ { typedef typename T::Reader Type; };
208 209
template <typename T> struct ReaderFor_<T, Kind::PRIMITIVE> { typedef T Type; };
template <typename T> struct ReaderFor_<T, Kind::ENUM> { typedef T Type; };
210
template <typename T> struct ReaderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
211 212 213
template <typename T> using ReaderFor = typename ReaderFor_<T>::Type;
// The type returned by List<T>::Reader::operator[].

214
template <typename T, Kind k = CAPNP_KIND(T)> struct BuilderFor_ { typedef typename T::Builder Type; };
215 216
template <typename T> struct BuilderFor_<T, Kind::PRIMITIVE> { typedef T Type; };
template <typename T> struct BuilderFor_<T, Kind::ENUM> { typedef T Type; };
217
template <typename T> struct BuilderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
218 219 220
template <typename T> using BuilderFor = typename BuilderFor_<T>::Type;
// The type returned by List<T>::Builder::operator[].

221
template <typename T, Kind k = CAPNP_KIND(T)> struct PipelineFor_ { typedef typename T::Pipeline Type;};
222 223 224
template <typename T> struct PipelineFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
template <typename T> using PipelineFor = typename PipelineFor_<T>::Type;

225
template <typename T, Kind k = CAPNP_KIND(T)> struct TypeIfEnum_;
226 227 228 229 230 231 232 233 234 235 236 237 238
template <typename T> struct TypeIfEnum_<T, Kind::ENUM> { typedef T Type; };

template <typename T>
using TypeIfEnum = typename TypeIfEnum_<kj::Decay<T>>::Type;

template <typename T>
using FromReader = typename kj::Decay<T>::Reads;
// FromReader<MyType::Reader> = MyType (for any Cap'n Proto type).

template <typename T>
using FromBuilder = typename kj::Decay<T>::Builds;
// FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type).

239 240 241 242
template <typename T>
using FromPipeline = typename kj::Decay<T>::Pipelines;
// FromBuilder<MyType::Pipeline> = MyType (for any Cap'n Proto type).

243 244 245 246 247 248 249 250
template <typename T>
using FromClient = typename kj::Decay<T>::Calls;
// FromReader<MyType::Client> = MyType (for any Cap'n Proto interface type).

template <typename T>
using FromServer = typename kj::Decay<T>::Serves;
// FromBuilder<MyType::Server> = MyType (for any Cap'n Proto interface type).

251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
template <typename T, typename = void>
struct FromAny_;

template <typename T>
struct FromAny_<T, kj::VoidSfinae<FromReader<T>>> {
  using Type = FromReader<T>;
};

template <typename T>
struct FromAny_<T, kj::VoidSfinae<FromBuilder<T>>> {
  using Type = FromBuilder<T>;
};

template <typename T>
struct FromAny_<T, kj::VoidSfinae<FromPipeline<T>>> {
  using Type = FromPipeline<T>;
};

// Note that T::Client is covered by FromReader

template <typename T>
struct FromAny_<kj::Own<T>, kj::VoidSfinae<FromServer<T>>> {
  using Type = FromServer<T>;
};

template <typename T>
struct FromAny_<T,
    kj::EnableIf<_::Kind_<T>::kind == Kind::PRIMITIVE || _::Kind_<T>::kind == Kind::ENUM>> {
  // TODO(msvc): Ideally the EnableIf condition would be `style<T>() == Style::PRIMITIVE`, but MSVC
  // cannot yet use style<T>() in this constexpr context.

  using Type = kj::Decay<T>;
283 284 285
};

template <typename T>
286
using FromAny = typename FromAny_<T>::Type;
287 288 289 290 291 292 293 294 295
// Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is:
//
//     Foo::Reader -> Foo
//     Foo::Builder -> Foo
//     Foo::Pipeline -> Foo
//     Foo::Client -> Foo
//     Own<Foo::Server> -> Foo
//     uint32_t -> uint32_t

296
namespace _ {  // private
297

298
template <typename T, Kind k = CAPNP_KIND(T)>
299
struct PointerHelpers;
300 301 302 303 304 305 306 307 308 309 310 311

#if _MSC_VER

template <typename T, Kind k>
struct PointerHelpers {};
// For some reason, without this declaration, MSVC will error out on some uses of PointerHelpers
// claiming that "T" -- as used in the default initializer for the second template param, "k" --
// is not defined. I do not understand this error, but adding this empty default declaration fixes
// it.

#endif

312 313
}  // namespace _ (private)

314 315 316 317 318 319
struct MessageSize {
  // Size of a message.  Every struct type has a method `.totalSize()` that returns this.
  uint64_t wordCount;
  uint capCount;
};

320 321 322 323 324
// =======================================================================================
// Raw memory types and measures

using kj::byte;

Kenton Varda's avatar
Kenton Varda committed
325
class word { uint64_t content KJ_UNUSED_MEMBER; KJ_DISALLOW_COPY(word); public: word() = default; };
326 327 328 329
// word is an opaque type with size of 64 bits.  This type is useful only to make pointer
// arithmetic clearer.  Since the contents are private, the only way to access them is to first
// reinterpret_cast to some other pointer type.
//
David Renshaw's avatar
David Renshaw committed
330
// Copying is disallowed because you should always use memcpy().  Otherwise, you may run afoul of
331 332 333 334 335 336 337 338
// aliasing rules.
//
// A pointer of type word* should always be word-aligned even if won't actually be dereferenced as
// that type.

static_assert(sizeof(byte) == 1, "uint8_t is not one byte?");
static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?");

339 340 341 342 343
#if CAPNP_DEBUG_TYPES
// Set CAPNP_DEBUG_TYPES to 1 to use kj::Quantity for "count" types.  Otherwise, plain integers are
// used.  All the code should still operate exactly the same, we just lose compile-time checking.
// Note that this will also change symbol names, so it's important that the library and any clients
// be compiled with the same setting here.
344
//
345 346 347
// We disable this by default to reduce symbol name size and avoid any possibility of the compiler
// failing to fully-optimize the types, but anyone modifying Cap'n Proto itself should enable this
// during development and testing.
348

349
namespace _ { class BitLabel; class ElementLabel; struct WirePointer; }
350

351
template <uint width, typename T = uint>
352
using BitCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::BitLabel>;
353
template <uint width, typename T = uint>
354
using ByteCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, byte>;
355
template <uint width, typename T = uint>
356
using WordCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, word>;
357
template <uint width, typename T = uint>
358
using ElementCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::ElementLabel>;
359
template <uint width, typename T = uint>
360
using WirePointerCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::WirePointer>;
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400

typedef BitCountN<8, uint8_t> BitCount8;
typedef BitCountN<16, uint16_t> BitCount16;
typedef BitCountN<32, uint32_t> BitCount32;
typedef BitCountN<64, uint64_t> BitCount64;
typedef BitCountN<sizeof(uint) * 8, uint> BitCount;

typedef ByteCountN<8, uint8_t> ByteCount8;
typedef ByteCountN<16, uint16_t> ByteCount16;
typedef ByteCountN<32, uint32_t> ByteCount32;
typedef ByteCountN<64, uint64_t> ByteCount64;
typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount;

typedef WordCountN<8, uint8_t> WordCount8;
typedef WordCountN<16, uint16_t> WordCount16;
typedef WordCountN<32, uint32_t> WordCount32;
typedef WordCountN<64, uint64_t> WordCount64;
typedef WordCountN<sizeof(uint) * 8, uint> WordCount;

typedef ElementCountN<8, uint8_t> ElementCount8;
typedef ElementCountN<16, uint16_t> ElementCount16;
typedef ElementCountN<32, uint32_t> ElementCount32;
typedef ElementCountN<64, uint64_t> ElementCount64;
typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount;

typedef WirePointerCountN<8, uint8_t> WirePointerCount8;
typedef WirePointerCountN<16, uint16_t> WirePointerCount16;
typedef WirePointerCountN<32, uint32_t> WirePointerCount32;
typedef WirePointerCountN<64, uint64_t> WirePointerCount64;
typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount;

template <uint width>
using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>());
template <uint width>
using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>());
template <uint width>
using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>());
template <uint width>
using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>());

401 402 403 404 405
using kj::bounded;
using kj::unbound;
using kj::unboundAs;
using kj::unboundMax;
using kj::unboundMaxBits;
406 407
using kj::assertMax;
using kj::assertMaxBits;
408
using kj::upgradeBound;
409 410
using kj::ThrowOverflow;
using kj::assumeBits;
411
using kj::assumeMax;
412
using kj::subtractChecked;
413
using kj::trySubtract;
414

415 416
template <typename T, typename U>
inline constexpr U* operator+(U* ptr, kj::Quantity<T, U> offset) {
417
  return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
418 419 420
}
template <typename T, typename U>
inline constexpr const U* operator+(const U* ptr, kj::Quantity<T, U> offset) {
421
  return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
422 423 424
}
template <typename T, typename U>
inline constexpr U* operator+=(U*& ptr, kj::Quantity<T, U> offset) {
425
  return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
426 427 428
}
template <typename T, typename U>
inline constexpr const U* operator+=(const U*& ptr, kj::Quantity<T, U> offset) {
429
  return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
430 431 432 433
}

template <typename T, typename U>
inline constexpr U* operator-(U* ptr, kj::Quantity<T, U> offset) {
434
  return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
435 436 437
}
template <typename T, typename U>
inline constexpr const U* operator-(const U* ptr, kj::Quantity<T, U> offset) {
438
  return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
439 440 441
}
template <typename T, typename U>
inline constexpr U* operator-=(U*& ptr, kj::Quantity<T, U> offset) {
442
  return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
443 444 445
}
template <typename T, typename U>
inline constexpr const U* operator-=(const U*& ptr, kj::Quantity<T, U> offset) {
446
  return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
447 448
}

449 450 451 452 453
constexpr auto BITS = kj::unit<BitCountN<1>>();
constexpr auto BYTES = kj::unit<ByteCountN<1>>();
constexpr auto WORDS = kj::unit<WordCountN<1>>();
constexpr auto ELEMENTS = kj::unit<ElementCountN<1>>();
constexpr auto POINTERS = kj::unit<WirePointerCountN<1>>();
454

455 456
constexpr auto ZERO = kj::bounded<0>();
constexpr auto ONE = kj::bounded<1>();
457

458
// GCC 4.7 actually gives unused warnings on these constants in opt mode...
459 460 461
constexpr auto BITS_PER_BYTE KJ_UNUSED = bounded<8>() * BITS / BYTES;
constexpr auto BITS_PER_WORD KJ_UNUSED = bounded<64>() * BITS / WORDS;
constexpr auto BYTES_PER_WORD KJ_UNUSED = bounded<8>() * BYTES / WORDS;
462

463 464
constexpr auto BITS_PER_POINTER KJ_UNUSED = bounded<64>() * BITS / POINTERS;
constexpr auto BYTES_PER_POINTER KJ_UNUSED = bounded<8>() * BYTES / POINTERS;
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
constexpr auto WORDS_PER_POINTER KJ_UNUSED = ONE * WORDS / POINTERS;

constexpr auto POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER;

constexpr uint SEGMENT_WORD_COUNT_BITS = 29;      // Number of words in a segment.
constexpr uint LIST_ELEMENT_COUNT_BITS = 29;      // Number of elements in a list.
constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16;  // Number of words in a Struct data section.
constexpr uint STRUCT_POINTER_COUNT_BITS = 16;    // Number of pointers in a Struct pointer section.
constexpr uint BLOB_SIZE_BITS = 29;               // Number of bytes in a blob.

typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount;
typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount;
typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount;
typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount;
typedef ByteCountN<BLOB_SIZE_BITS> BlobSize;

constexpr auto MAX_SEGMENT_WORDS =
482
    bounded<kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>()>() * WORDS;
483
constexpr auto MAX_LIST_ELEMENTS =
484
    bounded<kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>()>() * ELEMENTS;
485
constexpr auto MAX_STUCT_DATA_WORDS =
486
    bounded<kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>()>() * WORDS;
487
constexpr auto MAX_STRUCT_POINTER_COUNT =
488
    bounded<kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>()>() * POINTERS;
489 490 491 492

using StructDataBitCount = decltype(WordCountN<STRUCT_POINTER_COUNT_BITS>() * BITS_PER_WORD);
// Number of bits in a Struct data segment (should come out to BitCountN<22>).

493 494 495 496 497 498
using StructDataOffset = decltype(StructDataBitCount() * (ONE * ELEMENTS / BITS));
using StructPointerOffset = StructPointerCount;
// Type of a field offset.

inline StructDataOffset assumeDataOffset(uint32_t offset) {
  return assumeMax(MAX_STUCT_DATA_WORDS * BITS_PER_WORD * (ONE * ELEMENTS / BITS),
499
                   bounded(offset) * ELEMENTS);
500 501 502
}

inline StructPointerOffset assumePointerOffset(uint32_t offset) {
503
  return assumeMax(MAX_STRUCT_POINTER_COUNT, bounded(offset) * POINTERS);
504 505
}

506
constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1;
507
typedef kj::Quantity<kj::Bounded<MAX_TEXT_SIZE, uint>, byte> TextSize;
508
// Not including NUL terminator.
509 510

template <typename T>
511 512
inline KJ_CONSTEXPR() decltype(bounded<sizeof(T)>() * BYTES / ELEMENTS) bytesPerElement() {
  return bounded<sizeof(T)>() * BYTES / ELEMENTS;
513 514 515
}

template <typename T>
516 517
inline KJ_CONSTEXPR() decltype(bounded<sizeof(T) * 8>() * BITS / ELEMENTS) bitsPerElement() {
  return bounded<sizeof(T) * 8>() * BITS / ELEMENTS;
518 519
}

520
template <typename T, uint maxN>
521 522 523
inline constexpr kj::Quantity<kj::Bounded<maxN, size_t>, T>
intervalLength(const T* a, const T* b, kj::Quantity<kj::BoundedConst<maxN>, T>) {
  return kj::assumeMax<maxN>(b - a) * kj::unit<kj::Quantity<kj::BoundedConst<1u>, T>>();
524
}
525 526 527

template <typename T, typename U>
inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, kj::Quantity<T, U> size) {
528
  return kj::ArrayPtr<const U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>()));
529 530 531
}
template <typename T, typename U>
inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, kj::Quantity<T, U> size) {
532
  return kj::ArrayPtr<U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>()));
533 534
}

535 536
#else

537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
template <uint width, typename T = uint>
using BitCountN = T;
template <uint width, typename T = uint>
using ByteCountN = T;
template <uint width, typename T = uint>
using WordCountN = T;
template <uint width, typename T = uint>
using ElementCountN = T;
template <uint width, typename T = uint>
using WirePointerCountN = T;


// XXX
typedef BitCountN<8, uint8_t> BitCount8;
typedef BitCountN<16, uint16_t> BitCount16;
typedef BitCountN<32, uint32_t> BitCount32;
typedef BitCountN<64, uint64_t> BitCount64;
typedef BitCountN<sizeof(uint) * 8, uint> BitCount;

typedef ByteCountN<8, uint8_t> ByteCount8;
typedef ByteCountN<16, uint16_t> ByteCount16;
typedef ByteCountN<32, uint32_t> ByteCount32;
typedef ByteCountN<64, uint64_t> ByteCount64;
typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount;

typedef WordCountN<8, uint8_t> WordCount8;
typedef WordCountN<16, uint16_t> WordCount16;
typedef WordCountN<32, uint32_t> WordCount32;
typedef WordCountN<64, uint64_t> WordCount64;
typedef WordCountN<sizeof(uint) * 8, uint> WordCount;

typedef ElementCountN<8, uint8_t> ElementCount8;
typedef ElementCountN<16, uint16_t> ElementCount16;
typedef ElementCountN<32, uint32_t> ElementCount32;
typedef ElementCountN<64, uint64_t> ElementCount64;
typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount;

typedef WirePointerCountN<8, uint8_t> WirePointerCount8;
typedef WirePointerCountN<16, uint16_t> WirePointerCount16;
typedef WirePointerCountN<32, uint32_t> WirePointerCount32;
typedef WirePointerCountN<64, uint64_t> WirePointerCount64;
typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount;

template <uint width>
using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>());
template <uint width>
using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>());
template <uint width>
using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>());
template <uint width>
using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>());

using kj::ThrowOverflow;
// YYY

592 593 594
template <uint i> inline constexpr uint bounded() { return i; }
template <typename T> inline constexpr T bounded(T i) { return i; }
template <typename T> inline constexpr T unbound(T i) { return i; }
595

596
template <typename T, typename U> inline constexpr T unboundAs(U i) { return i; }
597

598 599
template <uint64_t requestedMax, typename T> inline constexpr uint unboundMax(T i) { return i; }
template <uint bits, typename T> inline constexpr uint unboundMaxBits(T i) { return i; }
600 601

template <uint newMax, typename T, typename ErrorFunc>
602
inline T assertMax(T value, ErrorFunc&& func) {
603 604 605 606 607
  if (KJ_UNLIKELY(value > newMax)) func();
  return value;
}

template <typename T, typename ErrorFunc>
608
inline T assertMax(uint newMax, T value, ErrorFunc&& func) {
609 610 611 612 613
  if (KJ_UNLIKELY(value > newMax)) func();
  return value;
}

template <uint bits, typename T, typename ErrorFunc = ThrowOverflow>
614
inline T assertMaxBits(T value, ErrorFunc&& func = ErrorFunc()) {
615 616 617 618 619
  if (KJ_UNLIKELY(value > kj::maxValueForBits<bits>())) func();
  return value;
}

template <typename T, typename ErrorFunc = ThrowOverflow>
620
inline T assertMaxBits(uint bits, T value, ErrorFunc&& func = ErrorFunc()) {
621 622 623 624
  if (KJ_UNLIKELY(value > (1ull << bits) - 1)) func();
  return value;
}

625
template <typename T, typename U> inline constexpr T upgradeBound(U i) { return i; }
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713

template <uint bits, typename T> inline constexpr T assumeBits(T i) { return i; }
template <uint64_t max, typename T> inline constexpr T assumeMax(T i) { return i; }

template <typename T, typename U, typename ErrorFunc = ThrowOverflow>
inline auto subtractChecked(T a, U b, ErrorFunc&& errorFunc = ErrorFunc())
    -> decltype(a - b) {
  if (b > a) errorFunc();
  return a - b;
}

template <typename T, typename U>
inline auto trySubtract(T a, U b) -> kj::Maybe<decltype(a - b)> {
  if (b > a) {
    return nullptr;
  } else {
    return a - b;
  }
}

constexpr uint BITS = 1;
constexpr uint BYTES = 1;
constexpr uint WORDS = 1;
constexpr uint ELEMENTS = 1;
constexpr uint POINTERS = 1;

constexpr uint ZERO = 0;
constexpr uint ONE = 1;

// GCC 4.7 actually gives unused warnings on these constants in opt mode...
constexpr uint BITS_PER_BYTE KJ_UNUSED = 8;
constexpr uint BITS_PER_WORD KJ_UNUSED = 64;
constexpr uint BYTES_PER_WORD KJ_UNUSED = 8;

constexpr uint BITS_PER_POINTER KJ_UNUSED = 64;
constexpr uint BYTES_PER_POINTER KJ_UNUSED = 8;
constexpr uint WORDS_PER_POINTER KJ_UNUSED = 1;

// XXX
constexpr uint POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER;

constexpr uint SEGMENT_WORD_COUNT_BITS = 29;      // Number of words in a segment.
constexpr uint LIST_ELEMENT_COUNT_BITS = 29;      // Number of elements in a list.
constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16;  // Number of words in a Struct data section.
constexpr uint STRUCT_POINTER_COUNT_BITS = 16;    // Number of pointers in a Struct pointer section.
constexpr uint BLOB_SIZE_BITS = 29;               // Number of bytes in a blob.

typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount;
typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount;
typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount;
typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount;
typedef ByteCountN<BLOB_SIZE_BITS> BlobSize;
// YYY

constexpr auto MAX_SEGMENT_WORDS = kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>();
constexpr auto MAX_LIST_ELEMENTS = kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>();
constexpr auto MAX_STUCT_DATA_WORDS = kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>();
constexpr auto MAX_STRUCT_POINTER_COUNT = kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>();

typedef uint StructDataBitCount;
typedef uint StructDataOffset;
typedef uint StructPointerOffset;

inline StructDataOffset assumeDataOffset(uint32_t offset) { return offset; }
inline StructPointerOffset assumePointerOffset(uint32_t offset) { return offset; }

constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1;
typedef uint TextSize;

template <typename T>
inline KJ_CONSTEXPR() size_t bytesPerElement() { return sizeof(T); }

template <typename T>
inline KJ_CONSTEXPR() size_t bitsPerElement() { return sizeof(T) * 8; }

template <typename T>
inline constexpr ptrdiff_t intervalLength(const T* a, const T* b, uint) {
  return b - a;
}

template <typename T, typename U>
inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, T size) {
  return kj::arrayPtr(ptr, size);
}
template <typename T, typename U>
inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, T size) {
  return kj::arrayPtr(ptr, size);
}
714 715 716

#endif

717
}  // namespace capnp
718

Kenton Varda's avatar
Kenton Varda committed
719
#endif  // CAPNP_COMMON_H_