cosmopolitan/ctl/vector.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

247 lines
4.3 KiB
C
Raw Normal View History

// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
#define COSMOPOLITAN_CTL_OPTIONAL_H_
#include <__utility/forward.h>
#include <__utility/move.h>
#include <__utility/swap.h>
namespace ctl {
template<typename T>
struct vector
{
size_t n = 0;
size_t c = 0;
T* p = nullptr;
using iterator = T*;
using const_iterator = const T*;
vector() = default;
~vector()
{
delete[] p;
}
vector(const vector& other)
{
n = other.n;
c = other.c;
p = new T[c];
for (size_t i = 0; i < n; ++i)
new (&p[i]) T(other.p[i]);
}
vector(vector&& other) noexcept
{
n = other.n;
c = other.c;
p = other.p;
other.n = 0;
other.c = 0;
other.p = nullptr;
}
explicit vector(size_t count, const T& value = T())
{
n = count;
c = count;
p = new T[c];
for (size_t i = 0; i < n; ++i)
new (&p[i]) T(value);
}
vector& operator=(const vector& other)
{
if (this != &other) {
T* newData = new T[other.c];
for (size_t i = 0; i < other.n; ++i) {
newData[i] = other.p[i];
}
delete[] p;
p = newData;
n = other.n;
c = other.c;
}
return *this;
}
vector& operator=(vector&& other) noexcept
{
if (this != &other) {
delete[] p;
p = other.p;
n = other.n;
c = other.c;
other.p = nullptr;
other.n = 0;
other.c = 0;
}
return *this;
}
bool empty() const
{
return !n;
}
size_t size() const
{
return n;
}
size_t capacity() const
{
return c;
}
T& operator[](size_t i)
{
if (i >= n)
__builtin_trap();
return p[i];
}
const T& operator[](size_t i) const
{
if (i >= n)
__builtin_trap();
return p[i];
}
iterator begin()
{
return p;
}
iterator end()
{
return p + n;
}
const_iterator cbegin() const
{
return p;
}
const_iterator cend() const
{
return p + n;
}
T& front()
{
if (!n)
__builtin_trap();
return p[0];
}
const T& front() const
{
if (!n)
__builtin_trap();
return p[0];
}
T& back()
{
if (!n)
__builtin_trap();
return p[n - 1];
}
const T& back() const
{
if (!n)
__builtin_trap();
return p[n - 1];
}
void clear()
{
for (size_t i = 0; i < n; ++i)
p[i].~T();
n = 0;
}
void reserve(size_t c2)
{
if (c2 <= c)
return;
T* newP = new T[c2];
for (size_t i = 0; i < n; ++i)
newP[i] = std::move(p[i]);
delete[] p;
p = newP;
c = c2;
}
void push_back(const T& e)
{
if (n == c) {
size_t c2 = c + 1;
c2 += c2 >> 1;
reserve(c2);
}
new (&p[n]) T(e);
++n;
}
void push_back(T&& e)
{
if (n == c) {
size_t c2 = c + 1;
c2 += c2 >> 1;
reserve(c2);
}
new (&p[n]) T(std::forward<T>(e));
++n;
}
template<typename... Args>
void emplace_back(Args&&... args)
{
if (n == c) {
size_t c2 = c + 1;
c2 += c2 >> 1;
reserve(c2);
}
new (&p[n]) T(std::forward<Args>(args)...);
++n;
}
void pop_back()
{
if (n > 0) {
--n;
p[n].~T();
}
}
void resize(size_t n2)
{
if (n2 > n) {
reserve(n2);
for (size_t i = n; i < n2; ++i)
new (&p[i]) T();
} else if (n2 < n) {
for (size_t i = n2; i < n; ++i)
p[i].~T();
}
n = n2;
}
void swap(vector& other) noexcept
{
std::swap(n, other.n);
std::swap(c, other.c);
std::swap(p, other.p);
}
};
} // namespace ctl
#endif // COSMOPOLITAN_CTL_OPTIONAL_H_