comparison osx/include/capnp/orphan.h @ 49:3ab5a40c4e3b

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