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