-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvec.h
More file actions
174 lines (137 loc) · 3.54 KB
/
vec.h
File metadata and controls
174 lines (137 loc) · 3.54 KB
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#ifndef VEC_H
#define VEC_H
#include <cstddef>
#include <iostream>
#include <iterator>
#include <exception>
#include <type_traits>
namespace nsl { // non-standard library...
template <class T>
class vec {
private:
T* _vec = nullptr;
size_t _size;
size_t _len = 0;
public:
class Iterator {
// iterator tags
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;
private:
pointer m_ptr;
public:
Iterator(pointer ptr) : m_ptr(ptr) {}
reference operator*() const { return *m_ptr; }
pointer operator->() { return m_ptr; }
// prefix increment
Iterator& operator++() {
m_ptr++;
return *this;
}
// postfix increment
Iterator operator++(int) {
Iterator tmp = *this;
++(*this);
return tmp;
}
friend bool operator==(const Iterator& a, const Iterator& b) {
return a.m_ptr == b.m_ptr;
}
friend bool operator!=(const Iterator& a, const Iterator& b) {
return a.m_ptr != b.m_ptr;
}
};
vec(size_t reserve = 0) {
_size = sizeof(T) * reserve;
if (_size) _vec = (T*)malloc(_size);
}
~vec() { free(_vec); }
T& operator[](size_t i) {
if (i >= _len) throw std::out_of_range("out of bounds vec access");
return _vec[i];
}
T& get_unsafe(size_t i) { return _vec[i]; }
void push(T val) {
size_t type_size = sizeof(T);
if (_size == 0) {
_size = type_size;
_vec = (T*)malloc(_size);
} else if (_size <= _len * type_size) {
_size += type_size;
_vec = (T*)realloc(_vec, _size);
}
_vec[_len] = val;
_len++;
}
/// decrements the length & will shrink the vector unless mem has
/// been reserved
void pop() {
if (_len * sizeof(T) == _size) {
_size -= sizeof(T);
_vec = (T*)realloc(_vec, _size);
}
_len--;
}
size_t size() { return _size; }
size_t len() { return _len; }
const T* ptr() { return _vec; };
// iterator methods
Iterator begin() { return Iterator(&_vec[0]); }
Iterator end() { return Iterator(&_vec[_len]); }
vec& operator=(const char* str) noexcept {
static_assert(std::is_same<T, char>::value,
"cannot assign "
"string to non string vector");
int str_len = 0;
while (str[str_len] != '\0') str_len++;
if (_len != str_len) { // shrink or grow vec to fit new string
_size = str_len + 1;
_vec = (T*)realloc(_vec, str_len + 1);
}
_len = 0;
for (int i = 0; i < str_len; i++) {
push(str[i]);
}
push('\0');
return *this;
}
};
class str {
private:
size_t _len;
vec<char> _vec;
public:
str(size_t reserve = 0) : _vec(reserve) {}
str(const char* str) {
_vec = str;
_len = _vec.len() - 1;
}
str& operator=(const char* str) noexcept {
_vec = str;
_len = _vec.len() - 1;
return *this;
}
char& operator[](size_t index) { return _vec[index]; }
friend std::ostream& operator<<(std::ostream& os, str& s) {
return os << s.ptr();
}
void append(const char* str) {
_vec.pop(); // remove null terminator
int str_len = 0;
while (str[str_len] != '\0') {
_vec.push(str[str_len]);
str_len++;
_len++;
}
_vec.push('\0');
}
const char* ptr() { return _vec.ptr(); }
size_t len() { return _len; }
vec<char>::Iterator begin() { return vec<char>::Iterator(&_vec[0]); }
vec<char>::Iterator end() { return vec<char>::Iterator(&_vec[_len]); }
};
} // namespace nsl
#endif // VEC_H