nlib
Nlist.h
Go to the documentation of this file.
1 
2 /*--------------------------------------------------------------------------------*
3  Project: CrossRoad
4  Copyright (C)Nintendo All rights reserved.
5 
6  These coded instructions, statements, and computer programs contain proprietary
7  information of Nintendo and/or its licensed developers and are protected by
8  national and international copyright laws. They may not be disclosed to third
9  parties or copied or duplicated in any form, in whole or in part, without the
10  prior written consent of Nintendo.
11 
12  The content herein is highly confidential and should be handled accordingly.
13  *--------------------------------------------------------------------------------*/
14 
15 #pragma once
16 #ifndef INCLUDE_NN_NLIB_NLIST_H_
17 #define INCLUDE_NN_NLIB_NLIST_H_
18 
19 #include <string.h>
20 #include <utility>
21 #include <algorithm>
22 #include <iterator>
23 #include <memory>
24 
25 #include "nn/nlib/Config.h"
26 #include "nn/nlib/Swap.h"
27 #include "nn/nlib/TypeTraits.h"
28 
29 NLIB_NAMESPACE_BEGIN
30 
31 template <class T, class AL>
32 class Nlist;
33 
34 namespace nlist {
35 
36 class NLIB_VIS_PUBLIC NlistBase {
37  protected:
38  struct Blk {
39  Blk* next;
40  void* item;
41  };
42 
43  protected:
44  NLIB_CEXPR NlistBase() NLIB_NOEXCEPT
45  : curblk_(nullptr), curlevel_(0), curidx_(0), firstblk_(nullptr) {}
46 #ifdef __cpp_rvalue_references
47  NlistBase(NlistBase&& rhs) NLIB_NOEXCEPT
48  : curblk_(rhs.curblk_), curlevel_(rhs.curlevel_),
49  curidx_(rhs.curidx_), firstblk_(rhs.firstblk_) {
50  rhs.curblk_ = nullptr;
51  rhs.curlevel_ = 0U;
52  rhs.curidx_ = 0U;
53  rhs.firstblk_ = nullptr;
54  }
55  NlistBase& operator=(NlistBase&& rhs) NLIB_NOEXCEPT {
56  curblk_ = rhs.curblk_;
57  curlevel_ = rhs.curlevel_;
58  curidx_ = rhs.curidx_;
59  firstblk_ = rhs.firstblk_;
60  rhs.curblk_ = nullptr;
61  rhs.curlevel_ = 0U;
62  rhs.curidx_ = 0U;
63  rhs.firstblk_ = nullptr;
64  return *this;
65  }
66 #endif
67  NlistBase(NlistBase& rhs, move_tag) NLIB_NOEXCEPT // NOLINT
68  : curblk_(rhs.curblk_), curlevel_(rhs.curlevel_),
69  curidx_(rhs.curidx_), firstblk_(rhs.firstblk_) {
70  rhs.curblk_ = nullptr;
71  rhs.curlevel_ = 0U;
72  rhs.curidx_ = 0U;
73  rhs.firstblk_ = nullptr;
74  }
75  NlistBase& assign(NlistBase& rhs, move_tag) NLIB_NOEXCEPT { // NOLINT
76  curblk_ = rhs.curblk_;
77  curlevel_ = rhs.curlevel_;
78  curidx_ = rhs.curidx_;
79  firstblk_ = rhs.firstblk_;
80  rhs.curblk_ = nullptr;
81  rhs.curlevel_ = 0U;
82  rhs.curidx_ = 0U;
83  rhs.firstblk_ = nullptr;
84  return *this;
85  }
86  static size_t BlkBaseIdx(size_t level) NLIB_NOEXCEPT {
87  return 8 * ((1 << level) - 1);
88  }
89  static size_t BlkSize(size_t level) NLIB_NOEXCEPT {
90  return 8 * (1 << level);
91  }
92  Blk* LastBlock(size_t* level) const NLIB_NOEXCEPT;
93  bool ConfirmBack() const NLIB_NOEXCEPT;
94  void ClearSimple() NLIB_NOEXCEPT {
95  curlevel_ = 0;
96  curidx_ = 0;
97  curblk_ = firstblk_;
98  }
99  const Blk* AtSub(size_t n, size_t* base) const NLIB_NOEXCEPT;
100 
101  protected:
102  mutable Blk* curblk_;
103  mutable size_t curlevel_;
104  mutable size_t curidx_;
105  mutable Blk* firstblk_;
106 
107  private:
109 };
110 
111 template <class T>
112 class NlistConstIterator;
113 template <class T>
114 class NlistIterator;
115 
116 template <class T>
117 class NlistBaseT : public NlistBase {
118  public:
119  typedef T& reference;
120  typedef const T& const_reference;
121  typedef NlistIterator<T> iterator;
122  typedef NlistConstIterator<T> const_iterator;
123  typedef size_t size_type;
124  typedef T value_type;
125  typedef T* pointer;
126  typedef const T* const_pointer;
127  typedef ptrdiff_t difference_type;
128 
129  protected:
130  NLIB_CEXPR NlistBaseT() {}
131 #ifdef __cpp_rvalue_references
132 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS
133  NlistBaseT(NlistBaseT&& rhs) = default;
134  NlistBaseT& operator=(NlistBaseT&& rhs) = default;
135 #else
136  NlistBaseT(NlistBaseT&& rhs) NLIB_NOEXCEPT : NlistBase(std::move(rhs)) {}
137  NlistBaseT& operator=(NlistBaseT&& rhs) NLIB_NOEXCEPT {
138  NlistBase::operator=(std::move(rhs));
139  return *this;
140  }
141 #endif
142 #endif
143  NlistBaseT(NlistBaseT& rhs, move_tag) NLIB_NOEXCEPT // NOLINT
144  : NlistBase(rhs, move_tag()) {}
145  NlistBaseT& assign(NlistBaseT& rhs, move_tag) NLIB_NOEXCEPT {
146  NlistBase::assign(rhs, move_tag());
147  return *this;
148  }
149 
150  static T* GetItem(Blk* blk) NLIB_NOEXCEPT {
151  return static_cast<T*>(blk->item);
152  }
153  static const T* GetItem(const Blk* blk) NLIB_NOEXCEPT {
154  return static_cast<const T*>(blk->item);
155  }
156  T* At(size_type n) const NLIB_NOEXCEPT {
157  size_type base;
158  const Blk* p = this->AtSub(n, &base);
159  return p ? const_cast<T*>(&(GetItem(p)[n - base])) : nullptr;
160  }
161  iterator Begin() NLIB_NOEXCEPT { return iterator(this, TrueType()); }
162  iterator End() NLIB_NOEXCEPT { return iterator(this, FalseType()); }
163  const_iterator Begin() const NLIB_NOEXCEPT {
164  return const_iterator(this, TrueType());
165  }
166  const_iterator End() const NLIB_NOEXCEPT {
167  return const_iterator(this, FalseType());
168  }
169 
170  private:
171  NLIB_DISALLOW_COPY_AND_ASSIGN(NlistBaseT);
172  friend class NlistConstIterator<T>;
173  friend class NlistIterator<T>;
174 };
175 
176 template <class T>
177 class NlistConstIterator
178  : public std::iterator<std::forward_iterator_tag, T> {
179  private:
180  typedef NlistBaseT<T> ContainerType;
181  typedef typename ContainerType::Blk Blk;
182 
183  public:
184  typedef typename std::iterator<std::forward_iterator_tag, T> BaseType;
185  typedef typename BaseType::iterator_category iterator_category;
186  typedef typename BaseType::value_type value_type;
187  typedef typename BaseType::difference_type difference_type;
188  typedef typename BaseType::pointer pointer;
189  typedef typename BaseType::reference reference;
190 
191  public:
192  NLIB_CEXPR NlistConstIterator() NLIB_NOEXCEPT : idx_(0),
193  elemptr_(nullptr),
194  blkend_(nullptr),
195  blk_(nullptr) {}
196 
197  protected:
198  NlistConstIterator(const ContainerType* p, TrueType) NLIB_NOEXCEPT {
199  ContainerType* rhs = const_cast<ContainerType*>(p);
200  idx_ = 0;
201  blk_ = rhs->firstblk_;
202  elemptr_ = GetItem(blk_);
203  blkend_ = elemptr_ + 8;
204  }
205  NlistConstIterator(const ContainerType* p, FalseType) NLIB_NOEXCEPT {
206  ContainerType* rhs = const_cast<ContainerType*>(p);
207  idx_ = rhs->BlkBaseIdx(rhs->curlevel_) + rhs->curidx_;
208  blk_ = rhs->curblk_;
209  elemptr_ = &(GetItem(blk_)[rhs->curidx_]);
210  blkend_ = GetItem(blk_) + rhs->BlkSize(rhs->curlevel_);
211  if (elemptr_ == blkend_) this->Normalize();
212  }
213 
214  public:
215  const T& operator*() const NLIB_NOEXCEPT { return *elemptr_; }
216  const T* operator->() const NLIB_NOEXCEPT { return elemptr_; }
217  NlistConstIterator& operator++() NLIB_NOEXCEPT {
218  NLIB_ASSERT(elemptr_ != blkend_);
219  ++idx_;
220  if (++elemptr_ == blkend_) this->Normalize();
221  return *this;
222  }
223  NlistConstIterator operator++(int) NLIB_NOEXCEPT { // NOLINT
224  NlistConstIterator rval(*this);
225  this->operator++();
226  return rval;
227  }
228  bool operator==(const NlistConstIterator& rhs) const NLIB_NOEXCEPT {
229  return idx_ == rhs.idx_ && elemptr_ == rhs.elemptr_;
230  }
231  bool operator!=(const NlistConstIterator& rhs) const NLIB_NOEXCEPT {
232  return !operator==(rhs);
233  }
234  void Advance(difference_type n) NLIB_NOEXCEPT;
235  difference_type Distance(NlistConstIterator to) const NLIB_NOEXCEPT {
236  return to.idx_ - idx_;
237  }
238 
239  private:
240  static T* GetItem(Blk* blk) NLIB_NOEXCEPT {
241  return static_cast<T*>(blk->item);
242  }
243  static const T* GetItem(const Blk* blk) NLIB_NOEXCEPT {
244  return reinterpret_cast<const T*>(blk->item);
245  }
246  bool Normalize() NLIB_NOEXCEPT;
247 
248  private:
249  size_t idx_;
250  T* elemptr_;
251  T* blkend_;
252  Blk* blk_;
253  friend class NlistBaseT<T>;
254 };
255 
256 template <class T>
257 bool NlistConstIterator<T>::Normalize() NLIB_NOEXCEPT {
258  if (blk_ && blk_->next) {
259  Blk* next = blk_->next;
260  size_t next_size = 2 * static_cast<size_t>(blkend_ - GetItem(blk_));
261  T* next_elemptr = GetItem(next);
262  T* next_end = next_elemptr + next_size;
263  blk_ = next;
264  elemptr_ = next_elemptr;
265  blkend_ = next_end;
266  return true;
267  }
268  return false;
269 }
270 
271 template <class T>
272 void NlistConstIterator<T>::Advance(difference_type n) NLIB_NOEXCEPT {
273  while (elemptr_ + n >= blkend_) {
274  n -= blkend_ - elemptr_;
275  idx_ += blkend_ - elemptr_;
276  elemptr_ = blkend_;
277  if (!this->Normalize()) return;
278  }
279  elemptr_ += n;
280  idx_ += n;
281 }
282 
283 template <class T>
284 class NlistIterator : public NlistConstIterator<T> {
285  private:
286  typedef NlistBaseT<T> ContainerType;
287  typedef typename ContainerType::Blk Blk;
288  typedef NlistConstIterator<T> MyBase;
289 
290  public:
291  typedef typename NlistConstIterator<T>::BaseType BaseType;
292  typedef typename BaseType::iterator_category iterator_category;
293  typedef typename BaseType::value_type value_type;
294  typedef typename BaseType::difference_type difference_type;
295  typedef typename BaseType::pointer pointer;
296  typedef typename BaseType::reference reference;
297 
298  public:
299  NLIB_CEXPR NlistIterator() NLIB_NOEXCEPT : MyBase() {}
300 
301  private:
302  NlistIterator(const ContainerType* p, TrueType) NLIB_NOEXCEPT : MyBase(p, TrueType()) {}
303  NlistIterator(const ContainerType* p, FalseType) NLIB_NOEXCEPT : MyBase(p, FalseType()) {}
304 
305  public:
306  T& operator*() const NLIB_NOEXCEPT {
307  const MyBase* tmp = static_cast<const MyBase*>(this);
308  return const_cast<T&>(**tmp);
309  }
310  T* operator->() const NLIB_NOEXCEPT {
311  const MyBase* tmp = static_cast<const MyBase*>(this);
312  return const_cast<T*>(tmp->operator->());
313  }
314  NlistIterator& operator++() NLIB_NOEXCEPT {
315  MyBase* tmp = static_cast<MyBase*>(this);
316  ++(*tmp);
317  return *this;
318  }
319  NlistIterator operator++(int) NLIB_NOEXCEPT { // NOLINT
320  NlistIterator rval(*this);
321  ++(*this);
322  return rval;
323  }
324  bool operator==(const NlistIterator& rhs) const NLIB_NOEXCEPT {
325  const MyBase* tmp = static_cast<const MyBase*>(this);
326  const MyBase* tmp2 = static_cast<const MyBase*>(&rhs);
327  return *tmp == *tmp2;
328  }
329  bool operator!=(const NlistIterator& rhs) const NLIB_NOEXCEPT {
330  return !operator==(rhs);
331  }
332  difference_type Distance(NlistIterator to) const NLIB_NOEXCEPT {
333  const MyBase* tmp = static_cast<const MyBase*>(this);
334  const MyBase* tmp2 = static_cast<const MyBase*>(&to);
335  return tmp->Distance(*tmp2);
336  }
337 
338  private:
339  friend class NlistBaseT<T>;
340 };
341 
342 template<bool is_empty, class AL>
343 class NlistAlloc {
344  public:
345  NlistAlloc() NLIB_NOEXCEPT : alloc_(AL()) {}
346  explicit NlistAlloc(const AL& al) NLIB_NOEXCEPT : alloc_(al) {}
347 
348  protected:
349  AL& _GetNlistAlloc() const NLIB_NOEXCEPT {
350  return const_cast<AL&>(alloc_);
351  }
352  void _SwapNlistAlloc(NlistAlloc& rhs) NLIB_NOEXCEPT { // NOLINT
353  using std::swap;
354  swap(alloc_, rhs.alloc_);
355  }
356 #ifdef __cpp_rvalue_references
357 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS
358  NlistAlloc(NlistAlloc&& rhs) = default;
359  NlistAlloc& operator=(NlistAlloc&& rhs) = default;
360 #else
361  NlistAlloc(NlistAlloc&& rhs) NLIB_NOEXCEPT : alloc_(std::move(rhs.alloc_)) {}
362  NlistAlloc& operator=(NlistAlloc&& rhs) NLIB_NOEXCEPT {
363  alloc_ = std::move(rhs.alloc_);
364  return *this;
365  }
366 #endif
367 #endif
368  NlistAlloc(NlistAlloc& rhs, move_tag) NLIB_NOEXCEPT // NOLINT
369  : alloc_() {
370  using std::swap;
371  swap(alloc_, rhs.alloc_);
372  }
373  NlistAlloc& assign(NlistAlloc& rhs, move_tag) NLIB_NOEXCEPT {
374  using std::swap;
375  AL x(*this, move_tag());
376  swap(alloc_, rhs.alloc_);
377  return *this;
378  }
379 
380  private:
381  AL alloc_;
382 };
383 
384 template<class AL>
385 class NlistAlloc <true, AL> {
386  public:
387  NlistAlloc() NLIB_NOEXCEPT {}
388  explicit NlistAlloc(const AL& al) NLIB_NOEXCEPT { NLIB_UNUSED(al); }
389 
390  protected:
391  AL _GetNlistAlloc() const NLIB_NOEXCEPT { return AL(); }
392  void _SwapNlistAlloc(NlistAlloc& rhs) NLIB_NOEXCEPT { // NOLINT
393  NLIB_UNUSED(rhs);
394  }
395 #ifdef __cpp_rvalue_references
396  NlistAlloc(NlistAlloc&&) NLIB_NOEXCEPT {}
397  NlistAlloc& operator=(NlistAlloc&&) NLIB_NOEXCEPT { return *this; }
398 #endif
399  NlistAlloc(NlistAlloc&, move_tag) NLIB_NOEXCEPT {}
400  NlistAlloc& assign(NlistAlloc&, move_tag) NLIB_NOEXCEPT { return *this; }
401 };
402 
403 } // namespace nlist
404 
405 template <class T, class AL = std::allocator<char> >
406 class Nlist NLIB_FINAL : public nlist::NlistBaseT<T>,
407  public nlist::NlistAlloc<IsEmpty<AL>::value, AL> {
408  // NOTE:
409  // To develop custom allocators:
410  //
411  // Nlist uses only the subset of std::allocator<T>.
412  // 1) rebind() is not used. the custom allocator does not have to be a class template.
413  // 2) construct(), destroy() are not used.
414  //
415  // You have to implement:
416  // a) void* allocate(size_t nbytes);
417  // b) void deallocate(void* ptr, size_t nbytes);
418  // allocate has to return 8 bytes aligned memory.
419  // And the custom allocator cannot have non-static data members.
420  /*
421  class MyAllocator
422  {
423  public:
424  MyAllocator();
425  MyAllocator(const MyAllocator& rhs);
426  void* allocate(size_t nbytes, void*);
427  void deallocate(void* p, size_t nbytes);
428  };
429  */
430 
431  private:
432  typedef typename nlist::NlistBaseT<T> BaseType;
433  typedef typename nlist::NlistAlloc<IsEmpty<AL>::value, AL> AllocType;
434  using BaseType::curblk_;
435  using BaseType::curidx_;
436  using BaseType::curlevel_;
437  using BaseType::firstblk_;
438  using BaseType::ConfirmBack;
439  using BaseType::ClearSimple;
440  using BaseType::BlkBaseIdx;
441  using BaseType::BlkSize;
442  using BaseType::GetItem;
443  using BaseType::Begin;
444  using BaseType::End;
445  typedef typename BaseType::Blk Blk;
446 
447  public:
449  typedef AL allocator_type;
450  typedef typename BaseType::size_type size_type;
451  typedef typename BaseType::difference_type difference_type;
452  typedef typename BaseType::reference reference;
454  typedef typename BaseType::pointer pointer;
456  typedef typename BaseType::iterator iterator;
457  typedef typename BaseType::const_iterator const_iterator;
458 
459  public:
460  Nlist() NLIB_NOEXCEPT : AllocType(AL()) {}
461  explicit Nlist(const AL& al) NLIB_NOEXCEPT : AllocType(al) {}
462  ~Nlist() NLIB_NOEXCEPT;
463 #ifdef __cpp_rvalue_references
464 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS
465  Nlist(Nlist&& rhs) = default;
466 #else
467  Nlist(Nlist&& rhs) NLIB_NOEXCEPT
468  : BaseType(std::move(rhs)), AllocType(std::move(rhs)) {}
469 #endif
470  Nlist& operator=(Nlist&& rhs) NLIB_NOEXCEPT {
471  this->clear();
472  this->DeallocBlkList(firstblk_, 0);
473  BaseType::operator=(std::move(rhs));
474  AllocType::operator=(std::move(rhs));
475  return *this;
476  }
477 #endif
478  Nlist(Nlist& rhs, move_tag) NLIB_NOEXCEPT // NOLINT
479  : BaseType(rhs, move_tag()), AllocType(rhs, move_tag()) {}
480  Nlist& assign(Nlist& rhs, move_tag) NLIB_NOEXCEPT {
481  this->clear();
482  this->DeallocBlkList(firstblk_, 0);
483  BaseType::assign(rhs, move_tag());
484  AllocType::assign(rhs, move_tag());
485  return *this;
486  }
487  NLIB_DEPRECATED void swap(Nlist& rhs) NLIB_NOEXCEPT { // NOLINT
488  using std::swap;
489  swap(curblk_, rhs.curblk_);
490  swap(curlevel_, rhs.curlevel_);
491  swap(curidx_, rhs.curidx_);
492  swap(firstblk_, rhs.firstblk_);
493  AllocType::_SwapNlistAlloc(rhs);
494  }
495  size_type size() const NLIB_NOEXCEPT {
496  return BlkBaseIdx(curlevel_) + curidx_;
497  }
498  size_type capacity() const NLIB_NOEXCEPT {
499  size_type lv;
500  return (nullptr != this->LastBlock(&lv)) ? BlkBaseIdx(lv + 1) : 0;
501  }
502  bool empty() const NLIB_NOEXCEPT { return curlevel_ == 0 && curidx_ == 0; }
503  bool resize(size_type n) NLIB_NOEXCEPT {
504  return Resize(n, typename IsTriviallyDefaultConstructible<T>::type());
505  }
506  bool reserve(size_type n) NLIB_NOEXCEPT;
507  pointer push_back() {
508  void* p = this->PushBack();
509  if (!p) return nullptr;
510  pointer ptr = MyCtor(p, typename IsTriviallyDefaultConstructible<T>::type()); // may throw
511  ++curidx_;
512  return ptr;
513  }
514 #ifdef __cpp_rvalue_references
515  pointer push_back(T&& rhs) NLIB_NOEXCEPT { // NOLINT
516 #if defined(NLIB_HAS_NATIVE_TYPETRAITS) && !defined(NLIB_HAS_TR1_TYPETRAITS)
517  NLIB_STATIC_ASSERT(std::is_nothrow_move_constructible<T>::value);
518 #endif
519  void* p = this->PushBack();
520  if (!p) return nullptr;
521  pointer ptr = new (p) T(std::forward<T>(rhs));
522  ++curidx_;
523  return ptr;
524  }
525 #endif
526  pointer push_back(const T& rhs) {
527  void* p = this->PushBack();
528  if (!p) return nullptr;
529  pointer ptr = new (p) T(rhs); // may throw
530  ++curidx_;
531  return ptr;
532  }
533  bool pop_back() NLIB_NOEXCEPT {
534  return this->pop_back_(typename IsTriviallyDestructible<T>::type());
535  }
536  void clear() NLIB_NOEXCEPT {
537  Clear(typename IsTriviallyDestructible<T>::type());
538  }
539  allocator_type get_allocator() const NLIB_NOEXCEPT {
540  return AllocType::_GetNlistAlloc();
541  }
542 
543  const_reference back() const {
544  if (curidx_ == 0) ConfirmBack();
545  return GetItem(curblk_)[curidx_ - 1];
546  }
547  reference back() {
548  if (curidx_ == 0) ConfirmBack();
549  return GetItem(curblk_)[curidx_ - 1];
550  }
551  const_reference front() const { return GetItem(firstblk_)[0]; }
552  reference front() { return GetItem(firstblk_)[0]; }
553  const_reference operator[](size_type idx) const {
554  NLIB_ASSERT(idx < this->size());
555  return *this->At(idx);
556  }
557  reference operator[](size_type idx) {
558  NLIB_ASSERT(idx < this->size());
559  return *this->At(idx);
560  }
561 
562  iterator begin() NLIB_NOEXCEPT {
563  if (!firstblk_ && !ConfirmFirstBlk()) return iterator();
564  return Begin();
565  }
566  const_iterator begin() const NLIB_NOEXCEPT {
567  if (!firstblk_ && !ConfirmFirstBlk()) return const_iterator();
568  return Begin();
569  }
570  const_iterator cbegin() const NLIB_NOEXCEPT {
571  if (!firstblk_ && !ConfirmFirstBlk()) return const_iterator();
572  return Begin();
573  }
574 
575  iterator end() NLIB_NOEXCEPT {
576  if (!firstblk_ && !ConfirmFirstBlk()) return iterator();
577  return End();
578  }
579  const_iterator end() const NLIB_NOEXCEPT {
580  if (!firstblk_ && !ConfirmFirstBlk()) return const_iterator();
581  return End();
582  }
583  const_iterator cend() const NLIB_NOEXCEPT {
584  if (!firstblk_ && !ConfirmFirstBlk()) return const_iterator();
585  return End();
586  }
587 
588  void shrink_to_fit() NLIB_NOEXCEPT {
589  if (!curblk_) return;
590  Blk* p = curblk_->next;
591  curblk_->next = nullptr;
592  DeallocBlkList(p, static_cast<int>(curlevel_ + 1));
593  }
594 #if defined(__cpp_rvalue_references) && defined(__cpp_variadic_templates)
595  template<class... Args>
596  pointer EmplaceBack(Args&&... args) {
597  void* p = this->PushBack();
598  if (!p) return nullptr;
599  pointer ptr = new (p) T(std::forward<Args>(args)...); // may throw
600  ++curidx_;
601  return ptr;
602  }
603 #else
604  template <class A1>
605  pointer EmplaceBack(const A1& a1) {
606  void* p = this->PushBack();
607  if (!p) return nullptr;
608  pointer ptr = new (p) T(const_cast<typename RemoveConst<A1>::type&>(a1));
609  ++curidx_;
610  return ptr;
611  }
612  template <class A1, class A2>
613  pointer EmplaceBack(const A1& a1, const A2& a2) {
614  void* p = this->PushBack();
615  if (!p) return nullptr;
616  pointer ptr = new (p) T(const_cast<typename RemoveConst<A1>::type&>(a1),
617  const_cast<typename RemoveConst<A2>::type&>(a2));
618  ++curidx_;
619  return ptr;
620  }
621  template <class A1, class A2, class A3>
622  pointer EmplaceBack(const A1& a1, const A2& a2, const A3& a3) {
623  void* p = this->PushBack();
624  if (!p) return nullptr;
625  pointer ptr = new (p) T(const_cast<typename RemoveConst<A1>::type&>(a1),
626  const_cast<typename RemoveConst<A2>::type&>(a2),
627  const_cast<typename RemoveConst<A3>::type&>(a3));
628  ++curidx_;
629  return ptr;
630  }
631  template <class A1, class A2, class A3, class A4>
632  pointer EmplaceBack(const A1& a1, const A2& a2, const A3& a3, const A4& a4) {
633  void* p = this->PushBack();
634  if (!p) return nullptr;
635  pointer ptr = new (p) T(const_cast<typename RemoveConst<A1>::type&>(a1),
636  const_cast<typename RemoveConst<A2>::type&>(a2),
637  const_cast<typename RemoveConst<A3>::type&>(a3),
638  const_cast<typename RemoveConst<A4>::type&>(a4));
639  ++curidx_;
640  return ptr;
641  }
642  template <class A1, class A2, class A3, class A4, class A5>
643  pointer
644  EmplaceBack(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) {
645  void* p = this->PushBack();
646  if (!p) return nullptr;
647  pointer ptr = new (p) T(const_cast<typename RemoveConst<A1>::type&>(a1),
648  const_cast<typename RemoveConst<A2>::type&>(a2),
649  const_cast<typename RemoveConst<A3>::type&>(a3),
650  const_cast<typename RemoveConst<A4>::type&>(a4),
651  const_cast<typename RemoveConst<A5>::type&>(a5));
652  ++curidx_;
653  return ptr;
654  }
655 #endif
656  void Clobber() NLIB_NOEXCEPT {
657  curblk_ = nullptr;
658  curlevel_ = 0;
659  curidx_ = 0;
660  firstblk_ = nullptr;
661  }
662 
663  private:
664  // The # of elements in the block increases as 8, 16, 32, 64, ....
665  Blk* AllocBlk(size_t n) const NLIB_NOEXCEPT;
666  void DeallocBlkList(Blk* p, int lv) const NLIB_NOEXCEPT;
667  void DestroyBlk(Blk*, size_t, TrueType) const NLIB_NOEXCEPT {}
668  void DestroyBlk(Blk* p, size_t n, FalseType) const NLIB_NOEXCEPT;
669  void DestroyBlk(Blk* p, size_t n) const NLIB_NOEXCEPT {
670  DestroyBlk(p, n, typename IsTriviallyDestructible<T>::type());
671  }
672  bool ConfirmFirstBlk() const NLIB_NOEXCEPT;
673  void* PushBack() NLIB_NOEXCEPT;
674  void Clear(FalseType) NLIB_NOEXCEPT;
675  void Clear(TrueType) NLIB_NOEXCEPT { ClearSimple(); }
676  bool Resize(size_t n, FalseType) NLIB_NOEXCEPT;
677  bool Resize(size_t n, TrueType) NLIB_NOEXCEPT;
678  T* MyCtor(void* p, TrueType) NLIB_NOEXCEPT {
679  return static_cast<T*>(p);
680  }
681  T* MyCtor(void* p, FalseType) {
682  T* ptr = new (p) T; // may throw
683  return ptr;
684  }
685  bool pop_back_(FalseType) NLIB_NOEXCEPT {
686  if (curidx_ == 0) {
687  if (!ConfirmBack()) return false;
688  }
689  reference item = GetItem(curblk_)[--curidx_];
690  NLIB_UNUSED(item);
691  item.~T();
692  return true;
693  }
694  bool pop_back_(TrueType) NLIB_NOEXCEPT {
695  if (curidx_ == 0) {
696  if (!ConfirmBack()) return false;
697  }
698  --curidx_;
699  return true;
700  }
701 
702  private:
704 };
705 
706 template <class T, class AL>
707 inline Nlist<T, AL>::~Nlist() NLIB_NOEXCEPT {
708  this->clear();
709  this->DeallocBlkList(firstblk_, 0);
710 }
711 
712 namespace nlist {
713 
714 template <class T, class AL>
715 class ResizeRewinder {
716  public:
717  ResizeRewinder(Nlist<T, AL>& l) NLIB_NOEXCEPT : count_(0), list_(l) {} // NOLINT
718  void PushBack(size_t n) {
719  for (; count_ < n; ++count_) {
720  list_.push_back(); // may throw in the default constructor of T
721  }
722  count_ = 0;
723  }
724  ~ResizeRewinder() NLIB_NOEXCEPT {
725  for (; count_ > 0; --count_) {
726  list_.pop_back();
727  }
728  }
729 
730  private:
731  size_t count_;
732  Nlist<T, AL>& list_;
733  NLIB_DISALLOW_COPY_AND_ASSIGN(ResizeRewinder);
734 };
735 
736 } // namespace nlist
737 
738 template <class T, class AL>
739 bool Nlist<T, AL>::Resize(size_t n, FalseType) NLIB_NOEXCEPT {
740  // NOTE: This can be optimized.
741  size_t sz = this->size();
742  if (n == sz) return true;
743  if (n < sz) {
744  for (size_t i = sz; i > n; --i) {
745  this->pop_back();
746  }
747  } else {
748  if (!this->reserve(n)) return false;
749  nlist::ResizeRewinder<T, AL> rewinder(*this);
750  rewinder.PushBack(n);
751  }
752  return true;
753 }
754 
755 template <class T, class AL>
756 bool Nlist<T, AL>::Resize(size_t n, TrueType) NLIB_NOEXCEPT {
757  size_type sz = this->size();
758  if (n == sz) return true;
759  if (n < sz) {
760  for (size_type i = sz; i > n; --i) {
761  this->pop_back();
762  }
763  } else {
764  if (!this->reserve(n)) return false;
765  // NOTE:
766  // Just set curlevel_, curblk_, curidx_
767  // because we don't have to invoke the constuctor of T.
768  size_t lower = this->BlkBaseIdx(curlevel_);
769  size_t upper = this->BlkBaseIdx(curlevel_ + 1);
770  while (upper > n) {
771  ++curlevel_;
772  curblk_ = curblk_->next;
773  lower = upper;
774  upper = this->BlkBaseIdx(curlevel_ + 1);
775  }
776  curidx_ = static_cast<size_t>(n - lower);
777  }
778  return true;
779 }
780 
781 template <class T, class AL>
782 bool Nlist<T, AL>::reserve(size_type n) NLIB_NOEXCEPT {
783  if (n == 0 || n <= BlkBaseIdx(curlevel_ + 1)) return true;
784  if (!firstblk_ && !this->ConfirmFirstBlk()) return false;
785  size_t lv;
786  Blk* blk = this->LastBlock(&lv);
787  for (;;) {
788  if (n <= BlkBaseIdx(lv + 1)) return true;
789  ++lv;
790  Blk* p = this->AllocBlk(BlkSize(lv));
791  if (!p) return false;
792  blk->next = p;
793  blk = p;
794  }
795 }
796 
797 template <class T, class AL>
798 typename Nlist<T, AL>::Blk* Nlist<T, AL>::AllocBlk(size_t n) const NLIB_NOEXCEPT {
799  NLIB_STATIC_ASSERT(NLIB_ALIGNOF(T) == 1 || NLIB_ALIGNOF(T) == 2 ||
800  NLIB_ALIGNOF(T) == 4 || NLIB_ALIGNOF(T) == 8);
801  NLIB_STATIC_ASSERT(sizeof(Blk) % 8 == 0);
802  size_t sz = sizeof(Blk) + n * sizeof(T);
803  void* pp;
804  NLIB_TRY {
805  pp = AllocType::_GetNlistAlloc().allocate(sz); // must be 8 bytes aligned
806  }
807 #ifdef __cpp_exceptions
808  NLIB_CATCH(const std::bad_alloc&) { return nullptr; }
809 #endif
810  if (!pp) return nullptr;
811  Blk* p = static_cast<Blk*>(pp);
812  p->next = nullptr;
813  p->item = reinterpret_cast<T*>(p + 1);
814  return p;
815 }
816 
817 template <class T, class AL>
818 void Nlist<T, AL>::DeallocBlkList(Blk* p, int lv) const NLIB_NOEXCEPT {
819  while (p) {
820  size_t n = BlkSize(lv);
821  Blk* pp = p;
822  p = pp->next;
823 
824  // DeallocBlock
825  AllocType::_GetNlistAlloc().deallocate(reinterpret_cast<char*>(pp),
826  sizeof(Blk) + n * sizeof(T));
827  ++lv;
828  }
829 }
830 
831 template <class T, class AL>
832 void Nlist<T, AL>::DestroyBlk(Blk* p, size_t n, FalseType) const NLIB_NOEXCEPT {
833  // NOTE:
834  // Do not use std::allocator::destroy() because destroy() is not required.
835  // invoke the destructor directly.
836  T* base = static_cast<T*>(p->item);
837  NLIB_UNUSED(base);
838  for (size_t i = 0; i < n; ++i) {
839  (base + i)->~T();
840  }
841 }
842 
843 template <class T, class AL>
844 bool Nlist<T, AL>::ConfirmFirstBlk() const NLIB_NOEXCEPT {
845  Blk* p = AllocBlk(BlkSize(0));
846  if (!p) return false;
847  firstblk_ = p;
848  curblk_ = p;
849  curidx_ = 0;
850  curlevel_ = 0;
851  return true;
852 }
853 
854 template <class T, class AL>
855 void* Nlist<T, AL>::PushBack() NLIB_NOEXCEPT {
856  if (!firstblk_ && !ConfirmFirstBlk()) return nullptr;
857  if (curidx_ == BlkSize(curlevel_)) {
858  if (!curblk_->next) {
859  Blk* p = AllocBlk(BlkSize(curlevel_ + 1));
860  if (!p) return nullptr;
861  curblk_->next = p;
862  }
863  ++curlevel_;
864  curblk_ = curblk_->next;
865  curidx_ = 0;
866  }
867 
868  // NOTE:
869  // If curidx_ is incremented here,
870  // The state will be inconsisitent when T's constructor throws an exception.
871  T& item = GetItem(curblk_)[curidx_];
872  return &item;
873 }
874 
875 template <class T, class AL>
876 void Nlist<T, AL>::Clear(FalseType) NLIB_NOEXCEPT {
877  int lv = 0;
878  Blk* p = firstblk_;
879  if (!p) return;
880  while (p != curblk_) {
881  size_t cnt = BlkSize(lv);
882  DestroyBlk(p, cnt);
883  ++lv;
884  p = p->next;
885  }
886  if (p == curblk_) {
887  DestroyBlk(p, curidx_);
888  }
889  ClearSimple();
890 }
891 
892 template <class T, class AL1, class AL2>
893 inline bool operator==(const Nlist<T, AL1>& lhs,
894  const Nlist<T, AL2>& rhs) NLIB_NOEXCEPT {
895  return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
896 }
897 
898 template <class T, class AL1, class AL2>
899 inline bool operator!=(const Nlist<T, AL1>& lhs,
900  const Nlist<T, AL2>& rhs) NLIB_NOEXCEPT {
901  return !(lhs == rhs);
902 }
903 
904 template <class T, class AL1, class AL2>
905 inline bool operator<(const Nlist<T, AL1>& lhs,
906  const Nlist<T, AL2>& rhs) NLIB_NOEXCEPT {
907  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
908 }
909 
910 template <class T, class AL1, class AL2>
911 inline bool operator>(const Nlist<T, AL1>& lhs,
912  const Nlist<T, AL2>& rhs) NLIB_NOEXCEPT {
913  return (rhs < lhs);
914 }
915 
916 template <class T, class AL1, class AL2>
917 inline bool operator<=(const Nlist<T, AL1>& lhs,
918  const Nlist<T, AL2>& rhs) NLIB_NOEXCEPT {
919  return (!(rhs < lhs));
920 }
921 
922 template <class T, class AL1, class AL2>
923 inline bool operator>=(const Nlist<T, AL1>& lhs,
924  const Nlist<T, AL2>& rhs) NLIB_NOEXCEPT {
925  return (!(lhs < rhs));
926 }
927 
928 template <class AL = std::allocator<char> >
929 class StringList {
930  typedef Nlist<char*, AL> ContainerType;
931 
932  public:
933  typedef AL allocator_type;
934  typedef typename ContainerType::iterator iterator;
935  typedef typename ContainerType::const_iterator const_iterator;
936 
937  public:
938  NLIB_DEPRECATED StringList() NLIB_NOEXCEPT : list_() {}
939  NLIB_DEPRECATED explicit StringList(const AL& al) : list_(al) {}
940  ~StringList() NLIB_NOEXCEPT;
941  size_t size() const NLIB_NOEXCEPT { return list_.size(); }
942  size_t capacity() const NLIB_NOEXCEPT { return list_.capacity(); }
943  bool empty() const NLIB_NOEXCEPT { return list_.empty(); }
944  bool reserve(size_t n) { return list_.reserve(n); }
945  bool resize(size_t n) { return list_.resize(n); }
946 
947  char** push_back(const char* str);
948  template <class Iterator>
949  char** push_back(Iterator first, Iterator last);
950 
951  bool pop_back() NLIB_NOEXCEPT;
952  NLIB_DEPRECATED void swap(StringList& rhs) NLIB_NOEXCEPT { list_.swap(rhs.list_); } // NOLINT
953  void clear() NLIB_NOEXCEPT { list_.clear(); }
954  allocator_type get_allocator() const { return list_.get_allocator(); }
955 
956  const char* back() const { return list_.back(); }
957  char* back() { return list_.back(); }
958  const char* front() const { return list_.front(); }
959  char* front() { return list_.front(); }
960  const char* operator[](size_t idx) const { return list_[idx]; }
961  char* operator[](size_t idx) { return list_[idx]; }
962  iterator begin() NLIB_NOEXCEPT { return list_.begin(); }
963  const_iterator begin() const NLIB_NOEXCEPT { return list_.begin(); }
964  const_iterator cbegin() NLIB_NOEXCEPT { return list_.cbegin(); }
965 
966  iterator end() NLIB_NOEXCEPT { return list_.end(); }
967  const_iterator end() const NLIB_NOEXCEPT { return list_.end(); }
968  const_iterator cend() NLIB_NOEXCEPT { return list_.cend(); }
969 
970  void shrink_to_fit() { list_.shrink_to_fit(); }
971  void Clobber() NLIB_NOEXCEPT { list_.clobber(); }
972 
973  char** Replace(iterator it, const char* str);
974  char** Replace(size_t idx, const char* str) {
975  if (idx >= list_.size()) return nullptr;
976  iterator it = list_.begin();
977  it.Advance(idx);
978  return this->Replace(it, str);
979  }
980 
981  private:
982  void Dealloc(const char* ptr) const {
983  if (ptr) {
984  // NOTE: note that size info is not supplied.
985  this->get_allocator().deallocate(const_cast<char*>(ptr), 0);
986  }
987  }
988  char* StrDup(const char* ptr) const;
989  char* Alloc(size_t nbytes) const {
990  return this->get_allocator().allocate(nbytes);
991  }
992 
993  private:
994  ContainerType list_;
995  NLIB_DISALLOW_COPY_AND_ASSIGN(StringList);
996 };
997 
998 template <class AL>
999 char* StringList<AL>::StrDup(const char* ptr) const {
1000  size_t nbytes = nlib_strlen(ptr) + 1;
1001  void* p = this->Alloc(nbytes);
1002  if (!p) return nullptr;
1003  nlib_memcpy(p, nbytes, ptr, nbytes);
1004  return reinterpret_cast<char*>(p);
1005 }
1006 
1007 template <class AL>
1008 StringList<AL>::~StringList() NLIB_NOEXCEPT {
1009  const_iterator it = this->cbegin();
1010  const_iterator it_end = this->cend();
1011  while (it != it_end) {
1012  Dealloc(*it);
1013  ++it;
1014  }
1015 }
1016 
1017 template <class AL>
1018 char** StringList<AL>::push_back(const char* str) {
1019  char* dup;
1020  if (str) {
1021  dup = this->StrDup(str);
1022  if (!dup) return nullptr;
1023  } else {
1024  dup = nullptr;
1025  }
1026  char** ptr_str = list_.push_back(dup);
1027  if (!ptr_str) this->Dealloc(dup);
1028  return ptr_str;
1029 }
1030 
1031 template <class AL>
1032 template <class Iterator>
1033 char** StringList<AL>::push_back(Iterator first, Iterator last) {
1034  typename std::iterator_traits<Iterator>::difference_type n = std::distance(first, last);
1035  char* str = this->Alloc(n + 1);
1036  if (!str) return nullptr;
1037  std::copy(first, last, str);
1038  str[n] = '\0';
1039  char** rval = list_.push_back(str);
1040  if (!rval) this->Dealloc(str);
1041  return rval;
1042 }
1043 
1044 template <class AL>
1045 bool StringList<AL>::pop_back() NLIB_NOEXCEPT {
1046  if (list_.empty()) return false;
1047  Dealloc(list_.back());
1048  return list_.pop_back();
1049 }
1050 
1051 template <class AL>
1052 char** StringList<AL>::Replace(iterator it, const char* str) {
1053  char* dup;
1054  if (str) {
1055  dup = this->StrDup(str);
1056  if (!dup) return nullptr;
1057  } else {
1058  dup = nullptr;
1059  }
1060  Dealloc(*it);
1061  *it = dup;
1062  return &*it;
1063 }
1064 
1065 template <class AL>
1066 bool AppendString(Nlist<char, AL>* obj, const char* str) {
1067  size_t n = nlib_strlen(str);
1068  if (!obj->reserve(obj->size() + n)) return false;
1069  while (*str) {
1070  obj->push_back(*str);
1071  ++str;
1072  }
1073  return true;
1074 }
1075 
1076 NLIB_NAMESPACE_END
1077 
1078 namespace std {
1079 
1080 template <class T, class Distance>
1081 inline void advance(::nlib_ns::nlist::NlistIterator<T>& pos, // NOLINT
1082  Distance n) {
1083  pos.Advance(static_cast<size_t>(n));
1084 }
1085 
1086 template <class T>
1087 inline std::ptrdiff_t distance(const ::nlib_ns::nlist::NlistIterator<T>& first,
1088  const ::nlib_ns::nlist::NlistIterator<T>& last) {
1089  return first.Distance(last);
1090 }
1091 
1092 } // namespace std
1093 
1094 
1095 NLIB_DEFINE_STD_SWAP_T_BEGIN2(nn, nlib) // NOLINT
1096 NLIB_DEFINE_STD_SWAP_T2(T, AL, NLIB_NS::Nlist) // NOLINT
1097 NLIB_DEFINE_STD_SWAP_T1(AL, NLIB_NS::StringList) // NOLINT
1098 NLIB_DEFINE_STD_SWAP_T_END2(nn, nlib) // NOLINT
1099 
1100 #endif // INCLUDE_NN_NLIB_NLIST_H_
Nlist(const AL &al) noexcept
Specifies an allocator. Creates an empty container.
Definition: Nlist.h:461
void swap(Nlist &rhs) noexcept
Swaps the container.
Definition: Nlist.h:487
BaseType::const_pointer const_pointer
const T*.
Definition: Nlist.h:455
pointer EmplaceBack(Args &&... args)
Adds elements in-place.
Definition: Nlist.h:596
reference back()
Returns a reference to the last element.
Definition: Nlist.h:547
BaseType::pointer pointer
T*.
Definition: Nlist.h:454
Substitute definitions for the C++11 standard header type_traits. These substitute definitions are us...
Nlist() noexcept
Instantiates the object with default parameters (default constructor). Creates an empty container...
Definition: Nlist.h:460
BaseType::reference reference
T&.
Definition: Nlist.h:452
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
Prohibits use of the copy constructor and assignment operator for the class specified by TypeName...
Definition: Config.h:179
bool operator>=(const Nlist< T, AL1 > &lhs, const Nlist< T, AL2 > &rhs) noexcept
Compares two lists in dictionary order.
Definition: Nlist.h:923
const_iterator begin() const noexcept
Returns the iterator pointing to the beginning of the container.
Definition: Nlist.h:566
Definition: Base64.h:25
BaseType::size_type size_type
Unsigned integer type (size_t).
Definition: Nlist.h:450
bool operator>(const Nlist< T, AL1 > &lhs, const Nlist< T, AL2 > &rhs) noexcept
Compares two lists in dictionary order.
Definition: Nlist.h:911
iterator begin() noexcept
Returns the iterator pointing to the beginning of the container.
Definition: Nlist.h:562
STL namespace.
void shrink_to_fit() noexcept
Returns allocated memory, if possible.
Definition: Nlist.h:588
allocator_type get_allocator() const noexcept
Gets the allocator.
Definition: Nlist.h:539
const_reference back() const
The same as back.
Definition: Nlist.h:543
const_iterator end() const noexcept
Returns the iterator pointing to the end of the container.
Definition: Nlist.h:579
bool operator==(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are equal.
Definition: NMalloc.h:149
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are not equal.
Definition: NMalloc.h:154
#define NLIB_DEPRECATED
Indicates that a function or something has been deprecated.
Definition: Config.h:109
BaseType::const_iterator const_iterator
Read-only forward iterator.
Definition: Nlist.h:457
#define NLIB_VIS_PUBLIC
Symbols for functions and classes are made available outside of the library.
Definition: Platform_unix.h:89
Nlist & operator=(Nlist &&rhs) noexcept
Move assignment operator. This function is useful when using C++11.
Definition: Nlist.h:470
Object created when MessagePack or JSON is read.
Definition: MpObject.h:95
size_type capacity() const noexcept
Returns the number of allocated elements.
Definition: Nlist.h:498
bool resize(size_type n) noexcept
Resizes the container.
Definition: Nlist.h:503
pointer push_back()
Adds an element to the end and initializes it with the default constructor.
Definition: Nlist.h:507
reference operator[](size_type idx)
Uses an index to reference an element.
Definition: Nlist.h:557
Nlist(Nlist &rhs, move_tag) noexcept
Corresponds to a move constructor.
Definition: Nlist.h:478
An empty structure indicating that an argument to a function needs to be moved.
Definition: Config.h:265
void clear() noexcept
Clears the container.
Definition: Nlist.h:536
#define NLIB_CATCH(x)
Defines catch(x) if exceptions are enabled. If not, defines if (true).
Definition: Config.h:143
static errno_t nlib_memcpy(void *s1, size_t s1max, const void *s2, size_t n)
An implementation corresponding to N1078 memcpy_s.
Definition: Platform.h:2437
#define NLIB_TRY
Defines try if exceptions are enabled. If not, defines if (true).
Definition: Config.h:142
Nlist & assign(Nlist &rhs, move_tag) noexcept
Corresponds to a move assignment operator.
Definition: Nlist.h:480
reference front()
Returns a reference to the first element.
Definition: Nlist.h:552
BaseType::iterator iterator
Forward iterator.
Definition: Nlist.h:456
BaseType::difference_type difference_type
Signed integer type (ptrdiff_t).
Definition: Nlist.h:451
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:105
BaseType::value_type value_type
Element type T.
Definition: Nlist.h:448
#define NLIB_CEXPR
Defines constexpr if it is available for use. If not, holds an empty string.
Definition: Config.h:107
A file that contains the configuration information for each development environment.
TimeSpan operator*(int i, const TimeSpan &rhs) noexcept
Increases rhs by a factor of i.
Definition: DateTime.h:210
bool reserve(size_type n) noexcept
Allocates memory for n number of elements.
Definition: Nlist.h:782
void Clobber() noexcept
Returns the container empty without calling the element destructor and without releasing the memory f...
Definition: Nlist.h:656
A container-like class similar to std::vector that can store objects that do not have copy constructo...
Definition: Nlist.h:32
const_reference front() const
The same as front.
Definition: Nlist.h:551
const_iterator cend() const noexcept
Returns the iterator pointing to the end of the container.
Definition: Nlist.h:583
size_type size() const noexcept
Returns the number of stored elements.
Definition: Nlist.h:495
size_t nlib_strlen(const char *s)
Internally calls strlen(). In some cases, it may operate as an independent implementation.
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
Definition: Config.h:245
#define NLIB_STATIC_ASSERT(exp)
Defines a static assertion. Uses static_assert if it is available for use.
Definition: Config.h:170
bool empty() const noexcept
Checks whether the container is empty.
Definition: Nlist.h:502
const_reference operator[](size_type idx) const
The same as operator[](size_t idx).
Definition: Nlist.h:553
#define NLIB_ALIGNOF(tp)
Defines alignof(tp) or the equivalent.
Definition: Config.h:256
std::allocator< char > allocator_type
Allocator type AL.
Definition: Nlist.h:449
BaseType::reference const_reference
const T&.
Definition: Nlist.h:453
const_iterator cbegin() const noexcept
Returns the iterator pointing to the beginning of the container.
Definition: Nlist.h:570
iterator end() noexcept
Returns the iterator pointing to the end of the container.
Definition: Nlist.h:575
bool pop_back() noexcept
Deletes the last element.
Definition: Nlist.h:533