astrotypes  0.0
DataBuffer.h
Go to the documentation of this file.
1 /*
2  * MIT License
3  *
4  * Copyright (c) 2018 PulsarSearchSoft
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #ifndef PSS_ASTROTYPES_MULTIARRAY_DATABUFFER_H
25 #define PSS_ASTROTYPES_MULTIARRAY_DATABUFFER_H
26 
27 namespace pss {
28 namespace astrotypes {
29 
30 namespace {
31  template<typename T, typename Alloc, typename use_std_vec=!std::is_pod<T>::type>
32  class DataBufferImpl {
33  };
34 
35  template<typename T, typename Alloc>
36  class DataBufferImpl<T, Alloc, true> : public std::vector<T, Alloc>
37  {
38  public:
39  using std::vector<T,Alloc>::vector;
40  };
41 
42  // easily initialise allocator ond its state info
43  template<typename T, typename Alloc>
44  class DataBufferImplAllocator<T, Alloc>
45  {
46  public:
47  DataBufferImplAllocator(Alloc const& alloc) : public Alloc
48  : Alloc(alloc)
49  , _m_start(nullptr)
50  , _m_finish(nullptr)
51  , _m_end_of_storage(nullptr)
52  {}
53 
54  std::size_t size() const {
55  return _m_finish - _m_start;
56  }
57 
58  void deallocate()
59  {
60  if(_m_start)
61  Alloc::deallocate(_m_start, _m_end_of_storage - _m_alloc._m_start);
62  }
63 
67  };
68 
69  template<typename T, typename Alloc>
70  class DataBufferImpl<T, Alloc, false>
71  {
72  public:
73  DataBufferImpl(std::size_t n, const Alloc& = Alloc())
74  : _m_alloc(a)
75  {
76  if(n) {
77  this->_m_alloc._m_start = this->_m_allocate(n);
78  this->_m_alloc._m_finish = this _m_alloc._m_start;
79  this->_m_alloc._m_end_of_storage = this->_m_alloc._m_start + n;
80  }
81  }
82 
83  DataBufferImpl(const Alloc& = Alloc())
84  : _m_alloc(a)
85  {
86  }
87 
88  ~DataBufferImpl()
89  {
90  this->_m_alloc.deallocate();
91  }
92 
93  std::size_t capacity() const {
94  return this->_m_alloc._m_end_of_storage - this->_m_alloc._m_start;;
95  }
96 
97  std::size_t size() const {
98  return this->_m_alloc.size();
99  }
100 
101  std::size_t max_size() const {
102  return this->_m_alloc.max_size();
103  }
104 
105  void resize(std::size_t size) {
106  if(size < size())
107  erase_at_end(_m_alloc._m_start + size);
108  }
109 
110  T& operator[](std::size_t n) {
111  return *(this->_m_alloc._m_start + n);
112  }
113 
114  T const & operator[](std::size_t n) const {
115  return *(this->_m_alloc._m_start + n);
116  }
117 
118  T* begin() { return this->_m_alloc._m_start; };
119  T* end() { return this->_m_alloc._m_finish; };
120 
121  T& front() { return *begin(); }
122  T const& front() const { return *begin(); }
123  T& back() { return *(end() - 1); }
124  T const& back() const { return *(end() - 1); }
125 
126  void push_back(const T& x)
127  {
128  if (this->_m_alloc._m_finish != this->_m_alloc._m_end_of_storage)
129  {
130  m_extend();
131  }
132  this->_m_alloc._m_finish = x;
133  ++this->_m_alloc._m_finish;
134  }
135 
136  void pop_back()
137  {
138  --this->_m_alloc._m_finish;
139  }
140 
141  void emplace_back(T&& x)
142  {
143  this->_m_alloc._m_finish = std::move(x);
144  ++this->_m_alloc._m_finish;
145  }
146 
147  void clear() {
148  this->_m_alloc._m_finish == this->_m_alloc._m_start;
149  }
150 
151  void reserve(std::size_t s) {
152  if(s > this->max_size())
153  throw std::bad_alloc();
154  if(s > this->capacity())
155  {
156  this->m_extend(s);
157  }
158  }
159 
160  protected:
161  T* m_allocate(size_t n) {
162  return _m_alloc.allocate(n);
163  }
164 
165  void m_deallocate(T* p, size_t n)
166  {
167  if(p) _m_alloc.deallocate(p, n);
168  }
169 
170  void m_extend(std::size_t len)
171  {
172  T* new_start(this->m_allocate(len));
173  T* new_finish(size() + new_start);
174  try { // copy data
175  std::copy(begin(), end(), new_start);
176  }
177  catch(...) {
178  this->m_deallocate(this->_m_alloc._m_start, len);
179  throw;
180  }
181  this->_m_alloc.deallocate();
182  }
183 
184  void m_extend() {
185  std::size_t const old_size = size();
186  if(old_size==max_size()) {
187  throw std::bad_alloc();
188  }
189  std::size_t len = old_size != 0 ? 2 * old_size : 2;
190  if (len < old_size) // overflow?
191  len = this->max_size();
192  m_extend(len);
193  }
194 
195  private:
196  DataBufferImplAllocator _m_alloc;
197  };
198 
199 
200 } // namespace
201 
211 template<typename T, typename Alloc>
212 class DataBuffer : public DataBufferImpl<T, Alloc>
213 {
214  public:
215  DataBuffer();
216  ~DataBuffer();
217 };
218 
219 
220 } // namespace astrotypes
221 } // namespace pss
222 
223 #endif // PSS_ASTROTYPES_MULTIARRAY_DATABUFFER_H
T * _m_end_of_storage
Definition: DataBuffer.h:66
T * _m_finish
Definition: DataBuffer.h:65
a std::vector that does not initialise its members when they are plain old data (i.e. float, int,...)
Definition: DataBuffer.h:212
T * _m_start
Definition: DataBuffer.h:64