list.h 20.5 KB
Newer Older
Kenton Varda's avatar
Kenton Varda committed
1 2
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
3
//
Kenton Varda's avatar
Kenton Varda committed
4 5 6 7 8 9
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
10
//
Kenton Varda's avatar
Kenton Varda committed
11 12
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
13
//
Kenton Varda's avatar
Kenton Varda committed
14 15 16 17 18 19 20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
21

Kenton Varda's avatar
Kenton Varda committed
22 23
#ifndef CAPNP_LIST_H_
#define CAPNP_LIST_H_
24

25
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
26 27 28
#pragma GCC system_header
#endif

29
#include "layout.h"
30
#include "orphan.h"
31
#include <initializer_list>
32
#ifdef KJ_STD_COMPAT
33
#include <iterator>
34
#endif  // KJ_STD_COMPAT
35

36
namespace capnp {
37
namespace _ {  // private
38

39 40 41 42 43 44 45 46
template <typename T>
class TemporaryPointer {
  // This class is a little hack which lets us define operator->() in cases where it needs to
  // return a pointer to a temporary value.  We instead construct a TemporaryPointer and return that
  // (by value).  The compiler then invokes operator->() on the TemporaryPointer, which itself is
  // able to return a real pointer to its member.

public:
Kenton Varda's avatar
Kenton Varda committed
47
  TemporaryPointer(T&& value): value(kj::mv(value)) {}
48 49 50 51 52 53 54
  TemporaryPointer(const T& value): value(value) {}

  inline T* operator->() { return &value; }
private:
  T value;
};

Kenton Varda's avatar
Kenton Varda committed
55
template <typename Container, typename Element>
56
class IndexingIterator {
57 58 59
public:
  IndexingIterator() = default;

Kenton Varda's avatar
Kenton Varda committed
60 61
  inline Element operator*() const { return (*container)[index]; }
  inline TemporaryPointer<Element> operator->() const {
Kenton Varda's avatar
Kenton Varda committed
62 63
    return TemporaryPointer<Element>((*container)[index]);
  }
Kenton Varda's avatar
Kenton Varda committed
64 65
  inline Element operator[]( int off) const { return (*container)[index]; }
  inline Element operator[](uint off) const { return (*container)[index]; }
66 67 68 69 70 71

  inline IndexingIterator& operator++() { ++index; return *this; }
  inline IndexingIterator operator++(int) { IndexingIterator other = *this; ++index; return other; }
  inline IndexingIterator& operator--() { --index; return *this; }
  inline IndexingIterator operator--(int) { IndexingIterator other = *this; --index; return other; }

Kenton Varda's avatar
Kenton Varda committed
72 73 74 75
  inline IndexingIterator operator+(uint amount) const { return IndexingIterator(container, index + amount); }
  inline IndexingIterator operator-(uint amount) const { return IndexingIterator(container, index - amount); }
  inline IndexingIterator operator+( int amount) const { return IndexingIterator(container, index + amount); }
  inline IndexingIterator operator-( int amount) const { return IndexingIterator(container, index - amount); }
76

Kenton Varda's avatar
Kenton Varda committed
77
  inline int operator-(const IndexingIterator& other) const { return index - other.index; }
78 79 80 81 82 83 84 85

  inline IndexingIterator& operator+=(uint amount) { index += amount; return *this; }
  inline IndexingIterator& operator-=(uint amount) { index -= amount; return *this; }
  inline IndexingIterator& operator+=( int amount) { index += amount; return *this; }
  inline IndexingIterator& operator-=( int amount) { index -= amount; return *this; }

  // STL says comparing iterators of different containers is not allowed, so we only compare
  // indices here.
Kenton Varda's avatar
Kenton Varda committed
86 87 88 89 90 91
  inline bool operator==(const IndexingIterator& other) const { return index == other.index; }
  inline bool operator!=(const IndexingIterator& other) const { return index != other.index; }
  inline bool operator<=(const IndexingIterator& other) const { return index <= other.index; }
  inline bool operator>=(const IndexingIterator& other) const { return index >= other.index; }
  inline bool operator< (const IndexingIterator& other) const { return index <  other.index; }
  inline bool operator> (const IndexingIterator& other) const { return index >  other.index; }
92 93

private:
94
  Container* container;
95 96 97
  uint index;

  friend Container;
98
  inline IndexingIterator(Container* container, uint index)
99
      : container(container), index(index) {}
100 101
};

102
}  // namespace _ (private)
103 104

template <typename T>
105
struct List<T, Kind::PRIMITIVE> {
106 107
  // List of primitives.

108 109
  List() = delete;

110 111
  class Reader {
  public:
112 113
    typedef List<T> Reads;

114
    inline Reader(): reader(_::elementSizeForType<T>()) {}
115
    inline explicit Reader(_::ListReader reader): reader(reader) {}
116

117
    inline uint size() const { return unbound(reader.size() / ELEMENTS); }
118
    inline T operator[](uint index) const {
119
      KJ_IREQUIRE(index < size());
120
      return reader.template getDataElement<T>(bounded(index) * ELEMENTS);
121
    }
122

123
    typedef _::IndexingIterator<const Reader, T> Iterator;
124 125
    inline Iterator begin() const { return Iterator(this, 0); }
    inline Iterator end() const { return Iterator(this, size()); }
126 127

  private:
128
    _::ListReader reader;
129
    template <typename U, Kind K>
130
    friend struct _::PointerHelpers;
131 132
    template <typename U, Kind K>
    friend struct List;
133 134 135
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
136 137 138 139
  };

  class Builder {
  public:
140 141
    typedef List<T> Builds;

142
    inline Builder(): builder(_::elementSizeForType<T>()) {}
Kenton Varda's avatar
Kenton Varda committed
143
    inline Builder(decltype(nullptr)): Builder() {}
144
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}
145

146 147
    inline operator Reader() const { return Reader(builder.asReader()); }
    inline Reader asReader() const { return Reader(builder.asReader()); }
148

149
    inline uint size() const { return unbound(builder.size() / ELEMENTS); }
150
    inline T operator[](uint index) {
151
      KJ_IREQUIRE(index < size());
152
      return builder.template getDataElement<T>(bounded(index) * ELEMENTS);
Kenton Varda's avatar
Kenton Varda committed
153 154 155 156 157 158 159 160
    }
    inline void set(uint index, T value) {
      // Alas, it is not possible to make operator[] return a reference to which you can assign,
      // since the encoded representation does not necessarily match the compiler's representation
      // of the type.  We can't even return a clever class that implements operator T() and
      // operator=() because it will lead to surprising behavior when using type inference (e.g.
      // calling a template function with inferred argument types, or using "auto" or "decltype").

161
      builder.template setDataElement<T>(bounded(index) * ELEMENTS, value);
Kenton Varda's avatar
Kenton Varda committed
162
    }
163

164
    typedef _::IndexingIterator<Builder, T> Iterator;
165 166
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }
167

Kenton Varda's avatar
Kenton Varda committed
168
  private:
169
    _::ListBuilder builder;
170 171
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
172 173 174
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
175
  };
176

177 178
  class Pipeline {};

179
private:
180
  inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
181
    return builder.initList(_::elementSizeForType<T>(), bounded(size) * ELEMENTS);
182
  }
183 184
  inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
    return builder.getList(_::elementSizeForType<T>(), defaultValue);
185
  }
186 187 188
  inline static _::ListReader getFromPointer(
      const _::PointerReader& reader, const word* defaultValue) {
    return reader.getList(_::elementSizeForType<T>(), defaultValue);
189 190
  }

191
  template <typename U, Kind k>
Kenton Varda's avatar
Kenton Varda committed
192
  friend struct List;
193
  template <typename U, Kind K>
194
  friend struct _::PointerHelpers;
Kenton Varda's avatar
Kenton Varda committed
195 196 197
};

template <typename T>
198 199 200 201
struct List<T, Kind::ENUM>: public List<T, Kind::PRIMITIVE> {};

template <typename T>
struct List<T, Kind::STRUCT> {
202 203
  // List of structs.

204 205
  List() = delete;

Kenton Varda's avatar
Kenton Varda committed
206 207
  class Reader {
  public:
208 209
    typedef List<T> Reads;

210
    inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {}
211
    inline explicit Reader(_::ListReader reader): reader(reader) {}
Kenton Varda's avatar
Kenton Varda committed
212

213
    inline uint size() const { return unbound(reader.size() / ELEMENTS); }
214
    inline typename T::Reader operator[](uint index) const {
215
      KJ_IREQUIRE(index < size());
216
      return typename T::Reader(reader.getStructElement(bounded(index) * ELEMENTS));
Kenton Varda's avatar
Kenton Varda committed
217
    }
218

219
    typedef _::IndexingIterator<const Reader, typename T::Reader> Iterator;
220 221
    inline Iterator begin() const { return Iterator(this, 0); }
    inline Iterator end() const { return Iterator(this, size()); }
222

Kenton Varda's avatar
Kenton Varda committed
223
  private:
224
    _::ListReader reader;
225
    template <typename U, Kind K>
226
    friend struct _::PointerHelpers;
227 228
    template <typename U, Kind K>
    friend struct List;
229 230 231
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
232
  };
233

Kenton Varda's avatar
Kenton Varda committed
234 235
  class Builder {
  public:
236 237
    typedef List<T> Builds;

238
    inline Builder(): builder(ElementSize::INLINE_COMPOSITE) {}
Kenton Varda's avatar
Kenton Varda committed
239
    inline Builder(decltype(nullptr)): Builder() {}
240
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}
241

242 243
    inline operator Reader() const { return Reader(builder.asReader()); }
    inline Reader asReader() const { return Reader(builder.asReader()); }
244

245
    inline uint size() const { return unbound(builder.size() / ELEMENTS); }
246
    inline typename T::Builder operator[](uint index) {
247
      KJ_IREQUIRE(index < size());
248
      return typename T::Builder(builder.getStructElement(bounded(index) * ELEMENTS));
Kenton Varda's avatar
Kenton Varda committed
249
    }
250

251 252 253 254 255 256 257 258 259 260
    inline void adoptWithCaveats(uint index, Orphan<T>&& orphan) {
      // Mostly behaves like you'd expect `adopt` to behave, but with two caveats originating from
      // the fact that structs in a struct list are allocated inline rather than by pointer:
      // * This actually performs a shallow copy, effectively adopting each of the orphan's
      //   children rather than adopting the orphan itself.  The orphan ends up being discarded,
      //   possibly wasting space in the message object.
      // * If the orphan is larger than the target struct -- say, because the orphan was built
      //   using a newer version of the schema that has additional fields -- it will be truncated,
      //   losing data.

261 262
      KJ_IREQUIRE(index < size());

263 264 265
      // We pass a zero-valued StructSize to asStruct() because we do not want the struct to be
      // expanded under any circumstances.  We're just going to throw it away anyway, and
      // transferContentFrom() already carefully compares the struct sizes before transferring.
266
      builder.getStructElement(bounded(index) * ELEMENTS).transferContentFrom(
267
          orphan.builder.asStruct(_::StructSize(ZERO * WORDS, ZERO * POINTERS)));
268
    }
269 270 271 272 273 274
    inline void setWithCaveats(uint index, const typename T::Reader& reader) {
      // Mostly behaves like you'd expect `set` to behave, but with a caveat originating from
      // the fact that structs in a struct list are allocated inline rather than by pointer:
      // If the source struct is larger than the target struct -- say, because the source was built
      // using a newer version of the schema that has additional fields -- it will be truncated,
      // losing data.
275 276 277 278
      //
      // Note: If you are trying to concatenate some lists, use Orphanage::newOrphanConcat() to
      //   do it without losing any data in case the source lists come from a newer version of the
      //   protocol. (Plus, it's easier to use anyhow.)
279

280
      KJ_IREQUIRE(index < size());
281
      builder.getStructElement(bounded(index) * ELEMENTS).copyContentFrom(reader._reader);
282
    }
283

284 285 286 287
    // There are no init(), set(), adopt(), or disown() methods for lists of structs because the
    // elements of the list are inlined and are initialized when the list is initialized.  This
    // means that init() would be redundant, and set() would risk data loss if the input struct
    // were from a newer version of the protocol.
288

289
    typedef _::IndexingIterator<Builder, typename T::Builder> Iterator;
290 291
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }
292 293

  private:
294
    _::ListBuilder builder;
295 296
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
297 298 299
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
300
  };
301

302 303
  class Pipeline {};

304
private:
305
  inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
306
    return builder.initStructList(bounded(size) * ELEMENTS, _::structSize<T>());
307
  }
308 309
  inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
    return builder.getStructList(_::structSize<T>(), defaultValue);
310
  }
311 312
  inline static _::ListReader getFromPointer(
      const _::PointerReader& reader, const word* defaultValue) {
313
    return reader.getList(ElementSize::INLINE_COMPOSITE, defaultValue);
314 315
  }

316
  template <typename U, Kind k>
Kenton Varda's avatar
Kenton Varda committed
317
  friend struct List;
318
  template <typename U, Kind K>
319
  friend struct _::PointerHelpers;
320 321 322
};

template <typename T>
323
struct List<List<T>, Kind::LIST> {
324 325
  // List of lists.

326 327
  List() = delete;

328 329
  class Reader {
  public:
330 331
    typedef List<List<T>> Reads;

332
    inline Reader(): reader(ElementSize::POINTER) {}
333
    inline explicit Reader(_::ListReader reader): reader(reader) {}
334

335
    inline uint size() const { return unbound(reader.size() / ELEMENTS); }
336
    inline typename List<T>::Reader operator[](uint index) const {
337
      KJ_IREQUIRE(index < size());
338
      return typename List<T>::Reader(_::PointerHelpers<List<T>>::get(
339
          reader.getPointerElement(bounded(index) * ELEMENTS)));
Kenton Varda's avatar
Kenton Varda committed
340
    }
341

342
    typedef _::IndexingIterator<const Reader, typename List<T>::Reader> Iterator;
343 344
    inline Iterator begin() const { return Iterator(this, 0); }
    inline Iterator end() const { return Iterator(this, size()); }
345 346

  private:
347
    _::ListReader reader;
348
    template <typename U, Kind K>
349
    friend struct _::PointerHelpers;
350 351
    template <typename U, Kind K>
    friend struct List;
352 353 354
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
355 356 357 358
  };

  class Builder {
  public:
359 360
    typedef List<List<T>> Builds;

361
    inline Builder(): builder(ElementSize::POINTER) {}
Kenton Varda's avatar
Kenton Varda committed
362
    inline Builder(decltype(nullptr)): Builder() {}
363
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}
364

365 366
    inline operator Reader() const { return Reader(builder.asReader()); }
    inline Reader asReader() const { return Reader(builder.asReader()); }
367

368
    inline uint size() const { return unbound(builder.size() / ELEMENTS); }
369
    inline typename List<T>::Builder operator[](uint index) {
370
      KJ_IREQUIRE(index < size());
371
      return typename List<T>::Builder(_::PointerHelpers<List<T>>::get(
372
          builder.getPointerElement(bounded(index) * ELEMENTS)));
Kenton Varda's avatar
Kenton Varda committed
373 374
    }
    inline typename List<T>::Builder init(uint index, uint size) {
375
      KJ_IREQUIRE(index < this->size());
376
      return typename List<T>::Builder(_::PointerHelpers<List<T>>::init(
377
          builder.getPointerElement(bounded(index) * ELEMENTS), size));
Kenton Varda's avatar
Kenton Varda committed
378
    }
379
    inline void set(uint index, typename List<T>::Reader value) {
380
      KJ_IREQUIRE(index < size());
381
      builder.getPointerElement(bounded(index) * ELEMENTS).setList(value.reader);
382 383
    }
    void set(uint index, std::initializer_list<ReaderFor<T>> value) {
384
      KJ_IREQUIRE(index < size());
385 386 387 388 389 390
      auto l = init(index, value.size());
      uint i = 0;
      for (auto& element: value) {
        l.set(i++, element);
      }
    }
391
    inline void adopt(uint index, Orphan<T>&& value) {
392
      KJ_IREQUIRE(index < size());
393
      builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder));
394 395
    }
    inline Orphan<T> disown(uint index) {
396
      KJ_IREQUIRE(index < size());
397
      return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown());
398
    }
399

400
    typedef _::IndexingIterator<Builder, typename List<T>::Builder> Iterator;
401 402
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }
403

Kenton Varda's avatar
Kenton Varda committed
404
  private:
405
    _::ListBuilder builder;
406 407
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
408 409 410
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
411
  };
412

413 414
  class Pipeline {};

415
private:
416
  inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
417
    return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS);
418
  }
419
  inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
420
    return builder.getList(ElementSize::POINTER, defaultValue);
421
  }
422 423
  inline static _::ListReader getFromPointer(
      const _::PointerReader& reader, const word* defaultValue) {
424
    return reader.getList(ElementSize::POINTER, defaultValue);
425 426
  }

427
  template <typename U, Kind k>
Kenton Varda's avatar
Kenton Varda committed
428
  friend struct List;
429
  template <typename U, Kind K>
430
  friend struct _::PointerHelpers;
Kenton Varda's avatar
Kenton Varda committed
431 432
};

433 434
template <typename T>
struct List<T, Kind::BLOB> {
435 436
  List() = delete;

Kenton Varda's avatar
Kenton Varda committed
437 438
  class Reader {
  public:
439 440
    typedef List<T> Reads;

441
    inline Reader(): reader(ElementSize::POINTER) {}
442
    inline explicit Reader(_::ListReader reader): reader(reader) {}
Kenton Varda's avatar
Kenton Varda committed
443

444
    inline uint size() const { return unbound(reader.size() / ELEMENTS); }
445
    inline typename T::Reader operator[](uint index) const {
446
      KJ_IREQUIRE(index < size());
447
      return reader.getPointerElement(bounded(index) * ELEMENTS)
448
          .template getBlob<T>(nullptr, ZERO * BYTES);
Kenton Varda's avatar
Kenton Varda committed
449 450
    }

451
    typedef _::IndexingIterator<const Reader, typename T::Reader> Iterator;
452 453
    inline Iterator begin() const { return Iterator(this, 0); }
    inline Iterator end() const { return Iterator(this, size()); }
Kenton Varda's avatar
Kenton Varda committed
454 455

  private:
456
    _::ListReader reader;
457
    template <typename U, Kind K>
458
    friend struct _::PointerHelpers;
459 460
    template <typename U, Kind K>
    friend struct List;
461 462 463
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
464 465 466 467
  };

  class Builder {
  public:
468 469
    typedef List<T> Builds;

470
    inline Builder(): builder(ElementSize::POINTER) {}
Kenton Varda's avatar
Kenton Varda committed
471
    inline Builder(decltype(nullptr)): Builder() {}
472
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}
Kenton Varda's avatar
Kenton Varda committed
473

474 475
    inline operator Reader() const { return Reader(builder.asReader()); }
    inline Reader asReader() const { return Reader(builder.asReader()); }
476

477
    inline uint size() const { return unbound(builder.size() / ELEMENTS); }
478
    inline typename T::Builder operator[](uint index) {
479
      KJ_IREQUIRE(index < size());
480
      return builder.getPointerElement(bounded(index) * ELEMENTS)
481
          .template getBlob<T>(nullptr, ZERO * BYTES);
Kenton Varda's avatar
Kenton Varda committed
482
    }
483
    inline void set(uint index, typename T::Reader value) {
484
      KJ_IREQUIRE(index < size());
485
      builder.getPointerElement(bounded(index) * ELEMENTS).template setBlob<T>(value);
486
    }
487
    inline typename T::Builder init(uint index, uint size) {
488
      KJ_IREQUIRE(index < this->size());
489 490
      return builder.getPointerElement(bounded(index) * ELEMENTS)
          .template initBlob<T>(bounded(size) * BYTES);
Kenton Varda's avatar
Kenton Varda committed
491
    }
492
    inline void adopt(uint index, Orphan<T>&& value) {
493
      KJ_IREQUIRE(index < size());
494
      builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder));
495 496
    }
    inline Orphan<T> disown(uint index) {
497
      KJ_IREQUIRE(index < size());
498
      return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown());
499
    }
Kenton Varda's avatar
Kenton Varda committed
500

501
    typedef _::IndexingIterator<Builder, typename T::Builder> Iterator;
502 503
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }
Kenton Varda's avatar
Kenton Varda committed
504 505

  private:
506
    _::ListBuilder builder;
507 508
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
509 510 511
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
512
  };
513

514 515
  class Pipeline {};

516
private:
517
  inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
518
    return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS);
519
  }
520
  inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
521
    return builder.getList(ElementSize::POINTER, defaultValue);
522
  }
523 524
  inline static _::ListReader getFromPointer(
      const _::PointerReader& reader, const word* defaultValue) {
525
    return reader.getList(ElementSize::POINTER, defaultValue);
526 527
  }

528
  template <typename U, Kind k>
Kenton Varda's avatar
Kenton Varda committed
529
  friend struct List;
530
  template <typename U, Kind K>
531
  friend struct _::PointerHelpers;
Kenton Varda's avatar
Kenton Varda committed
532 533
};

534
}  // namespace capnp
535

536 537 538 539 540 541 542 543 544 545
#ifdef KJ_STD_COMPAT
namespace std {

template <typename Container, typename Element>
struct iterator_traits<capnp::_::IndexingIterator<Container, Element>>
      : public std::iterator<std::random_access_iterator_tag, Element, int> {};

}  // namespace std
#endif  // KJ_STD_COMPAT

Kenton Varda's avatar
Kenton Varda committed
546
#endif  // CAPNP_LIST_H_