1// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
2// Licensed under the MIT License:
3//
4// Permission is hereby granted, free of charge, to any person obtaining a copy
5// of this software and associated documentation files (the "Software"), to deal
6// in the Software without restriction, including without limitation the rights
7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8// copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20// THE SOFTWARE.
21
22#pragma once
23
24#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
25#pragma GCC system_header
26#endif
27
28#include "layout.h"
29
30namespace capnp {
31
32class StructSchema;
33class ListSchema;
34struct DynamicStruct;
35struct DynamicList;
36namespace _ { struct OrphanageInternal; }
37
38template <typename T>
39class Orphan {
40 // Represents an object which is allocated within some message builder but has no pointers
41 // pointing at it. An Orphan can later be "adopted" by some other object as one of that object's
42 // fields, without having to copy the orphan. For a field `foo` of pointer type, the generated
43 // code will define builder methods `void adoptFoo(Orphan<T>)` and `Orphan<T> disownFoo()`.
44 // Orphans can also be created independently of any parent using an Orphanage.
45 //
46 // `Orphan<T>` can be moved but not copied, like `Own<T>`, so that it is impossible for one
47 // orphan to be adopted multiple times. If an orphan is destroyed without being adopted, its
48 // contents are zero'd out (and possibly reused, if we ever implement the ability to reuse space
49 // in a message arena).
50
51public:
52 Orphan() = default;
53 KJ_DISALLOW_COPY(Orphan);
54 Orphan(Orphan&&) = default;
55 Orphan& operator=(Orphan&&) = default;
56 inline Orphan(_::OrphanBuilder&& builder): builder(kj::mv(builder)) {}
57
58 inline BuilderFor<T> get();
59 // Get the underlying builder. If the orphan is null, this will allocate and return a default
60 // object rather than crash. This is done for security -- otherwise, you might enable a DoS
61 // attack any time you disown a field and fail to check if it is null. In the case of structs,
62 // this means that the orphan is no longer null after get() returns. In the case of lists,
63 // no actual object is allocated since a simple empty ListBuilder can be returned.
64
65 inline ReaderFor<T> getReader() const;
66
67 inline bool operator==(decltype(nullptr)) const { return builder == nullptr; }
68 inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; }
69
70 inline void truncate(uint size);
71 // Resize an object (which must be a list or a blob) to the given size.
72 //
73 // If the new size is less than the original, the remaining elements will be discarded. The
74 // list is never moved in this case. If the list happens to be located at the end of its segment
75 // (which is always true if the list was the last thing allocated), the removed memory will be
76 // reclaimed (reducing the messag size), otherwise it is simply zeroed. The reclaiming behavior
77 // is particularly useful for allocating buffer space when you aren't sure how much space you
78 // actually need: you can pre-allocate, say, a 4k byte array, read() from a file into it, and
79 // then truncate it back to the amount of space actually used.
80 //
81 // If the new size is greater than the original, the list is extended with default values. If
82 // the list is the last object in its segment *and* there is enough space left in the segment to
83 // extend it to cover the new values, then the list is extended in-place. Otherwise, it must be
84 // moved to a new location, leaving a zero'd hole in the previous space that won't be filled.
85 // This copy is shallow; sub-objects will simply be reparented, not copied.
86 //
87 // Any existing readers or builders pointing at the object are invalidated by this call (even if
88 // it doesn't move). You must call `get()` or `getReader()` again to get the new, valid pointer.
89
90private:
91 _::OrphanBuilder builder;
92
93 template <typename, Kind>
94 friend struct _::PointerHelpers;
95 template <typename, Kind>
96 friend struct List;
97 template <typename U>
98 friend class Orphan;
99 friend class Orphanage;
100 friend class MessageBuilder;
101};
102
103class Orphanage: private kj::DisallowConstCopy {
104 // Use to directly allocate Orphan objects, without having a parent object allocate and then
105 // disown the object.
106
107public:
108 inline Orphanage(): arena(nullptr) {}
109
110 template <typename BuilderType>
111 static Orphanage getForMessageContaining(BuilderType builder);
112 // Construct an Orphanage that allocates within the message containing the given Builder. This
113 // allows the constructed Orphans to be adopted by objects within said message.
114 //
115 // This constructor takes the builder rather than having the builder have a getOrphanage() method
116 // because this is an advanced feature and we don't want to pollute the builder APIs with it.
117 //
118 // Note that if you have a direct pointer to the `MessageBuilder`, you can simply call its
119 // `getOrphanage()` method.
120
121 template <typename RootType>
122 Orphan<RootType> newOrphan() const;
123 // Allocate a new orphaned struct.
124
125 template <typename RootType>
126 Orphan<RootType> newOrphan(uint size) const;
127 // Allocate a new orphaned list or blob.
128
129 Orphan<DynamicStruct> newOrphan(StructSchema schema) const;
130 // Dynamically create an orphan struct with the given schema. You must
131 // #include <capnp/dynamic.h> to use this.
132
133 Orphan<DynamicList> newOrphan(ListSchema schema, uint size) const;
134 // Dynamically create an orphan list with the given schema. You must #include <capnp/dynamic.h>
135 // to use this.
136
137 template <typename Reader>
138 Orphan<FromReader<Reader>> newOrphanCopy(Reader copyFrom) const;
139 // Allocate a new orphaned object (struct, list, or blob) and initialize it as a copy of the
140 // given object.
141
142 template <typename T>
143 Orphan<List<ListElementType<FromReader<T>>>> newOrphanConcat(kj::ArrayPtr<T> lists) const;
144 template <typename T>
145 Orphan<List<ListElementType<FromReader<T>>>> newOrphanConcat(kj::ArrayPtr<const T> lists) const;
146 // Given an array of List readers, copy and concatenate the lists, creating a new Orphan.
147 //
148 // Note that compared to allocating the list yourself and using `setWithCaveats()` to set each
149 // item, this method avoids the "caveats": the new list will be allocated with the element size
150 // being the maximum of that from all the input lists. This is particularly important when
151 // concatenating struct lists: if the lists were created using a newer version of the protocol
152 // in which some new fields had been added to the struct, using `setWithCaveats()` would
153 // truncate off those new fields.
154
155 Orphan<Data> referenceExternalData(Data::Reader data) const;
156 // Creates an Orphan<Data> that points at an existing region of memory (e.g. from another message)
157 // without copying it. There are some SEVERE restrictions on how this can be used:
158 // - The memory must remain valid until the `MessageBuilder` is destroyed (even if the orphan is
159 // abandoned).
160 // - Because the data is const, you will not be allowed to obtain a `Data::Builder`
161 // for this blob. Any call which would return such a builder will throw an exception. You
162 // can, however, obtain a Reader, e.g. via orphan.getReader() or from a parent Reader (once
163 // the orphan is adopted). It is your responsibility to make sure your code can deal with
164 // these problems when using this optimization; if you can't, allocate a copy instead.
165 // - `data.begin()` must be aligned to a machine word boundary (32-bit or 64-bit depending on
166 // the CPU). Any pointer returned by malloc() as well as any data blob obtained from another
167 // Cap'n Proto message satisfies this.
168 // - If `data.size()` is not a multiple of 8, extra bytes past data.end() up until the next 8-byte
169 // boundary will be visible in the raw message when it is written out. Thus, there must be no
170 // secrets in these bytes. Data blobs obtained from other Cap'n Proto messages should be safe
171 // as these bytes should be zero (unless the sender had the same problem).
172 //
173 // The array will actually become one of the message's segments. The data can thus be adopted
174 // into the message tree without copying it. This is particularly useful when referencing very
175 // large blobs, such as whole mmap'd files.
176
177private:
178 _::BuilderArena* arena;
179 _::CapTableBuilder* capTable;
180
181 inline explicit Orphanage(_::BuilderArena* arena, _::CapTableBuilder* capTable)
182 : arena(arena), capTable(capTable) {}
183
184 template <typename T, Kind = CAPNP_KIND(T)>
185 struct GetInnerBuilder;
186 template <typename T, Kind = CAPNP_KIND(T)>
187 struct GetInnerReader;
188 template <typename T>
189 struct NewOrphanListImpl;
190
191 friend class MessageBuilder;
192 friend struct _::OrphanageInternal;
193};
194
195// =======================================================================================
196// Inline implementation details.
197
198namespace _ { // private
199
200template <typename T, Kind = CAPNP_KIND(T)>
201struct OrphanGetImpl;
202
203template <typename T>
204struct OrphanGetImpl<T, Kind::PRIMITIVE> {
205 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
206 builder.truncate(size, _::elementSizeForType<T>());
207 }
208};
209
210template <typename T>
211struct OrphanGetImpl<T, Kind::STRUCT> {
212 static inline typename T::Builder apply(_::OrphanBuilder& builder) {
213 return typename T::Builder(builder.asStruct(_::structSize<T>()));
214 }
215 static inline typename T::Reader applyReader(const _::OrphanBuilder& builder) {
216 return typename T::Reader(builder.asStructReader(_::structSize<T>()));
217 }
218 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
219 builder.truncate(size, _::structSize<T>());
220 }
221};
222
223#if !CAPNP_LITE
224template <typename T>
225struct OrphanGetImpl<T, Kind::INTERFACE> {
226 static inline typename T::Client apply(_::OrphanBuilder& builder) {
227 return typename T::Client(builder.asCapability());
228 }
229 static inline typename T::Client applyReader(const _::OrphanBuilder& builder) {
230 return typename T::Client(builder.asCapability());
231 }
232 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
233 builder.truncate(size, ElementSize::POINTER);
234 }
235};
236#endif // !CAPNP_LITE
237
238template <typename T, Kind k>
239struct OrphanGetImpl<List<T, k>, Kind::LIST> {
240 static inline typename List<T>::Builder apply(_::OrphanBuilder& builder) {
241 return typename List<T>::Builder(builder.asList(_::ElementSizeForType<T>::value));
242 }
243 static inline typename List<T>::Reader applyReader(const _::OrphanBuilder& builder) {
244 return typename List<T>::Reader(builder.asListReader(_::ElementSizeForType<T>::value));
245 }
246 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
247 builder.truncate(size, ElementSize::POINTER);
248 }
249};
250
251template <typename T>
252struct OrphanGetImpl<List<T, Kind::STRUCT>, Kind::LIST> {
253 static inline typename List<T>::Builder apply(_::OrphanBuilder& builder) {
254 return typename List<T>::Builder(builder.asStructList(_::structSize<T>()));
255 }
256 static inline typename List<T>::Reader applyReader(const _::OrphanBuilder& builder) {
257 return typename List<T>::Reader(builder.asListReader(_::ElementSizeForType<T>::value));
258 }
259 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
260 builder.truncate(size, ElementSize::POINTER);
261 }
262};
263
264template <>
265struct OrphanGetImpl<Text, Kind::BLOB> {
266 static inline Text::Builder apply(_::OrphanBuilder& builder) {
267 return Text::Builder(builder.asText());
268 }
269 static inline Text::Reader applyReader(const _::OrphanBuilder& builder) {
270 return Text::Reader(builder.asTextReader());
271 }
272 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
273 builder.truncate(size, ElementSize::POINTER);
274 }
275};
276
277template <>
278struct OrphanGetImpl<Data, Kind::BLOB> {
279 static inline Data::Builder apply(_::OrphanBuilder& builder) {
280 return Data::Builder(builder.asData());
281 }
282 static inline Data::Reader applyReader(const _::OrphanBuilder& builder) {
283 return Data::Reader(builder.asDataReader());
284 }
285 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
286 builder.truncate(size, ElementSize::POINTER);
287 }
288};
289
290struct OrphanageInternal {
291 static inline _::BuilderArena* getArena(Orphanage orphanage) { return orphanage.arena; }
292 static inline _::CapTableBuilder* getCapTable(Orphanage orphanage) { return orphanage.capTable; }
293};
294
295} // namespace _ (private)
296
297template <typename T>
298inline BuilderFor<T> Orphan<T>::get() {
299 return _::OrphanGetImpl<T>::apply(builder);
300}
301
302template <typename T>
303inline ReaderFor<T> Orphan<T>::getReader() const {
304 return _::OrphanGetImpl<T>::applyReader(builder);
305}
306
307template <typename T>
308inline void Orphan<T>::truncate(uint size) {
309 _::OrphanGetImpl<ListElementType<T>>::truncateListOf(builder, bounded(size) * ELEMENTS);
310}
311
312template <>
313inline void Orphan<Text>::truncate(uint size) {
314 builder.truncateText(bounded(size) * ELEMENTS);
315}
316
317template <>
318inline void Orphan<Data>::truncate(uint size) {
319 builder.truncate(bounded(size) * ELEMENTS, ElementSize::BYTE);
320}
321
322template <typename T>
323struct Orphanage::GetInnerBuilder<T, Kind::STRUCT> {
324 static inline _::StructBuilder apply(typename T::Builder& t) {
325 return t._builder;
326 }
327};
328
329template <typename T>
330struct Orphanage::GetInnerBuilder<T, Kind::LIST> {
331 static inline _::ListBuilder apply(typename T::Builder& t) {
332 return t.builder;
333 }
334};
335
336template <typename BuilderType>
337Orphanage Orphanage::getForMessageContaining(BuilderType builder) {
338 auto inner = GetInnerBuilder<FromBuilder<BuilderType>>::apply(builder);
339 return Orphanage(inner.getArena(), inner.getCapTable());
340}
341
342template <typename RootType>
343Orphan<RootType> Orphanage::newOrphan() const {
344 return Orphan<RootType>(_::OrphanBuilder::initStruct(arena, capTable, _::structSize<RootType>()));
345}
346
347template <typename T, Kind k>
348struct Orphanage::NewOrphanListImpl<List<T, k>> {
349 static inline _::OrphanBuilder apply(
350 _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) {
351 return _::OrphanBuilder::initList(
352 arena, capTable, bounded(size) * ELEMENTS, _::ElementSizeForType<T>::value);
353 }
354};
355
356template <typename T>
357struct Orphanage::NewOrphanListImpl<List<T, Kind::STRUCT>> {
358 static inline _::OrphanBuilder apply(
359 _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) {
360 return _::OrphanBuilder::initStructList(
361 arena, capTable, bounded(size) * ELEMENTS, _::structSize<T>());
362 }
363};
364
365template <>
366struct Orphanage::NewOrphanListImpl<Text> {
367 static inline _::OrphanBuilder apply(
368 _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) {
369 return _::OrphanBuilder::initText(arena, capTable, bounded(size) * BYTES);
370 }
371};
372
373template <>
374struct Orphanage::NewOrphanListImpl<Data> {
375 static inline _::OrphanBuilder apply(
376 _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) {
377 return _::OrphanBuilder::initData(arena, capTable, bounded(size) * BYTES);
378 }
379};
380
381template <typename RootType>
382Orphan<RootType> Orphanage::newOrphan(uint size) const {
383 return Orphan<RootType>(NewOrphanListImpl<RootType>::apply(arena, capTable, size));
384}
385
386template <typename T>
387struct Orphanage::GetInnerReader<T, Kind::STRUCT> {
388 static inline _::StructReader apply(const typename T::Reader& t) {
389 return t._reader;
390 }
391};
392
393template <typename T>
394struct Orphanage::GetInnerReader<T, Kind::LIST> {
395 static inline _::ListReader apply(const typename T::Reader& t) {
396 return t.reader;
397 }
398};
399
400template <typename T>
401struct Orphanage::GetInnerReader<T, Kind::BLOB> {
402 static inline const typename T::Reader& apply(const typename T::Reader& t) {
403 return t;
404 }
405};
406
407template <typename Reader>
408inline Orphan<FromReader<Reader>> Orphanage::newOrphanCopy(Reader copyFrom) const {
409 return Orphan<FromReader<Reader>>(_::OrphanBuilder::copy(
410 arena, capTable, GetInnerReader<FromReader<Reader>>::apply(copyFrom)));
411}
412
413template <typename T>
414inline Orphan<List<ListElementType<FromReader<T>>>>
415Orphanage::newOrphanConcat(kj::ArrayPtr<T> lists) const {
416 return newOrphanConcat(kj::implicitCast<kj::ArrayPtr<const T>>(lists));
417}
418template <typename T>
419inline Orphan<List<ListElementType<FromReader<T>>>>
420Orphanage::newOrphanConcat(kj::ArrayPtr<const T> lists) const {
421 // Optimization / simplification: Rely on List<T>::Reader containing nothing except a
422 // _::ListReader.
423 static_assert(sizeof(T) == sizeof(_::ListReader), "lists are not bare readers?");
424 kj::ArrayPtr<const _::ListReader> raw(
425 reinterpret_cast<const _::ListReader*>(lists.begin()), lists.size());
426 typedef ListElementType<FromReader<T>> Element;
427 return Orphan<List<Element>>(
428 _::OrphanBuilder::concat(arena, capTable,
429 _::elementSizeForType<Element>(),
430 _::minStructSizeForElement<Element>(), raw));
431}
432
433inline Orphan<Data> Orphanage::referenceExternalData(Data::Reader data) const {
434 return Orphan<Data>(_::OrphanBuilder::referenceExternalData(arena, data));
435}
436
437} // namespace capnp
438