generated-header-support.h 11.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// This file is included form all generated headers.

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

29
#include "layout.h"
30
#include "list.h"
31
#include "orphan.h"
32
#include <kj/string.h>
33
#include <kj/string-tree.h>
34

35
namespace capnp {
36

37 38
class MessageBuilder;  // So that it can be declared a friend.

39 40
template <typename T, Kind k = kind<T>()>
struct ToDynamic_;   // Defined in dynamic.h, needs to be declared as everyone's friend.
Kenton Varda's avatar
Kenton Varda committed
41

Kenton Varda's avatar
Kenton Varda committed
42
struct DynamicStruct;  // So that it can be declared a friend.
43

44
namespace _ {  // private
45 46

template <typename T>
47
struct PointerHelpers<T, Kind::STRUCT> {
48
  static inline typename T::Reader get(StructReader reader, WirePointerCount index,
49 50
                                       const word* defaultValue = nullptr) {
    return typename T::Reader(reader.getStructField(index, defaultValue));
51
  }
52
  static inline typename T::Builder get(StructBuilder builder, WirePointerCount index,
53 54 55
                                        const word* defaultValue = nullptr) {
    return typename T::Builder(builder.getStructField(index, structSize<T>(), defaultValue));
  }
56
  static inline void set(StructBuilder builder, WirePointerCount index,
57
                         typename T::Reader value) {
58
    builder.setStructField(index, value._reader);
59
  }
60
  static inline typename T::Builder init(StructBuilder builder, WirePointerCount index) {
61
    return typename T::Builder(builder.initStructField(index, structSize<T>()));
62
  }
63 64 65 66 67 68
  static inline void adopt(StructBuilder builder, WirePointerCount index, Orphan<T>&& value) {
    builder.adopt(index, kj::mv(value.builder));
  }
  static inline Orphan<T> disown(StructBuilder builder, WirePointerCount index) {
    return Orphan<T>(builder.disown(index));
  }
69 70 71
};

template <typename T>
72
struct PointerHelpers<List<T>, Kind::LIST> {
73
  static inline typename List<T>::Reader get(StructReader reader, WirePointerCount index,
74 75
                                             const word* defaultValue = nullptr) {
    return typename List<T>::Reader(List<T>::getAsFieldOf(reader, index, defaultValue));
76
  }
77
  static inline typename List<T>::Builder get(StructBuilder builder, WirePointerCount index,
78 79
                                              const word* defaultValue = nullptr) {
    return typename List<T>::Builder(List<T>::getAsFieldOf(builder, index, defaultValue));
80
  }
81
  static inline void set(StructBuilder builder, WirePointerCount index,
82
                         typename List<T>::Reader value) {
83
    builder.setListField(index, value.reader);
84
  }
85 86 87 88 89 90 91
  template <typename U>
  static void set(StructBuilder builder, WirePointerCount index, std::initializer_list<U> value) {
    auto l = init(builder, index, value.size());
    uint i = 0;
    for (auto& element: value) {
      l.set(i++, element);
    }
92
  }
93
  static inline typename List<T>::Builder init(
94
      StructBuilder builder, WirePointerCount index, uint size) {
95
    return typename List<T>::Builder(List<T>::initAsFieldOf(builder, index, size));
96
  }
97 98 99 100 101 102
  static inline void adopt(StructBuilder builder, WirePointerCount index, Orphan<List<T>>&& value) {
    builder.adopt(index, kj::mv(value.builder));
  }
  static inline Orphan<List<T>> disown(StructBuilder builder, WirePointerCount index) {
    return Orphan<List<T>>(builder.disown(index));
  }
103 104
};

105 106
template <typename T>
struct PointerHelpers<T, Kind::BLOB> {
107
  static inline typename T::Reader get(StructReader reader, WirePointerCount index,
108 109 110
                                       const void* defaultValue = nullptr,
                                       uint defaultBytes = 0) {
    return reader.getBlobField<T>(index, defaultValue, defaultBytes * BYTES);
111
  }
112
  static inline typename T::Builder get(StructBuilder builder, WirePointerCount index,
113 114 115
                                        const void* defaultValue = nullptr,
                                        uint defaultBytes = 0) {
    return builder.getBlobField<T>(index, defaultValue, defaultBytes * BYTES);
116
  }
117
  static inline void set(StructBuilder builder, WirePointerCount index, typename T::Reader value) {
118
    builder.setBlobField<T>(index, value);
119
  }
120
  static inline typename T::Builder init(StructBuilder builder, WirePointerCount index, uint size) {
121
    return builder.initBlobField<T>(index, size * BYTES);
122
  }
123 124 125 126 127 128
  static inline void adopt(StructBuilder builder, WirePointerCount index, Orphan<T>&& value) {
    builder.adopt(index, kj::mv(value.builder));
  }
  static inline Orphan<T> disown(StructBuilder builder, WirePointerCount index) {
    return Orphan<T>(builder.disown(index));
  }
129 130
};

131
struct UncheckedMessage {
132 133 134 135
  typedef const word* Reader;
};

template <>
136 137 138
struct PointerHelpers<UncheckedMessage> {
  // Reads an Object field as an unchecked message pointer.  Requires that the containing message is
  // itself unchecked.  This hack is currently private.  It is used to locate default values within
139 140
  // encoded schemas.

141
  static inline const word* get(StructReader reader, WirePointerCount index) {
142
    return reader.getUncheckedPointer(index);
143 144 145
  }
};

Kenton Varda's avatar
Kenton Varda committed
146
struct RawSchema {
147 148 149 150
  // The generated code defines a constant RawSchema for every compiled declaration.
  //
  // This is an internal structure which could change in the future.

151 152
  uint64_t id;

Kenton Varda's avatar
Kenton Varda committed
153
  const word* encodedNode;
154
  // Encoded SchemaNode, readable via readMessageUnchecked<schema::Node>(encodedNode).
155

Kenton Varda's avatar
Kenton Varda committed
156 157 158
  uint32_t encodedSize;
  // Size of encodedNode, in words.

159
  const RawSchema* const* dependencies;
160 161 162 163
  // Pointers to other types on which this one depends, sorted by ID.  The schemas in this table
  // may be uninitialized -- you must call ensureInitialized() on the one you wish to use before
  // using it.
  //
164 165 166 167 168 169 170 171 172 173 174 175 176 177
  // TODO(someday):  Make this a hashtable.

  struct MemberInfo {
    uint16_t unionIndex;  // 0 = not in a union, >0 = parent union's index + 1
    uint16_t index;       // index of the member
  };

  const MemberInfo* membersByName;
  // Indexes of members sorted by name.  Used to implement name lookup.
  // TODO(someday):  Make this a hashtable.

  uint32_t dependencyCount;
  uint32_t memberCount;
  // Sizes of above tables.
178 179 180 181 182

  const RawSchema* canCastTo;
  // Points to the RawSchema of a compiled-in type to which it is safe to cast any DynamicValue
  // with this schema.  This is null for all compiled-in types; it is only set by SchemaLoader on
  // dynamically-loaded types.
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199

  class Initializer {
  public:
    virtual void init(const RawSchema* schema) const = 0;
  };

  const Initializer* lazyInitializer;
  // Lazy initializer, invoked by ensureInitialized().

  inline void ensureInitialized() const {
    // Lazy initialization support.  Invoke to ensure that initialization has taken place.  This
    // is required in particular when traversing the dependency list.  RawSchemas for compiled-in
    // types are always initialized; only dynamically-loaded schemas may be lazy.

    const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_ACQUIRE);
    if (i != nullptr) i->init(this);
  }
Kenton Varda's avatar
Kenton Varda committed
200 201 202
};

template <typename T>
203
struct RawSchema_;
204 205 206

template <typename T>
inline const RawSchema& rawSchema() {
207
  return RawSchema_<T>::get();
208 209 210
}

template <typename T>
211
struct TypeId_;
Kenton Varda's avatar
Kenton Varda committed
212

Kenton Varda's avatar
Kenton Varda committed
213
template <typename T>
214
struct UnionMemberIndex_;
Kenton Varda's avatar
Kenton Varda committed
215
template <typename T>
216
inline uint unionMemberIndex() { return UnionMemberIndex_<T>::value; }
Kenton Varda's avatar
Kenton Varda committed
217 218

template <typename T>
219
struct UnionParentType_;
Kenton Varda's avatar
Kenton Varda committed
220
template <typename T>
221
using UnionParentType = typename UnionParentType_<T>::Type;
Kenton Varda's avatar
Kenton Varda committed
222

223 224
kj::StringTree structString(StructReader reader, const RawSchema& schema);
kj::StringTree unionString(StructReader reader, const RawSchema& schema, uint memberIndex);
Kenton Varda's avatar
Kenton Varda committed
225
// Declared here so that we can declare inline stringify methods on generated types.
226 227 228
// Defined in stringify.c++, which depends on dynamic.c++, which is allowed not to be linked in.

template <typename T>
229
inline kj::StringTree structString(StructReader reader) {
Kenton Varda's avatar
Kenton Varda committed
230 231 232 233
  return structString(reader, rawSchema<T>());
}

template <typename T>
234
inline kj::StringTree unionString(StructReader reader) {
Kenton Varda's avatar
Kenton Varda committed
235
  return unionString(reader, rawSchema<UnionParentType<T>>(), unionMemberIndex<T>());
236 237
}

238
}  // namespace _ (private)
239 240

template <typename T>
241
inline constexpr uint64_t typeId() { return _::TypeId_<T>::typeId; }
242 243 244
// typeId<MyType>() returns the type ID as defined in the schema.  Works with structs, enums, and
// interfaces.

245
}  // namespace capnp
246

Kenton Varda's avatar
Kenton Varda committed
247
#define CAPNP_DECLARE_ENUM(type, id) \
248 249 250 251
    template <> struct Kind_<type> { static constexpr Kind kind = Kind::ENUM; }; \
    template <> struct TypeId_<type> { static constexpr uint64_t typeId = 0x##id; }; \
    template <> struct RawSchema_<type> { \
      static inline const RawSchema& get() { return schemas::s_##id; } \
252
    }
Kenton Varda's avatar
Kenton Varda committed
253
#define CAPNP_DEFINE_ENUM(type) \
254 255
    constexpr Kind Kind_<type>::kind; \
    constexpr uint64_t TypeId_<type>::typeId;
Kenton Varda's avatar
Kenton Varda committed
256

Kenton Varda's avatar
Kenton Varda committed
257
#define CAPNP_DECLARE_STRUCT(type, id, dataWordSize, pointerCount, preferredElementEncoding) \
258 259
    template <> struct Kind_<type> { static constexpr Kind kind = Kind::STRUCT; }; \
    template <> struct StructSize_<type> { \
260
      static constexpr StructSize value = StructSize( \
261
          dataWordSize * WORDS, pointerCount * POINTERS, FieldSize::preferredElementEncoding); \
262
    }; \
263 264 265
    template <> struct TypeId_<type> { static constexpr uint64_t typeId = 0x##id; }; \
    template <> struct RawSchema_<type> { \
      static inline const RawSchema& get() { return schemas::s_##id; } \
266
    }
Kenton Varda's avatar
Kenton Varda committed
267
#define CAPNP_DEFINE_STRUCT(type) \
268 269 270
    constexpr Kind Kind_<type>::kind; \
    constexpr StructSize StructSize_<type>::value; \
    constexpr uint64_t TypeId_<type>::typeId;
Kenton Varda's avatar
Kenton Varda committed
271

Kenton Varda's avatar
Kenton Varda committed
272
#define CAPNP_DECLARE_UNION(type, parentType, memberIndex) \
273 274 275
    template <> struct Kind_<type> { static constexpr Kind kind = Kind::UNION; }; \
    template <> struct UnionMemberIndex_<type> { static constexpr uint value = memberIndex; }; \
    template <> struct UnionParentType_<type> { typedef parentType Type; }
Kenton Varda's avatar
Kenton Varda committed
276
#define CAPNP_DEFINE_UNION(type) \
277 278
    constexpr Kind Kind_<type>::kind; \
    constexpr uint UnionMemberIndex_<type>::value;
Kenton Varda's avatar
Kenton Varda committed
279

Kenton Varda's avatar
Kenton Varda committed
280
#define CAPNP_DECLARE_INTERFACE(type, id) \
281 282 283 284
    template <> struct Kind_<type> { static constexpr Kind kind = Kind::INTERFACE; }; \
    template <> struct TypeId_<type> { static constexpr uint64_t typeId = 0x##id; }; \
    template <> struct RawSchema_<type> { \
      static inline const RawSchema& get() { return schemas::s_##id; } \
285
    }
Kenton Varda's avatar
Kenton Varda committed
286
#define CAPNP_DEFINE_INTERFACE(type) \
287 288
    constexpr Kind Kind_<type>::kind; \
    constexpr uint64_t TypeId_<type>::typeId;
289

Kenton Varda's avatar
Kenton Varda committed
290
#endif  // CAPNP_GENERATED_HEADER_SUPPORT_H_