// -*-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> template 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(e)); ++n; } template 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)...); ++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); } }; #endif // COSMOPOLITAN_CTL_OPTIONAL_H_