summaryrefslogtreecommitdiff
path: root/src/vec.h
blob: 98c760a89015ea1210b8e06d76a69a3fe3bbaee2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#pragma once

/* SPDX-License-Identifier: Unlicense
 */

/*! A data vector implementation.
 *
 * The sole purpose of this vector implementation is to not use std::vector,
 * because it greatly increases compilation times even if you just type
 * `#include <vector>`. And since there is no exceptions enabled in m68k-disasm
 * project, I consider it to be fine to have an implementation this bold. I also
 * don't need all the features of original std::vector an this implementation
 * provide only a small portion of them.
 * */
template <typename T>
class Vec {
public:
    using size_type = decltype(sizeof 0);
private:
    size_type _size{};
    size_type _capacity{};
    T *_d{};
    void expand(size_type by);
public:
    constexpr explicit Vec() {}
    Vec(const Vec& other);
    Vec(const T *data, size_type nmemb);
    Vec(const void *data, size_type size);
    constexpr Vec(Vec&& other)
        : _size(other._size), _capacity(other._capacity), _d(other._d)
    {
        other._d = nullptr;
        other._capacity = other._size = 0;
    }
    Vec &operator=(const Vec &other);
    Vec &operator=(Vec &&other)
    {
        // In case if `other` points to `this` we have to store it's state on
        // the stack before calling destructor of `this`.
        const size_type size = other._size;
        const size_type capacity = other._capacity;
        T *const d = other._d;
        other._d = nullptr;
        other._capacity = other._size = 0;
        this->~Vec();
        _size = size;
        _capacity = capacity;
        _d = d;
        return *this;
    }
    ~Vec();
    Vec<T> &PushBack(const T &value)
    {
        expand(1);
        _d[_size++] = static_cast<const T &>(value);
        return *this;
    }
    Vec<T> &PushBack(T &&value)
    {
        expand(1);
        _d[_size++] = static_cast<T &&>(value);
        return *this;
    }
    T PopBack(void) { return static_cast<T &&>(_d[--_size]); }
    constexpr T *Extract(void)
    {
        T *d = _d;
        _d = nullptr;
        _size = _capacity = 0;
        return d;
    }
    constexpr size_type Size(void) const { return _size; }
    constexpr size_type Capacity(void) const { return _capacity; }
    constexpr T *begin(void) { return _d; }
    constexpr T *end(void) { return _d + _size; }
    constexpr const T& operator[](size_type index) const { return *(_d + index); }
    constexpr T& operator[](size_type index) { return *(_d + index); }
    bool operator==(const Vec& other) const;
    bool operator!=(const Vec& other) const
    {
        return !(*this == other);
    }
};