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