19 #include <type_traits>
32 #if !ISOSPEC_BUILDING_R
33 static_assert(std::is_trivially_copyable<T>::value,
"Cannot use a pod_vector with a non-Plain Old Data type.");
43 store =
reinterpret_cast<T*
>(malloc(
sizeof(T) * initial_size));
45 throw std::bad_alloc();
47 backend_past_end = store + initial_size;
55 backend_past_end = other.backend_past_end;
56 first_free = other.first_free;
58 other.backend_past_end = other.first_free = other.store = NULL;
65 backend_past_end = other.backend_past_end;
66 first_free = other.first_free;
70 void fast_reserve(
size_t n)
72 ISOSPEC_IMPOSSIBLE(n <
static_cast<size_t>(backend_past_end - store));
73 T* new_store =
reinterpret_cast<T*
>(realloc(store, n *
sizeof(T)));
75 throw std::bad_alloc();
76 first_free = new_store + (first_free - store);
77 backend_past_end = new_store + n;
81 void reserve(
size_t n)
83 if (n >
static_cast<size_t>(backend_past_end - store))
87 ISOSPEC_FORCE_INLINE
void nocheck_push_back(
const T& val) noexcept
89 ISOSPEC_IMPOSSIBLE(first_free >= backend_past_end);
94 ISOSPEC_FORCE_INLINE
void push_back(
const T& val)
96 if(first_free >= backend_past_end)
97 fast_reserve((std::max<std::ptrdiff_t>)(4, (backend_past_end-store)) * 2);
102 ISOSPEC_FORCE_INLINE T& operator[](
size_t n) noexcept
104 ISOSPEC_IMPOSSIBLE(store + n >= first_free);
108 ISOSPEC_FORCE_INLINE
const T& operator[](
size_t n)
const noexcept
110 ISOSPEC_IMPOSSIBLE(store + n >= first_free);
114 ISOSPEC_FORCE_INLINE
size_t size()
const noexcept
116 return first_free - store;
119 ISOSPEC_FORCE_INLINE
size_t capacity()
const noexcept
121 return backend_past_end - store;
124 ISOSPEC_FORCE_INLINE T* data() noexcept
129 ISOSPEC_FORCE_INLINE
const T* data()
const noexcept
134 ISOSPEC_FORCE_INLINE
bool empty()
const noexcept
136 return first_free == store;
139 ISOSPEC_FORCE_INLINE
const T& back()
const noexcept
141 ISOSPEC_IMPOSSIBLE(first_free > backend_past_end);
142 return *(first_free-1);
145 ISOSPEC_FORCE_INLINE
void pop_back() noexcept
148 ISOSPEC_IMPOSSIBLE(first_free == store);
154 std::swap(backend_past_end, other.backend_past_end);
155 std::swap(first_free, other.first_free);
156 std::swap(store, other.store);
160 typedef const T* const_iterator;
161 typedef T value_type;
162 typedef size_t size_type;
163 typedef T& reference;
164 typedef const T& const_reference;
166 iterator begin() noexcept {
return store; };
167 const_iterator begin()
const noexcept {
return store; }
168 const_iterator cbegin()
const noexcept {
return store; }
169 iterator end() noexcept {
return first_free; }
170 const_iterator end()
const noexcept {
return first_free; }
171 const_iterator cend()
const noexcept {
return first_free; }
173 ISOSPEC_FORCE_INLINE
const T& front()
const noexcept
175 ISOSPEC_IMPOSSIBLE(store == first_free);
182 first_free = store = backend_past_end = NULL;
191 #if !ISOSPEC_BUILDING_R
192 static_assert(std::is_trivially_copyable<T>::value,
"Cannot use a pod_vector with a non-Plain Old Data type.");
193 static_assert(std::is_trivially_copyable<
unsafe_pod_vector<T> >::value,
"Cannot use a pod_vector with a non-Plain Old Data type.");
203 void init() { memset(
this, 0,
sizeof(*
this)); }
205 void init(
size_t initial_size)
207 store =
reinterpret_cast<T*
>(malloc(
sizeof(T) * initial_size));
209 throw std::bad_alloc();
211 backend_past_end = store + initial_size;
219 memcpy(
this, *other,
sizeof(*
this));
224 void free() { free(store); }
226 void fast_reserve(
size_t n)
228 ISOSPEC_IMPOSSIBLE(n <
static_cast<size_t>(backend_past_end - store));
229 T* new_store =
reinterpret_cast<T*
>(realloc(store, n *
sizeof(T)));
230 if(new_store == NULL)
231 throw std::bad_alloc();
232 first_free = new_store + (first_free - store);
233 backend_past_end = new_store + n;
237 void reserve(
size_t n)
239 if (n > backend_past_end - store)
243 void resize(
size_t new_size)
245 ISOSPEC_IMPOSSIBLE(new_size < first_free - store);
246 size_t cap = capacity();
251 }
while(cap < new_size);
254 first_free = store + new_size;
257 void resize_and_wipe(
size_t new_size)
259 size_t old_size = size();
260 ISOSPEC_IMPOSSIBLE(new_size < old_size);
262 memset(store+old_size, 0, (new_size-old_size) *
sizeof(T));
265 ISOSPEC_FORCE_INLINE
void nocheck_push_back(
const T& val) noexcept
267 ISOSPEC_IMPOSSIBLE(first_free >= backend_past_end);
272 ISOSPEC_FORCE_INLINE
void push_back(
const T& val)
274 if(first_free >= backend_past_end)
275 fast_reserve((std::max<std::ptrdiff_t>)(4, (backend_past_end-store)) * 2);
280 ISOSPEC_FORCE_INLINE T& operator[](
size_t n) noexcept
282 ISOSPEC_IMPOSSIBLE(store + n >= first_free);
286 ISOSPEC_FORCE_INLINE
const T& operator[](
size_t n)
const noexcept
288 ISOSPEC_IMPOSSIBLE(store + n >= first_free);
292 ISOSPEC_FORCE_INLINE
size_t size() const noexcept
294 return first_free - store;
297 ISOSPEC_FORCE_INLINE
size_t capacity() const noexcept
299 return backend_past_end - store;
302 ISOSPEC_FORCE_INLINE T* data() noexcept
307 ISOSPEC_FORCE_INLINE
const T* data() const noexcept
312 ISOSPEC_FORCE_INLINE
bool empty() const noexcept
314 return first_free == store;
317 ISOSPEC_FORCE_INLINE
const T& back() const noexcept
319 ISOSPEC_IMPOSSIBLE(first_free > backend_past_end);
320 return *(first_free-1);
323 ISOSPEC_FORCE_INLINE
void pop_back() noexcept
326 ISOSPEC_IMPOSSIBLE(first_free == store);
332 std::swap(backend_past_end, other.backend_past_end);
333 std::swap(first_free, other.first_free);
334 std::swap(store, other.store);
338 typedef const T* const_iterator;
339 typedef T value_type;
340 typedef size_t size_type;
341 typedef T& reference;
342 typedef const T& const_reference;
344 iterator begin() noexcept {
return store; };
345 const_iterator begin() const noexcept {
return store; }
346 const_iterator cbegin() const noexcept {
return store; }
347 iterator end() noexcept {
return first_free; }
348 const_iterator end() const noexcept {
return first_free; }
349 const_iterator cend() const noexcept {
return first_free; }
351 ISOSPEC_FORCE_INLINE
const T& front() const noexcept
353 ISOSPEC_IMPOSSIBLE(store == first_free);
360 first_free = store = backend_past_end = NULL;