cannam@135: // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors cannam@135: // Licensed under the MIT License: cannam@135: // cannam@135: // Permission is hereby granted, free of charge, to any person obtaining a copy cannam@135: // of this software and associated documentation files (the "Software"), to deal cannam@135: // in the Software without restriction, including without limitation the rights cannam@135: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell cannam@135: // copies of the Software, and to permit persons to whom the Software is cannam@135: // furnished to do so, subject to the following conditions: cannam@135: // cannam@135: // The above copyright notice and this permission notice shall be included in cannam@135: // all copies or substantial portions of the Software. cannam@135: // cannam@135: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR cannam@135: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, cannam@135: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE cannam@135: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER cannam@135: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, cannam@135: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN cannam@135: // THE SOFTWARE. cannam@135: cannam@135: // This file contains types which are intended to help detect incorrect usage at compile cannam@135: // time, but should then be optimized down to basic primitives (usually, integers) by the cannam@135: // compiler. cannam@135: cannam@135: #ifndef CAPNP_COMMON_H_ cannam@135: #define CAPNP_COMMON_H_ cannam@135: cannam@135: #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) cannam@135: #pragma GCC system_header cannam@135: #endif cannam@135: cannam@135: #include cannam@135: #include cannam@135: #include cannam@135: #include cannam@135: cannam@135: namespace capnp { cannam@135: cannam@135: #define CAPNP_VERSION_MAJOR 0 cannam@135: #define CAPNP_VERSION_MINOR 6 cannam@135: #define CAPNP_VERSION_MICRO 0 cannam@135: cannam@135: #define CAPNP_VERSION \ cannam@135: (CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO) cannam@135: cannam@135: #ifdef _MSC_VER cannam@135: #define CAPNP_LITE 1 cannam@135: // MSVC only supports "lite" mode for now, due to missing C++11 features. cannam@135: #endif cannam@135: cannam@135: #ifndef CAPNP_LITE cannam@135: #define CAPNP_LITE 0 cannam@135: #endif cannam@135: cannam@135: typedef unsigned int uint; cannam@135: cannam@135: struct Void { cannam@135: // Type used for Void fields. Using C++'s "void" type creates a bunch of issues since it behaves cannam@135: // differently from other types. cannam@135: cannam@135: inline constexpr bool operator==(Void other) const { return true; } cannam@135: inline constexpr bool operator!=(Void other) const { return false; } cannam@135: }; cannam@135: cannam@135: static constexpr Void VOID = Void(); cannam@135: // Constant value for `Void`, which is an empty struct. cannam@135: cannam@135: inline kj::StringPtr KJ_STRINGIFY(Void) { return "void"; } cannam@135: cannam@135: struct Text; cannam@135: struct Data; cannam@135: cannam@135: enum class Kind: uint8_t { cannam@135: PRIMITIVE, cannam@135: BLOB, cannam@135: ENUM, cannam@135: STRUCT, cannam@135: UNION, cannam@135: INTERFACE, cannam@135: LIST, cannam@135: cannam@135: OTHER cannam@135: // Some other type which is often a type parameter to Cap'n Proto templates, but which needs cannam@135: // special handling. This includes types like AnyPointer, Dynamic*, etc. cannam@135: }; cannam@135: cannam@135: enum class Style: uint8_t { cannam@135: PRIMITIVE, cannam@135: POINTER, // other than struct cannam@135: STRUCT, cannam@135: CAPABILITY cannam@135: }; cannam@135: cannam@135: enum class ElementSize: uint8_t { cannam@135: // Size of a list element. cannam@135: cannam@135: VOID = 0, cannam@135: BIT = 1, cannam@135: BYTE = 2, cannam@135: TWO_BYTES = 3, cannam@135: FOUR_BYTES = 4, cannam@135: EIGHT_BYTES = 5, cannam@135: cannam@135: POINTER = 6, cannam@135: cannam@135: INLINE_COMPOSITE = 7 cannam@135: }; cannam@135: cannam@135: enum class PointerType { cannam@135: // Various wire types a pointer field can take cannam@135: cannam@135: NULL_, cannam@135: // Should be NULL, but that's #defined in stddef.h cannam@135: cannam@135: STRUCT, cannam@135: LIST, cannam@135: CAPABILITY cannam@135: }; cannam@135: cannam@135: namespace schemas { cannam@135: cannam@135: template cannam@135: struct EnumInfo; cannam@135: cannam@135: } // namespace schemas cannam@135: cannam@135: namespace _ { // private cannam@135: cannam@135: template struct Kind_; cannam@135: cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::BLOB; }; cannam@135: template <> struct Kind_ { static constexpr Kind kind = Kind::BLOB; }; cannam@135: cannam@135: template struct Kind_> { cannam@135: static constexpr Kind kind = Kind::STRUCT; cannam@135: }; cannam@135: template struct Kind_> { cannam@135: static constexpr Kind kind = Kind::INTERFACE; cannam@135: }; cannam@135: template struct Kind_::IsEnum>> { cannam@135: static constexpr Kind kind = Kind::ENUM; cannam@135: }; cannam@135: cannam@135: } // namespace _ (private) cannam@135: cannam@135: template ::kind> cannam@135: inline constexpr Kind kind() { cannam@135: // This overload of kind() matches types which have a Kind_ specialization. cannam@135: cannam@135: return k; cannam@135: } cannam@135: cannam@135: #if CAPNP_LITE cannam@135: cannam@135: #define CAPNP_KIND(T) ::capnp::_::Kind_::kind cannam@135: // Avoid constexpr methods in lite mode (MSVC is bad at constexpr). cannam@135: cannam@135: #else // CAPNP_LITE cannam@135: cannam@135: #define CAPNP_KIND(T) ::capnp::kind() cannam@135: // Use this macro rather than kind() in any code which must work in lite mode. cannam@135: cannam@135: template ()> cannam@135: inline constexpr Style style() { cannam@135: return k == Kind::PRIMITIVE || k == Kind::ENUM ? Style::PRIMITIVE cannam@135: : k == Kind::STRUCT ? Style::STRUCT cannam@135: : k == Kind::INTERFACE ? Style::CAPABILITY : Style::POINTER; cannam@135: } cannam@135: cannam@135: #endif // CAPNP_LITE, else cannam@135: cannam@135: template cannam@135: struct List; cannam@135: cannam@135: #if _MSC_VER cannam@135: cannam@135: template cannam@135: struct List {}; cannam@135: // For some reason, without this declaration, MSVC will error out on some uses of List cannam@135: // claiming that "T" -- as used in the default initializer for the second template param, "k" -- cannam@135: // is not defined. I do not understand this error, but adding this empty default declaration fixes cannam@135: // it. cannam@135: cannam@135: #endif cannam@135: cannam@135: template struct ListElementType_; cannam@135: template struct ListElementType_> { typedef T Type; }; cannam@135: template using ListElementType = typename ListElementType_::Type; cannam@135: cannam@135: namespace _ { // private cannam@135: template struct Kind_> { cannam@135: static constexpr Kind kind = Kind::LIST; cannam@135: }; cannam@135: } // namespace _ (private) cannam@135: cannam@135: template struct ReaderFor_ { typedef typename T::Reader Type; }; cannam@135: template struct ReaderFor_ { typedef T Type; }; cannam@135: template struct ReaderFor_ { typedef T Type; }; cannam@135: template struct ReaderFor_ { typedef typename T::Client Type; }; cannam@135: template using ReaderFor = typename ReaderFor_::Type; cannam@135: // The type returned by List::Reader::operator[]. cannam@135: cannam@135: template struct BuilderFor_ { typedef typename T::Builder Type; }; cannam@135: template struct BuilderFor_ { typedef T Type; }; cannam@135: template struct BuilderFor_ { typedef T Type; }; cannam@135: template struct BuilderFor_ { typedef typename T::Client Type; }; cannam@135: template using BuilderFor = typename BuilderFor_::Type; cannam@135: // The type returned by List::Builder::operator[]. cannam@135: cannam@135: template struct PipelineFor_ { typedef typename T::Pipeline Type;}; cannam@135: template struct PipelineFor_ { typedef typename T::Client Type; }; cannam@135: template using PipelineFor = typename PipelineFor_::Type; cannam@135: cannam@135: template struct TypeIfEnum_; cannam@135: template struct TypeIfEnum_ { typedef T Type; }; cannam@135: cannam@135: template cannam@135: using TypeIfEnum = typename TypeIfEnum_>::Type; cannam@135: cannam@135: template cannam@135: using FromReader = typename kj::Decay::Reads; cannam@135: // FromReader = MyType (for any Cap'n Proto type). cannam@135: cannam@135: template cannam@135: using FromBuilder = typename kj::Decay::Builds; cannam@135: // FromBuilder = MyType (for any Cap'n Proto type). cannam@135: cannam@135: template cannam@135: using FromPipeline = typename kj::Decay::Pipelines; cannam@135: // FromBuilder = MyType (for any Cap'n Proto type). cannam@135: cannam@135: template cannam@135: using FromClient = typename kj::Decay::Calls; cannam@135: // FromReader = MyType (for any Cap'n Proto interface type). cannam@135: cannam@135: template cannam@135: using FromServer = typename kj::Decay::Serves; cannam@135: // FromBuilder = MyType (for any Cap'n Proto interface type). cannam@135: cannam@135: template cannam@135: struct FromAny_; cannam@135: cannam@135: template cannam@135: struct FromAny_>> { cannam@135: using Type = FromReader; cannam@135: }; cannam@135: cannam@135: template cannam@135: struct FromAny_>> { cannam@135: using Type = FromBuilder; cannam@135: }; cannam@135: cannam@135: template cannam@135: struct FromAny_>> { cannam@135: using Type = FromPipeline; cannam@135: }; cannam@135: cannam@135: // Note that T::Client is covered by FromReader cannam@135: cannam@135: template cannam@135: struct FromAny_, kj::VoidSfinae>> { cannam@135: using Type = FromServer; cannam@135: }; cannam@135: cannam@135: template cannam@135: struct FromAny_::kind == Kind::PRIMITIVE || _::Kind_::kind == Kind::ENUM>> { cannam@135: // TODO(msvc): Ideally the EnableIf condition would be `style() == Style::PRIMITIVE`, but MSVC cannam@135: // cannot yet use style() in this constexpr context. cannam@135: cannam@135: using Type = kj::Decay; cannam@135: }; cannam@135: cannam@135: template cannam@135: using FromAny = typename FromAny_::Type; cannam@135: // Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is: cannam@135: // cannam@135: // Foo::Reader -> Foo cannam@135: // Foo::Builder -> Foo cannam@135: // Foo::Pipeline -> Foo cannam@135: // Foo::Client -> Foo cannam@135: // Own -> Foo cannam@135: // uint32_t -> uint32_t cannam@135: cannam@135: namespace _ { // private cannam@135: cannam@135: template cannam@135: struct PointerHelpers; cannam@135: cannam@135: #if _MSC_VER cannam@135: cannam@135: template cannam@135: struct PointerHelpers {}; cannam@135: // For some reason, without this declaration, MSVC will error out on some uses of PointerHelpers cannam@135: // claiming that "T" -- as used in the default initializer for the second template param, "k" -- cannam@135: // is not defined. I do not understand this error, but adding this empty default declaration fixes cannam@135: // it. cannam@135: cannam@135: #endif cannam@135: cannam@135: } // namespace _ (private) cannam@135: cannam@135: struct MessageSize { cannam@135: // Size of a message. Every struct type has a method `.totalSize()` that returns this. cannam@135: uint64_t wordCount; cannam@135: uint capCount; cannam@135: }; cannam@135: cannam@135: // ======================================================================================= cannam@135: // Raw memory types and measures cannam@135: cannam@135: using kj::byte; cannam@135: cannam@135: class word { uint64_t content KJ_UNUSED_MEMBER; KJ_DISALLOW_COPY(word); public: word() = default; }; cannam@135: // word is an opaque type with size of 64 bits. This type is useful only to make pointer cannam@135: // arithmetic clearer. Since the contents are private, the only way to access them is to first cannam@135: // reinterpret_cast to some other pointer type. cannam@135: // cannam@135: // Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of cannam@135: // aliasing rules. cannam@135: // cannam@135: // A pointer of type word* should always be word-aligned even if won't actually be dereferenced as cannam@135: // that type. cannam@135: cannam@135: static_assert(sizeof(byte) == 1, "uint8_t is not one byte?"); cannam@135: static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?"); cannam@135: cannam@135: #if CAPNP_DEBUG_TYPES cannam@135: // Set CAPNP_DEBUG_TYPES to 1 to use kj::Quantity for "count" types. Otherwise, plain integers are cannam@135: // used. All the code should still operate exactly the same, we just lose compile-time checking. cannam@135: // Note that this will also change symbol names, so it's important that the library and any clients cannam@135: // be compiled with the same setting here. cannam@135: // cannam@135: // We disable this by default to reduce symbol name size and avoid any possibility of the compiler cannam@135: // failing to fully-optimize the types, but anyone modifying Cap'n Proto itself should enable this cannam@135: // during development and testing. cannam@135: cannam@135: namespace _ { class BitLabel; class ElementLabel; struct WirePointer; } cannam@135: cannam@135: typedef kj::Quantity BitCount; cannam@135: typedef kj::Quantity BitCount8; cannam@135: typedef kj::Quantity BitCount16; cannam@135: typedef kj::Quantity BitCount32; cannam@135: typedef kj::Quantity BitCount64; cannam@135: cannam@135: typedef kj::Quantity ByteCount; cannam@135: typedef kj::Quantity ByteCount8; cannam@135: typedef kj::Quantity ByteCount16; cannam@135: typedef kj::Quantity ByteCount32; cannam@135: typedef kj::Quantity ByteCount64; cannam@135: cannam@135: typedef kj::Quantity WordCount; cannam@135: typedef kj::Quantity WordCount8; cannam@135: typedef kj::Quantity WordCount16; cannam@135: typedef kj::Quantity WordCount32; cannam@135: typedef kj::Quantity WordCount64; cannam@135: cannam@135: typedef kj::Quantity ElementCount; cannam@135: typedef kj::Quantity ElementCount8; cannam@135: typedef kj::Quantity ElementCount16; cannam@135: typedef kj::Quantity ElementCount32; cannam@135: typedef kj::Quantity ElementCount64; cannam@135: cannam@135: typedef kj::Quantity WirePointerCount; cannam@135: typedef kj::Quantity WirePointerCount8; cannam@135: typedef kj::Quantity WirePointerCount16; cannam@135: typedef kj::Quantity WirePointerCount32; cannam@135: typedef kj::Quantity WirePointerCount64; cannam@135: cannam@135: template cannam@135: inline constexpr U* operator+(U* ptr, kj::Quantity offset) { cannam@135: return ptr + offset / kj::unit>(); cannam@135: } cannam@135: template cannam@135: inline constexpr const U* operator+(const U* ptr, kj::Quantity offset) { cannam@135: return ptr + offset / kj::unit>(); cannam@135: } cannam@135: template cannam@135: inline constexpr U* operator+=(U*& ptr, kj::Quantity offset) { cannam@135: return ptr = ptr + offset / kj::unit>(); cannam@135: } cannam@135: template cannam@135: inline constexpr const U* operator+=(const U*& ptr, kj::Quantity offset) { cannam@135: return ptr = ptr + offset / kj::unit>(); cannam@135: } cannam@135: cannam@135: template cannam@135: inline constexpr U* operator-(U* ptr, kj::Quantity offset) { cannam@135: return ptr - offset / kj::unit>(); cannam@135: } cannam@135: template cannam@135: inline constexpr const U* operator-(const U* ptr, kj::Quantity offset) { cannam@135: return ptr - offset / kj::unit>(); cannam@135: } cannam@135: template cannam@135: inline constexpr U* operator-=(U*& ptr, kj::Quantity offset) { cannam@135: return ptr = ptr - offset / kj::unit>(); cannam@135: } cannam@135: template cannam@135: inline constexpr const U* operator-=(const U*& ptr, kj::Quantity offset) { cannam@135: return ptr = ptr - offset / kj::unit>(); cannam@135: } cannam@135: cannam@135: #else cannam@135: cannam@135: typedef uint BitCount; cannam@135: typedef uint8_t BitCount8; cannam@135: typedef uint16_t BitCount16; cannam@135: typedef uint32_t BitCount32; cannam@135: typedef uint64_t BitCount64; cannam@135: cannam@135: typedef uint ByteCount; cannam@135: typedef uint8_t ByteCount8; cannam@135: typedef uint16_t ByteCount16; cannam@135: typedef uint32_t ByteCount32; cannam@135: typedef uint64_t ByteCount64; cannam@135: cannam@135: typedef uint WordCount; cannam@135: typedef uint8_t WordCount8; cannam@135: typedef uint16_t WordCount16; cannam@135: typedef uint32_t WordCount32; cannam@135: typedef uint64_t WordCount64; cannam@135: cannam@135: typedef uint ElementCount; cannam@135: typedef uint8_t ElementCount8; cannam@135: typedef uint16_t ElementCount16; cannam@135: typedef uint32_t ElementCount32; cannam@135: typedef uint64_t ElementCount64; cannam@135: cannam@135: typedef uint WirePointerCount; cannam@135: typedef uint8_t WirePointerCount8; cannam@135: typedef uint16_t WirePointerCount16; cannam@135: typedef uint32_t WirePointerCount32; cannam@135: typedef uint64_t WirePointerCount64; cannam@135: cannam@135: #endif cannam@135: cannam@135: constexpr BitCount BITS = kj::unit(); cannam@135: constexpr ByteCount BYTES = kj::unit(); cannam@135: constexpr WordCount WORDS = kj::unit(); cannam@135: constexpr ElementCount ELEMENTS = kj::unit(); cannam@135: constexpr WirePointerCount POINTERS = kj::unit(); cannam@135: cannam@135: // GCC 4.7 actually gives unused warnings on these constants in opt mode... cannam@135: constexpr auto BITS_PER_BYTE KJ_UNUSED = 8 * BITS / BYTES; cannam@135: constexpr auto BITS_PER_WORD KJ_UNUSED = 64 * BITS / WORDS; cannam@135: constexpr auto BYTES_PER_WORD KJ_UNUSED = 8 * BYTES / WORDS; cannam@135: cannam@135: constexpr auto BITS_PER_POINTER KJ_UNUSED = 64 * BITS / POINTERS; cannam@135: constexpr auto BYTES_PER_POINTER KJ_UNUSED = 8 * BYTES / POINTERS; cannam@135: constexpr auto WORDS_PER_POINTER KJ_UNUSED = 1 * WORDS / POINTERS; cannam@135: cannam@135: constexpr WordCount POINTER_SIZE_IN_WORDS = 1 * POINTERS * WORDS_PER_POINTER; cannam@135: cannam@135: template cannam@135: inline KJ_CONSTEXPR() decltype(BYTES / ELEMENTS) bytesPerElement() { cannam@135: return sizeof(T) * BYTES / ELEMENTS; cannam@135: } cannam@135: cannam@135: template cannam@135: inline KJ_CONSTEXPR() decltype(BITS / ELEMENTS) bitsPerElement() { cannam@135: return sizeof(T) * 8 * BITS / ELEMENTS; cannam@135: } cannam@135: cannam@135: inline constexpr ByteCount intervalLength(const byte* a, const byte* b) { cannam@135: return uint(b - a) * BYTES; cannam@135: } cannam@135: inline constexpr WordCount intervalLength(const word* a, const word* b) { cannam@135: return uint(b - a) * WORDS; cannam@135: } cannam@135: cannam@135: } // namespace capnp cannam@135: cannam@135: #endif // CAPNP_COMMON_H_