Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

with_capacity.hpp
Go to the documentation of this file.
1 //
2 // immer: immutable data structures for C++
3 // Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
4 //
5 // This software is distributed under the Boost Software License, Version 1.0.
6 // See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
7 //
8 
9 #pragma once
10 
12 
13 namespace immer {
14 namespace detail {
15 namespace arrays {
16 
17 template <typename T, typename MemoryPolicy>
19 {
21 
23  using edit_t = typename MemoryPolicy::transience_t::edit;
24  using size_t = std::size_t;
25 
27  size_t size;
28  size_t capacity;
29 
30  static const with_capacity& empty()
31  {
32  static const with_capacity empty_ {
33  node_t::make_n(1),
34  0,
35  1
36  };
37  return empty_;
38  }
39 
40  with_capacity(node_t* p, size_t s, size_t c)
41  : ptr{p}, size{s}, capacity{c}
42  {}
43 
45  : with_capacity{other.ptr, other.size, other.capacity}
46  {
47  inc();
48  }
49 
51  : with_capacity{other.ptr, other.size, other.size}
52  {
53  inc();
54  }
55 
57  : with_capacity{empty()}
58  {
59  swap(*this, other);
60  }
61 
63  {
64  auto next = other;
65  swap(*this, next);
66  return *this;
67  }
68 
70  {
71  swap(*this, other);
72  return *this;
73  }
74 
75  friend void swap(with_capacity& x, with_capacity& y)
76  {
77  using std::swap;
78  swap(x.ptr, y.ptr);
79  swap(x.size, y.size);
80  swap(x.capacity, y.capacity);
81  }
82 
84  {
85  dec();
86  }
87 
88  void inc()
89  {
90  using immer::detail::get;
91  ptr->refs().inc();
92  }
93 
94  void dec()
95  {
96  using immer::detail::get;
97  if (ptr->refs().dec())
99  }
100 
101  const T* data() const { return ptr->data(); }
102  T* data() { return ptr->data(); }
103 
104  operator no_capacity_t() const
105  {
106  if (size == capacity) {
107  ptr->refs().inc();
108  return { ptr, size };
109  } else {
110  return { node_t::copy_n(size, ptr, size), size };
111  }
112  }
113 
114  template <typename Iter, typename Sent,
115  std::enable_if_t
116  <is_forward_iterator_v<Iter>
117  && compatible_sentinel_v<Iter, Sent>, bool> = true>
118  static with_capacity from_range(Iter first, Sent last)
119  {
120  auto count = static_cast<size_t>(distance(first, last));
121  return {
122  node_t::copy_n(count, first, last),
123  count,
124  count
125  };
126  }
127 
128  template <typename U>
129  static with_capacity from_initializer_list(std::initializer_list<U> values)
130  {
131  using namespace std;
132  return from_range(begin(values), end(values));
133  }
134 
135  static with_capacity from_fill(size_t n, T v)
136  {
137  return { node_t::fill_n(n, v), n, n };
138  }
139 
140  template <typename Fn>
141  void for_each_chunk(Fn&& fn) const
142  {
143  std::forward<Fn>(fn)(data(), data() + size);
144  }
145 
146  template <typename Fn>
147  bool for_each_chunk_p(Fn&& fn) const
148  {
149  return std::forward<Fn>(fn)(data(), data() + size);
150  }
151 
152  const T& get(std::size_t index) const
153  {
154  return data()[index];
155  }
156 
157  const T& get_check(std::size_t index) const
158  {
159  if (index >= size)
160  throw std::out_of_range{"out of range"};
161  return data()[index];
162  }
163 
164  bool equals(const with_capacity& other) const
165  {
166  return ptr == other.ptr ||
167  (size == other.size &&
168  std::equal(data(), data() + size, other.data()));
169  }
170 
171  static size_t recommend_up(size_t sz, size_t cap)
172  {
173  auto max = std::numeric_limits<size_t>::max();
174  return
175  sz <= cap ? cap :
176  cap >= max / 2 ? max
177  /* otherwise */ : std::max(2 * cap, sz);
178  }
179 
180  static size_t recommend_down(size_t sz, size_t cap)
181  {
182  return sz == 0 ? 1 :
183  sz < cap / 2 ? sz * 2 :
184  /* otherwise */ cap;
185  }
186 
187  with_capacity push_back(T value) const
188  {
189  auto cap = recommend_up(size + 1, capacity);
190  auto p = node_t::copy_n(cap, ptr, size);
191  try {
192  new (p->data() + size) T{std::move(value)};
193  return { p, size + 1, cap };
194  } catch (...) {
195  node_t::delete_n(p, size, cap);
196  throw;
197  }
198  }
199 
200  void push_back_mut(edit_t e, T value)
201  {
202  if (ptr->can_mutate(e) && capacity > size) {
203  new (data() + size) T{std::move(value)};
204  ++size;
205  } else {
206  auto cap = recommend_up(size + 1, capacity);
207  auto p = node_t::copy_e(e, cap, ptr, size);
208  try {
209  new (p->data() + size) T{std::move(value)};
210  *this = { p, size + 1, cap };
211  } catch (...) {
212  node_t::delete_n(p, size, cap);
213  throw;
214  }
215  }
216  }
217 
218  with_capacity assoc(std::size_t idx, T value) const
219  {
220  auto p = node_t::copy_n(capacity, ptr, size);
221  try {
222  p->data()[idx] = std::move(value);
223  return { p, size, capacity };
224  } catch (...) {
226  throw;
227  }
228  }
229 
230  void assoc_mut(edit_t e, std::size_t idx, T value)
231  {
232  if (ptr->can_mutate(e)) {
233  data()[idx] = std::move(value);
234  } else {
235  auto p = node_t::copy_n(capacity, ptr, size);
236  try {
237  p->data()[idx] = std::move(value);
238  *this = { p, size, capacity };
239  } catch (...) {
241  throw;
242  }
243  }
244  }
245 
246  template <typename Fn>
247  with_capacity update(std::size_t idx, Fn&& op) const
248  {
249  auto p = node_t::copy_n(capacity, ptr, size);
250  try {
251  auto& elem = p->data()[idx];
252  elem = std::forward<Fn>(op)(std::move(elem));
253  return { p, size, capacity };
254  } catch (...) {
256  throw;
257  }
258  }
259 
260  template <typename Fn>
261  void update_mut(edit_t e, std::size_t idx, Fn&& op)
262  {
263  if (ptr->can_mutate(e)) {
264  auto& elem = data()[idx];
265  elem = std::forward<Fn>(op)(std::move(elem));
266  } else {
267  auto p = node_t::copy_e(e, capacity, ptr, size);
268  try {
269  auto& elem = p->data()[idx];
270  elem = std::forward<Fn>(op)(std::move(elem));
271  *this = { p, size, capacity };
272  } catch (...) {
274  throw;
275  }
276  }
277  }
278 
280  {
281  auto cap = recommend_down(sz, capacity);
282  auto p = node_t::copy_n(cap, ptr, sz);
283  return { p, sz, cap };
284  }
285 
287  {
288  if (ptr->can_mutate(e)) {
289  destroy_n(data() + size, size - sz);
290  size = sz;
291  } else {
292  auto cap = recommend_down(sz, capacity);
293  auto p = node_t::copy_e(e, cap, ptr, sz);
294  *this = { p, sz, cap };
295  }
296  }
297 };
298 
299 } // namespace arrays
300 } // namespace detail
301 } // namespace immer
static node_t * copy_n(size_t n, Iter first, Sent last)
Definition: node.hpp:99
typename MemoryPolicy::transience_t::edit edit_t
void destroy_n(T *p, Size n)
Definition: util.hpp:52
with_capacity assoc(std::size_t idx, T value) const
void push_back_mut(edit_t e, T value)
friend void swap(with_capacity &x, with_capacity &y)
std::iterator_traits< Iterator >::difference_type distance(Iterator first, Sentinel last)
Definition: util.hpp:141
with_capacity(node_t *p, size_t s, size_t c)
no_capacity< T, MemoryPolicy > no_capacity_t
static node_t * fill_n(size_t n, T v)
Definition: node.hpp:84
bool can_mutate(edit_t e) const
Definition: node.hpp:59
const T & get_check(std::size_t index) const
Definition: box.hpp:161
static node_t * make_n(size_t n)
Definition: node.hpp:72
with_capacity push_back(T value) const
bool equals(const with_capacity &other) const
void take_mut(edit_t e, std::size_t sz)
static size_t recommend_down(size_t sz, size_t cap)
void assoc_mut(edit_t e, std::size_t idx, T value)
static size_t recommend_up(size_t sz, size_t cap)
std::size_t size_t
Definition: bits.hpp:21
static void delete_n(node_t *p, size_t sz, size_t cap)
Definition: node.hpp:65
with_capacity(const with_capacity &other)
with_capacity update(std::size_t idx, Fn &&op) const
static with_capacity from_fill(size_t n, T v)
static const with_capacity & empty()
with_capacity take(std::size_t sz) const
static with_capacity from_range(Iter first, Sent last)
with_capacity(const no_capacity_t &other)
void update_mut(edit_t e, std::size_t idx, Fn &&op)
with_capacity & operator=(const with_capacity &other)
static node_t * copy_e(edit_t e, size_t n, Iter first, Iter last)
Definition: node.hpp:117
static int count
Definition: tests.c:45
with_capacity(with_capacity &&other)
const T * data() const
Definition: node.hpp:56
static with_capacity from_initializer_list(std::initializer_list< U > values)
with_capacity & operator=(with_capacity &&other)
refs_t & refs() const
Definition: node.hpp:48
Released under the MIT license