117 lines
2.9 KiB
C++
117 lines
2.9 KiB
C++
//
|
|
// A vector class without default-initialization, for "plain old data"
|
|
//
|
|
// Copyright (C) 2016-2021 Andreas Gustafsson. This file is part of
|
|
// the Gaborator library source distribution. See the file LICENSE at
|
|
// the top level of the distribution for license information.
|
|
//
|
|
|
|
#ifndef _GABORATOR_POD_VECTOR_H
|
|
#define _GABORATOR_POD_VECTOR_H
|
|
|
|
#include <stdlib.h> // size_t
|
|
|
|
#include <algorithm> // std::swap
|
|
|
|
namespace gaborator {
|
|
|
|
// A vector for storing Plain Old Data. This is similar to a
|
|
// std::vector, except that it does not zero-initialize elements,
|
|
// and that it guarantees that data() returns a non-NULL pointer
|
|
// even when the vector contains zero elements.
|
|
|
|
template <class T>
|
|
struct pod_vector {
|
|
typedef T value_type;
|
|
typedef T *iterator;
|
|
pod_vector() {
|
|
b = e = 0;
|
|
}
|
|
explicit pod_vector(size_t size_) {
|
|
// Allocate raw uninitialized memory
|
|
b = static_cast<T *>(::operator new(size_ * sizeof(T)));
|
|
e = b + size_;
|
|
}
|
|
~pod_vector()
|
|
#if __cplusplus >= 201103L
|
|
noexcept
|
|
#endif
|
|
{
|
|
_free();
|
|
}
|
|
void swap(pod_vector &x) {
|
|
std::swap(b, x.b);
|
|
std::swap(e, x.e);
|
|
}
|
|
iterator begin() const { return b; }
|
|
iterator end() const { return e; }
|
|
T *data() { return b; }
|
|
const T *data() const { return b; }
|
|
T &operator[](size_t i) { return b[i]; }
|
|
const T &operator[](size_t i) const { return b[i]; }
|
|
size_t size() const { return e - b; }
|
|
void resize(size_t new_size) {
|
|
if (new_size == size())
|
|
return;
|
|
T *n = static_cast<T *>(::operator new(new_size * sizeof(T)));
|
|
size_t ncopy = std::min(size(), new_size);
|
|
std::copy(b, b + ncopy, n);
|
|
_free();
|
|
b = n;
|
|
e = n + new_size;
|
|
}
|
|
pod_vector(const pod_vector &a)
|
|
|
|
{
|
|
b = new T[a.size()];
|
|
e = b + a.size();
|
|
std::copy(a.b, a.e, b);
|
|
//if (size()) fprintf(stderr, "pod_vector cc %d\n", (int)size());
|
|
}
|
|
void clear() {
|
|
_free();
|
|
b = e = 0;
|
|
}
|
|
#if __cplusplus >= 201103L
|
|
pod_vector(pod_vector&& x) noexcept:
|
|
b(x.b), e(x.e)
|
|
{
|
|
x.b = x.e = 0;
|
|
//if (size()) fprintf(stderr, "pod_vector mv %d\n", (int)size());
|
|
}
|
|
#endif
|
|
pod_vector &operator=(const pod_vector &a) {
|
|
if (&a == this)
|
|
return *this;
|
|
_free();
|
|
b = static_cast<T *>(::operator new(a.size() * sizeof(T)));
|
|
e = b + a.size();
|
|
std::copy(a.b, a.e, b);
|
|
//if (size()) fprintf(stderr, "pod_vector = %d\n", (int)size());
|
|
return *this;
|
|
}
|
|
#if __cplusplus >= 201103L
|
|
pod_vector &operator=(pod_vector &&x) noexcept {
|
|
if (&x == this)
|
|
return *this;
|
|
_free();
|
|
b = x.b;
|
|
e = x.e;
|
|
x.b = x.e = 0;
|
|
return *this;
|
|
}
|
|
#endif
|
|
private:
|
|
void _free() {
|
|
// Free as raw uninitialized memory
|
|
::operator delete(b);
|
|
}
|
|
private:
|
|
T *b;
|
|
T *e;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
#endif
|