Lumiera  0.pre.03
»edit your freedom«
several.hpp
Go to the documentation of this file.
1 /*
2  SEVERAL.hpp - abstraction providing a limited fixed number of elements
3 
4  Copyright (C)
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6  2024, Hermann Vosseler <Ichthyostega@web.de>
7 
8   **Lumiera** is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2 of the License, or (at your
11   option) any later version. See the file COPYING for further details.
12 
13 */
14 
15 
50 #ifndef LIB_SEVERAL_H
51 #define LIB_SEVERAL_H
52 
53 
54 #include "lib/nocopy.hpp"
55 #include "lib/index-iter.hpp"
56 
57 #include <cstddef>
58 #include <functional>
59 
60 
61 namespace lib {
62 
63  namespace several {// Storage header implementation details
64 
70  template<class TAR>
72  {
73  std::function<void(TAR*)> dtor_{};
74 
75  public:
76  template<class FUN>
77  void
78  installDestructor (FUN&& dtor)
79  {
80  dtor_ = std::forward<FUN> (dtor);
81  }
82 
84  {
85  if (isArmed())
86  {
87  auto destructionFun = std::move(dtor_);
88  ENSURE (not dtor_);
89  destructionFun (target());
90  }
91  }
92 
93  bool isArmed() const { return bool(dtor_); }
94  auto getDtor() const { return dtor_; }
95  void destroy() { target()->~TAR(); }
96  TAR* target() { return static_cast<TAR*>(this); }
97  };
98 
104  template<class I>
105  struct ArrayBucket
106  : SelfDestructor<ArrayBucket<I>>
107  {
108  ArrayBucket (size_t storageSize, size_t buffStart, size_t elmSize = sizeof(I))
109  : cnt{0}
110  , spread{elmSize}
111  , buffSiz{storageSize - buffStart}
112  , buffOffset{buffStart}
113  { }
114 
115  using Deleter = std::function<void(ArrayBucket*)>;
116 
117  size_t cnt;
118  size_t spread;
119  size_t buffSiz;
120  size_t buffOffset;
121 
122  static constexpr size_t storageOffset = sizeof(ArrayBucket);
123  size_t getAllocSize() const { return buffOffset +buffSiz; }
124 
125 
127  std::byte*
129  {
130  return reinterpret_cast<std::byte*>(this) + buffOffset;
131  }
132 
134  I&
135  subscript (size_t idx)
136  {
137  std::byte* elm = storage() + (idx * spread);
138  ENSURE (storage() <= elm and elm < storage()+buffSiz);
139  return * std::launder (reinterpret_cast<I*> (elm));
140  }
141 
142  };
143 
144  }//(End)implementation details
145 
146 
147 
148  /************************************************/
155  template<class I>
156  class Several
158  {
159  protected:
161 
162  Bucket data_{nullptr};
163 
164  public:
165  Several() =default;
166 
167  ~Several() noexcept
168  try { if (data_) data_->destroy(); }
169  ERROR_LOG_AND_IGNORE (progress, "clean-up Several data")
170 
171 
173  {
174  std::swap (data_, rr.data_);
175  }
176  Several& operator= (Several&& rr)
177  {
178  std::swap (data_, rr.data_);
179  return *this;
180  }
181 
182  size_t
183  size() const
184  {
185  return data_? data_->cnt : 0;
186  }
187 
188  bool
189  empty() const
190  {
191  return not data_;
192  }
193 
194  I&
195  operator[] (size_t idx)
196  {
197  REQUIRE (data_);
198  return data_->subscript (idx);
199  }
200 
201  I const&
202  operator[] (size_t idx) const
203  {
204  return const_cast<Several&>(*this).operator[] (idx);
205  }
206 
207  I& front() { return operator[] (0); }
208  I& back() { return operator[] (data_? data_->cnt-1 : 0); }
209 
212 
213  iterator begin() { return iterator{*this}; }
214  iterator end() { return iterator{}; }
215  const_iterator begin() const { return const_iterator{*this};}
216  const_iterator end() const { return const_iterator{}; }
217 
218  friend auto begin (Several& svl) { return svl.begin();}
219  friend auto end (Several& svl) { return svl.end(); }
220  friend auto begin (Several const& svl) { return svl.begin();}
221  friend auto end (Several const& svl) { return svl.end(); }
222 
223 
224  protected:
225  size_t
226  spread() const
227  {
228  return data_? data_->spread : sizeof(I);
229  }
230 
231  size_t
232  storageBuffSiz() const
233  {
234  return data_? data_->buffSiz : 0;
235  }
236 
237  bool
238  hasReserve (size_t requiredSize, size_t newElms =1) const
239  {
240  if (requiredSize < spread())
241  requiredSize = spread();
242  size_t extraSize{requiredSize * newElms};
243  if (requiredSize > spread())
244  extraSize += (requiredSize - spread())*size();
245  return data_
246  and data_->buffSiz >= size()*spread() + extraSize;
247  }
248  };
249 
250 
251 } // namespace lib
252 #endif
Types marked with this mix-in may be moved and move-assigned.
Definition: nocopy.hpp:63
I & subscript(size_t idx)
perform unchecked access into the storage area
Definition: several.hpp:135
#define ERROR_LOG_AND_IGNORE(_FLAG_, _OP_DESCR_)
convenience shortcut for a sequence of catch blocks just logging and consuming an error...
Definition: error.hpp:266
Metadata record placed immediately before the data storage.
Definition: several.hpp:105
Implementation namespace for support and library code.
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Abstraction: Fixed array of elements.
Definition: several.hpp:156
Iterator-style access handle to a referred container with subscript index.
Subscript-index based access to a container, packaged as iterator.
Definition: index-iter.hpp:112
std::byte * storage()
data storage area starts immediately behind the ArrayBucket
Definition: several.hpp:128