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#include "orphan.h"
30#include <initializer_list>
31#ifdef KJ_STD_COMPAT
32#include <iterator>
33#endif // KJ_STD_COMPAT
34
35namespace capnp {
36namespace _ { // private
37
38template <typename T>
39class TemporaryPointer {
40 // This class is a little hack which lets us define operator->() in cases where it needs to
41 // return a pointer to a temporary value. We instead construct a TemporaryPointer and return that
42 // (by value). The compiler then invokes operator->() on the TemporaryPointer, which itself is
43 // able to return a real pointer to its member.
44
45public:
46 TemporaryPointer(T&& value): value(kj::mv(value)) {}
47 TemporaryPointer(const T& value): value(value) {}
48
49 inline T* operator->() { return &value; }
50private:
51 T value;
52};
53
54template <typename Container, typename Element>
55class IndexingIterator {
56public:
57 IndexingIterator() = default;
58
59 inline Element operator*() const { return (*container)[index]; }
60 inline TemporaryPointer<Element> operator->() const {
61 return TemporaryPointer<Element>((*container)[index]);
62 }
63 inline Element operator[]( int off) const { return (*container)[index]; }
64 inline Element operator[](uint off) const { return (*container)[index]; }
65
66 inline IndexingIterator& operator++() { ++index; return *this; }
67 inline IndexingIterator operator++(int) { IndexingIterator other = *this; ++index; return other; }
68 inline IndexingIterator& operator--() { --index; return *this; }
69 inline IndexingIterator operator--(int) { IndexingIterator other = *this; --index; return other; }
70
71 inline IndexingIterator operator+(uint amount) const { return IndexingIterator(container, index + amount); }
72 inline IndexingIterator operator-(uint amount) const { return IndexingIterator(container, index - amount); }
73 inline IndexingIterator operator+( int amount) const { return IndexingIterator(container, index + amount); }
74 inline IndexingIterator operator-( int amount) const { return IndexingIterator(container, index - amount); }
75
76 inline int operator-(const IndexingIterator& other) const { return index - other.index; }
77
78 inline IndexingIterator& operator+=(uint amount) { index += amount; return *this; }
79 inline IndexingIterator& operator-=(uint amount) { index -= amount; return *this; }
80 inline IndexingIterator& operator+=( int amount) { index += amount; return *this; }
81 inline IndexingIterator& operator-=( int amount) { index -= amount; return *this; }
82
83 // STL says comparing iterators of different containers is not allowed, so we only compare
84 // indices here.
85 inline bool operator==(const IndexingIterator& other) const { return index == other.index; }
86 inline bool operator!=(const IndexingIterator& other) const { return index != other.index; }
87 inline bool operator<=(const IndexingIterator& other) const { return index <= other.index; }
88 inline bool operator>=(const IndexingIterator& other) const { return index >= other.index; }
89 inline bool operator< (const IndexingIterator& other) const { return index < other.index; }
90 inline bool operator> (const IndexingIterator& other) const { return index > other.index; }
91
92private:
93 Container* container;
94 uint index;
95
96 friend Container;
97 inline IndexingIterator(Container* container, uint index)
98 : container(container), index(index) {}
99};
100
101} // namespace _ (private)
102
103template <typename T>
104struct List<T, Kind::PRIMITIVE> {
105 // List of primitives.
106
107 List() = delete;
108
109 class Reader {
110 public:
111 typedef List<T> Reads;
112
113 inline Reader(): reader(_::elementSizeForType<T>()) {}
114 inline explicit Reader(_::ListReader reader): reader(reader) {}
115
116 inline uint size() const { return unbound(reader.size() / ELEMENTS); }
117 inline T operator[](uint index) const {
118 KJ_IREQUIRE(index < size());
119 return reader.template getDataElement<T>(bounded(index) * ELEMENTS);
120 }
121
122 typedef _::IndexingIterator<const Reader, T> Iterator;
123 inline Iterator begin() const { return Iterator(this, 0); }
124 inline Iterator end() const { return Iterator(this, size()); }
125
126 inline MessageSize totalSize() const {
127 return reader.totalSize().asPublic();
128 }
129
130 private:
131 _::ListReader reader;
132 template <typename U, Kind K>
133 friend struct _::PointerHelpers;
134 template <typename U, Kind K>
135 friend struct List;
136 friend class Orphanage;
137 template <typename U, Kind K>
138 friend struct ToDynamic_;
139 };
140
141 class Builder {
142 public:
143 typedef List<T> Builds;
144
145 inline Builder(): builder(_::elementSizeForType<T>()) {}
146 inline Builder(decltype(nullptr)): Builder() {}
147 inline explicit Builder(_::ListBuilder builder): builder(builder) {}
148
149 inline operator Reader() const { return Reader(builder.asReader()); }
150 inline Reader asReader() const { return Reader(builder.asReader()); }
151
152 inline uint size() const { return unbound(builder.size() / ELEMENTS); }
153 inline T operator[](uint index) {
154 KJ_IREQUIRE(index < size());
155 return builder.template getDataElement<T>(bounded(index) * ELEMENTS);
156 }
157 inline void set(uint index, T value) {
158 // Alas, it is not possible to make operator[] return a reference to which you can assign,
159 // since the encoded representation does not necessarily match the compiler's representation
160 // of the type. We can't even return a clever class that implements operator T() and
161 // operator=() because it will lead to surprising behavior when using type inference (e.g.
162 // calling a template function with inferred argument types, or using "auto" or "decltype").
163
164 builder.template setDataElement<T>(bounded(index) * ELEMENTS, value);
165 }
166
167 typedef _::IndexingIterator<Builder, T> Iterator;
168 inline Iterator begin() { return Iterator(this, 0); }
169 inline Iterator end() { return Iterator(this, size()); }
170
171 private:
172 _::ListBuilder builder;
173 template <typename U, Kind K>
174 friend struct _::PointerHelpers;
175 friend class Orphanage;
176 template <typename U, Kind K>
177 friend struct ToDynamic_;
178 };
179
180 class Pipeline {};
181
182private:
183 inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
184 return builder.initList(_::elementSizeForType<T>(), bounded(size) * ELEMENTS);
185 }
186 inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
187 return builder.getList(_::elementSizeForType<T>(), defaultValue);
188 }
189 inline static _::ListReader getFromPointer(
190 const _::PointerReader& reader, const word* defaultValue) {
191 return reader.getList(_::elementSizeForType<T>(), defaultValue);
192 }
193
194 template <typename U, Kind k>
195 friend struct List;
196 template <typename U, Kind K>
197 friend struct _::PointerHelpers;
198};
199
200template <typename T>
201struct List<T, Kind::ENUM>: public List<T, Kind::PRIMITIVE> {};
202
203template <typename T>
204struct List<T, Kind::STRUCT> {
205 // List of structs.
206
207 List() = delete;
208
209 class Reader {
210 public:
211 typedef List<T> Reads;
212
213 inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {}
214 inline explicit Reader(_::ListReader reader): reader(reader) {}
215
216 inline uint size() const { return unbound(reader.size() / ELEMENTS); }
217 inline typename T::Reader operator[](uint index) const {
218 KJ_IREQUIRE(index < size());
219 return typename T::Reader(reader.getStructElement(bounded(index) * ELEMENTS));
220 }
221
222 typedef _::IndexingIterator<const Reader, typename T::Reader> Iterator;
223 inline Iterator begin() const { return Iterator(this, 0); }
224 inline Iterator end() const { return Iterator(this, size()); }
225
226 inline MessageSize totalSize() const {
227 return reader.totalSize().asPublic();
228 }
229
230 private:
231 _::ListReader reader;
232 template <typename U, Kind K>
233 friend struct _::PointerHelpers;
234 template <typename U, Kind K>
235 friend struct List;
236 friend class Orphanage;
237 template <typename U, Kind K>
238 friend struct ToDynamic_;
239 };
240
241 class Builder {
242 public:
243 typedef List<T> Builds;
244
245 inline Builder(): builder(ElementSize::INLINE_COMPOSITE) {}
246 inline Builder(decltype(nullptr)): Builder() {}
247 inline explicit Builder(_::ListBuilder builder): builder(builder) {}
248
249 inline operator Reader() const { return Reader(builder.asReader()); }
250 inline Reader asReader() const { return Reader(builder.asReader()); }
251
252 inline uint size() const { return unbound(builder.size() / ELEMENTS); }
253 inline typename T::Builder operator[](uint index) {
254 KJ_IREQUIRE(index < size());
255 return typename T::Builder(builder.getStructElement(bounded(index) * ELEMENTS));
256 }
257
258 inline void adoptWithCaveats(uint index, Orphan<T>&& orphan) {
259 // Mostly behaves like you'd expect `adopt` to behave, but with two caveats originating from
260 // the fact that structs in a struct list are allocated inline rather than by pointer:
261 // * This actually performs a shallow copy, effectively adopting each of the orphan's
262 // children rather than adopting the orphan itself. The orphan ends up being discarded,
263 // possibly wasting space in the message object.
264 // * If the orphan is larger than the target struct -- say, because the orphan was built
265 // using a newer version of the schema that has additional fields -- it will be truncated,
266 // losing data.
267
268 KJ_IREQUIRE(index < size());
269
270 // We pass a zero-valued StructSize to asStruct() because we do not want the struct to be
271 // expanded under any circumstances. We're just going to throw it away anyway, and
272 // transferContentFrom() already carefully compares the struct sizes before transferring.
273 builder.getStructElement(bounded(index) * ELEMENTS).transferContentFrom(
274 orphan.builder.asStruct(_::StructSize(ZERO * WORDS, ZERO * POINTERS)));
275 }
276 inline void setWithCaveats(uint index, const typename T::Reader& reader) {
277 // Mostly behaves like you'd expect `set` to behave, but with a caveat originating from
278 // the fact that structs in a struct list are allocated inline rather than by pointer:
279 // If the source struct is larger than the target struct -- say, because the source was built
280 // using a newer version of the schema that has additional fields -- it will be truncated,
281 // losing data.
282 //
283 // Note: If you are trying to concatenate some lists, use Orphanage::newOrphanConcat() to
284 // do it without losing any data in case the source lists come from a newer version of the
285 // protocol. (Plus, it's easier to use anyhow.)
286
287 KJ_IREQUIRE(index < size());
288 builder.getStructElement(bounded(index) * ELEMENTS).copyContentFrom(reader._reader);
289 }
290
291 // There are no init(), set(), adopt(), or disown() methods for lists of structs because the
292 // elements of the list are inlined and are initialized when the list is initialized. This
293 // means that init() would be redundant, and set() would risk data loss if the input struct
294 // were from a newer version of the protocol.
295
296 typedef _::IndexingIterator<Builder, typename T::Builder> Iterator;
297 inline Iterator begin() { return Iterator(this, 0); }
298 inline Iterator end() { return Iterator(this, size()); }
299
300 private:
301 _::ListBuilder builder;
302 template <typename U, Kind K>
303 friend struct _::PointerHelpers;
304 friend class Orphanage;
305 template <typename U, Kind K>
306 friend struct ToDynamic_;
307 };
308
309 class Pipeline {};
310
311private:
312 inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
313 return builder.initStructList(bounded(size) * ELEMENTS, _::structSize<T>());
314 }
315 inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
316 return builder.getStructList(_::structSize<T>(), defaultValue);
317 }
318 inline static _::ListReader getFromPointer(
319 const _::PointerReader& reader, const word* defaultValue) {
320 return reader.getList(ElementSize::INLINE_COMPOSITE, defaultValue);
321 }
322
323 template <typename U, Kind k>
324 friend struct List;
325 template <typename U, Kind K>
326 friend struct _::PointerHelpers;
327};
328
329template <typename T>
330struct List<List<T>, Kind::LIST> {
331 // List of lists.
332
333 List() = delete;
334
335 class Reader {
336 public:
337 typedef List<List<T>> Reads;
338
339 inline Reader(): reader(ElementSize::POINTER) {}
340 inline explicit Reader(_::ListReader reader): reader(reader) {}
341
342 inline uint size() const { return unbound(reader.size() / ELEMENTS); }
343 inline typename List<T>::Reader operator[](uint index) const {
344 KJ_IREQUIRE(index < size());
345 return typename List<T>::Reader(_::PointerHelpers<List<T>>::get(
346 reader.getPointerElement(bounded(index) * ELEMENTS)));
347 }
348
349 typedef _::IndexingIterator<const Reader, typename List<T>::Reader> Iterator;
350 inline Iterator begin() const { return Iterator(this, 0); }
351 inline Iterator end() const { return Iterator(this, size()); }
352
353 inline MessageSize totalSize() const {
354 return reader.totalSize().asPublic();
355 }
356
357 private:
358 _::ListReader reader;
359 template <typename U, Kind K>
360 friend struct _::PointerHelpers;
361 template <typename U, Kind K>
362 friend struct List;
363 friend class Orphanage;
364 template <typename U, Kind K>
365 friend struct ToDynamic_;
366 };
367
368 class Builder {
369 public:
370 typedef List<List<T>> Builds;
371
372 inline Builder(): builder(ElementSize::POINTER) {}
373 inline Builder(decltype(nullptr)): Builder() {}
374 inline explicit Builder(_::ListBuilder builder): builder(builder) {}
375
376 inline operator Reader() const { return Reader(builder.asReader()); }
377 inline Reader asReader() const { return Reader(builder.asReader()); }
378
379 inline uint size() const { return unbound(builder.size() / ELEMENTS); }
380 inline typename List<T>::Builder operator[](uint index) {
381 KJ_IREQUIRE(index < size());
382 return typename List<T>::Builder(_::PointerHelpers<List<T>>::get(
383 builder.getPointerElement(bounded(index) * ELEMENTS)));
384 }
385 inline typename List<T>::Builder init(uint index, uint size) {
386 KJ_IREQUIRE(index < this->size());
387 return typename List<T>::Builder(_::PointerHelpers<List<T>>::init(
388 builder.getPointerElement(bounded(index) * ELEMENTS), size));
389 }
390 inline void set(uint index, typename List<T>::Reader value) {
391 KJ_IREQUIRE(index < size());
392 builder.getPointerElement(bounded(index) * ELEMENTS).setList(value.reader);
393 }
394 void set(uint index, std::initializer_list<ReaderFor<T>> value) {
395 KJ_IREQUIRE(index < size());
396 auto l = init(index, value.size());
397 uint i = 0;
398 for (auto& element: value) {
399 l.set(i++, element);
400 }
401 }
402 inline void adopt(uint index, Orphan<T>&& value) {
403 KJ_IREQUIRE(index < size());
404 builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder));
405 }
406 inline Orphan<T> disown(uint index) {
407 KJ_IREQUIRE(index < size());
408 return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown());
409 }
410
411 typedef _::IndexingIterator<Builder, typename List<T>::Builder> Iterator;
412 inline Iterator begin() { return Iterator(this, 0); }
413 inline Iterator end() { return Iterator(this, size()); }
414
415 private:
416 _::ListBuilder builder;
417 template <typename U, Kind K>
418 friend struct _::PointerHelpers;
419 friend class Orphanage;
420 template <typename U, Kind K>
421 friend struct ToDynamic_;
422 };
423
424 class Pipeline {};
425
426private:
427 inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
428 return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS);
429 }
430 inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
431 return builder.getList(ElementSize::POINTER, defaultValue);
432 }
433 inline static _::ListReader getFromPointer(
434 const _::PointerReader& reader, const word* defaultValue) {
435 return reader.getList(ElementSize::POINTER, defaultValue);
436 }
437
438 template <typename U, Kind k>
439 friend struct List;
440 template <typename U, Kind K>
441 friend struct _::PointerHelpers;
442};
443
444template <typename T>
445struct List<T, Kind::BLOB> {
446 List() = delete;
447
448 class Reader {
449 public:
450 typedef List<T> Reads;
451
452 inline Reader(): reader(ElementSize::POINTER) {}
453 inline explicit Reader(_::ListReader reader): reader(reader) {}
454
455 inline uint size() const { return unbound(reader.size() / ELEMENTS); }
456 inline typename T::Reader operator[](uint index) const {
457 KJ_IREQUIRE(index < size());
458 return reader.getPointerElement(bounded(index) * ELEMENTS)
459 .template getBlob<T>(nullptr, ZERO * BYTES);
460 }
461
462 typedef _::IndexingIterator<const Reader, typename T::Reader> Iterator;
463 inline Iterator begin() const { return Iterator(this, 0); }
464 inline Iterator end() const { return Iterator(this, size()); }
465
466 inline MessageSize totalSize() const {
467 return reader.totalSize().asPublic();
468 }
469
470 private:
471 _::ListReader reader;
472 template <typename U, Kind K>
473 friend struct _::PointerHelpers;
474 template <typename U, Kind K>
475 friend struct List;
476 friend class Orphanage;
477 template <typename U, Kind K>
478 friend struct ToDynamic_;
479 };
480
481 class Builder {
482 public:
483 typedef List<T> Builds;
484
485 inline Builder(): builder(ElementSize::POINTER) {}
486 inline Builder(decltype(nullptr)): Builder() {}
487 inline explicit Builder(_::ListBuilder builder): builder(builder) {}
488
489 inline operator Reader() const { return Reader(builder.asReader()); }
490 inline Reader asReader() const { return Reader(builder.asReader()); }
491
492 inline uint size() const { return unbound(builder.size() / ELEMENTS); }
493 inline typename T::Builder operator[](uint index) {
494 KJ_IREQUIRE(index < size());
495 return builder.getPointerElement(bounded(index) * ELEMENTS)
496 .template getBlob<T>(nullptr, ZERO * BYTES);
497 }
498 inline void set(uint index, typename T::Reader value) {
499 KJ_IREQUIRE(index < size());
500 builder.getPointerElement(bounded(index) * ELEMENTS).template setBlob<T>(value);
501 }
502 inline typename T::Builder init(uint index, uint size) {
503 KJ_IREQUIRE(index < this->size());
504 return builder.getPointerElement(bounded(index) * ELEMENTS)
505 .template initBlob<T>(bounded(size) * BYTES);
506 }
507 inline void adopt(uint index, Orphan<T>&& value) {
508 KJ_IREQUIRE(index < size());
509 builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder));
510 }
511 inline Orphan<T> disown(uint index) {
512 KJ_IREQUIRE(index < size());
513 return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown());
514 }
515
516 typedef _::IndexingIterator<Builder, typename T::Builder> Iterator;
517 inline Iterator begin() { return Iterator(this, 0); }
518 inline Iterator end() { return Iterator(this, size()); }
519
520 private:
521 _::ListBuilder builder;
522 template <typename U, Kind K>
523 friend struct _::PointerHelpers;
524 friend class Orphanage;
525 template <typename U, Kind K>
526 friend struct ToDynamic_;
527 };
528
529 class Pipeline {};
530
531private:
532 inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
533 return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS);
534 }
535 inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
536 return builder.getList(ElementSize::POINTER, defaultValue);
537 }
538 inline static _::ListReader getFromPointer(
539 const _::PointerReader& reader, const word* defaultValue) {
540 return reader.getList(ElementSize::POINTER, defaultValue);
541 }
542
543 template <typename U, Kind k>
544 friend struct List;
545 template <typename U, Kind K>
546 friend struct _::PointerHelpers;
547};
548
549} // namespace capnp
550
551#ifdef KJ_STD_COMPAT
552namespace std {
553
554template <typename Container, typename Element>
555struct iterator_traits<capnp::_::IndexingIterator<Container, Element>>
556 : public std::iterator<std::random_access_iterator_tag, Element, int> {};
557
558} // namespace std
559#endif // KJ_STD_COMPAT
560