Skip to content

Commit 5813128

Browse files
committed
[CPP] Rewrite vector<int> to work with primitive and non-primitive data-type
1 parent cb764bb commit 5813128

File tree

4 files changed

+137
-75
lines changed

4 files changed

+137
-75
lines changed

src/usr/include/new.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ void *operator new(std::size_t size);
66
void *operator new[](std::size_t size);
77
void operator delete(void *ptr);
88
void operator delete[](void *ptr);
9+
10+
void *operator new(std::size_t size, void *);

src/usr/include/vector.h

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,34 @@ namespace std {
77
template <typename T> class vector {
88
std::size_t _capacity, _size;
99
T *_data;
10-
void resize_capacity(std::size_t capacity);
1110

1211
public:
1312
typedef T *iterator;
1413
typedef const T *const_iterator;
1514

1615
vector();
16+
vector(std::size_t size);
1717
vector(std::size_t size, const T &_default);
1818
vector(const vector<T> &o);
19-
vector &operator=(const vector<T> &o);
2019
~vector();
2120

21+
vector &operator=(const vector<T> &o);
22+
23+
void reserve(std::size_t n);
24+
void resize(std::size_t new_size);
25+
void resize(std::size_t new_size, const T &_default);
26+
void push_back(const T &val);
27+
void pop_back();
28+
29+
void clear();
30+
2231
iterator begin();
2332
iterator end();
2433
const_iterator begin() const;
2534
const_iterator end() const;
2635

27-
void clear();
2836
bool empty() const;
2937
std::size_t size() const;
30-
void push_back(const T &val);
31-
void pop_back();
3238

3339
T &back();
3440
T &front();
@@ -39,4 +45,20 @@ template <typename T> class vector {
3945

4046
} // namespace std
4147

42-
#include <vector.tcc>
48+
template <typename T>
49+
inline bool operator!=(const std::vector<T> &a, const std::vector<T> b) {
50+
if (a.size() != b.size())
51+
return true;
52+
for (std::size_t i = 0; i < a.size(); i++) {
53+
if (a[i] != b[i])
54+
return true;
55+
}
56+
return false;
57+
}
58+
59+
template <typename T>
60+
inline bool operator==(const std::vector<T> &a, const std::vector<T> b) {
61+
return !(a != b);
62+
}
63+
64+
#include <vector.tcc>

src/usr/include/vector.tcc

Lines changed: 104 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3,125 +3,161 @@
33
// This is internal headerfile to be included by vector.h only
44

55
#include <new.h>
6+
#include <stdio.h>
67
#include <stdlib.h>
78
#include <string.h>
89
#include <vector.h>
910

1011
namespace std {
1112

12-
static std::size_t next_power2(std::size_t size) {
13-
// assumes no overflow
14-
std::size_t p = 1;
15-
while (p && p < size)
16-
p <<= 1;
17-
return p;
18-
}
13+
template <typename T>
14+
vector<T>::vector() : _data(NULL), _capacity(0), _size(0) {}
1915

2016
template <typename T>
21-
vector<T>::vector() : _data(NULL), _capacity(0), _size(0) {
22-
resize_capacity(1);
17+
vector<T>::vector(std::size_t size) : _data(NULL), _capacity(0), _size(0) {
18+
reserve(size);
19+
// initializing the members
20+
for (std::size_t i = 0; i < size; i++) {
21+
new (_data + i) T(); // default constructor
22+
}
23+
_size = size;
2324
}
2425

2526
template <typename T>
2627
vector<T>::vector(std::size_t size, const T &_default)
27-
: _data(NULL), _capacity(0), _size(size) {
28-
resize_capacity(size);
28+
: _data(NULL), _capacity(0), _size(0) {
29+
reserve(size);
30+
// initializing the members
2931
for (std::size_t i = 0; i < size; i++) {
30-
this->_data[i] = _default;
32+
new (_data + i) T(_default); // copy constructor
3133
}
34+
_size = size;
3235
}
3336

3437
template <typename T>
35-
vector<T>::vector(const vector<T> &o)
36-
: _data(NULL), _capacity(0), _size(o._size) {
37-
resize_capacity(o._capacity);
38-
std::memcpy(_data, o._data, _capacity * sizeof(T));
38+
vector<T>::vector(const vector<T> &o) : _data(NULL), _capacity(0), _size(0) {
39+
reserve(o._size);
40+
// initializing the members
41+
for (std::size_t i = 0; i < o._size; i++) {
42+
new (_data + i) T(o._data[i]); // copy constructor
43+
}
44+
_size = o._size;
3945
}
4046

4147
template <typename T> vector<T> &vector<T>::operator=(const vector<T> &o) {
42-
resize_capacity(o._capacity);
43-
_size = o._size;
44-
std::memcpy(_data, o._data, _capacity * sizeof(T));
48+
resize(o._size);
49+
// re-initialize the members
50+
for (std::size_t i = 0; i < o._size; i++) {
51+
_data[i] = o._data[i]; // assignment operator
52+
}
4553
return *this;
4654
}
4755

48-
template <typename T> vector<T>::~vector() { delete[] _data; }
56+
template <typename T> vector<T>::~vector() {
57+
clear();
58+
reserve(0);
59+
}
4960

50-
template <typename T> typename vector<T>::iterator vector<T>::begin() {
51-
return this->_data;
61+
template <typename T> void vector<T>::reserve(std::size_t new_capacity) {
62+
if (new_capacity < _size)
63+
new_capacity = _size; // never reserve less than size
64+
if (new_capacity == _capacity)
65+
return; // resize not needed
66+
67+
const std::size_t new_capacity_size = (new_capacity) * sizeof(T);
68+
69+
// make a copy of array and move _data pointer.
70+
_data = (T *)std::realloc(_data, new_capacity_size);
71+
_capacity = new_capacity;
5272
}
5373

54-
template <typename T> typename vector<T>::iterator vector<T>::end() {
55-
return this->_data + this->_size;
74+
template <typename T> void vector<T>::resize(const std::size_t new_size) {
75+
if (_size < new_size) {
76+
reserve(new_size);
77+
for (std::size_t i = _size; i < new_size; i++) {
78+
new (_data + i) T(); // default constructor
79+
}
80+
_size = new_size;
81+
} else {
82+
for (std::size_t i = new_size; i < _size; i++) {
83+
_data[i].~T(); // explicit destructor call
84+
}
85+
_size = new_size;
86+
// not reducing the allocated capacity.
87+
}
5688
}
5789

5890
template <typename T>
59-
typename vector<T>::const_iterator vector<T>::begin() const {
60-
return this->_data;
91+
void vector<T>::resize(const std::size_t new_size, const T &_default) {
92+
if (_size < new_size) {
93+
reserve(new_size);
94+
for (std::size_t i = _size; i < new_size; i++) {
95+
new (_data + i) T(_default); // copy constructor
96+
}
97+
_size = new_size;
98+
} else {
99+
for (std::size_t i = new_size; i < _size; i++) {
100+
_data[i].~T(); // explicit destructor call
101+
}
102+
_size = new_size;
103+
// not reducing the allocated capacity.
104+
}
61105
}
62106

63-
template <typename T>
64-
typename vector<T>::const_iterator vector<T>::end() const {
65-
return this->_data + this->_size;
107+
template <typename T> void vector<T>::push_back(const T &val) {
108+
if (_size == _capacity) {
109+
reserve(max(1, _capacity * 2));
110+
}
111+
new (_data + (_size++)) T(val); // copy constructor
66112
}
67113

68-
template <typename T> void vector<T>::resize_capacity(std::size_t capacity) {
69-
// internal; assumes capacity to be power of 2
70-
// and will also make a copy of array and move _data pointer.
71-
// assumes size<=current_capacity and size<=new_capacity
72-
const std::size_t data_size =
73-
std::min(capacity, this->_capacity) * sizeof(T);
74-
T *_new_data = new T[capacity];
75-
if (!_new_data)
76-
return; // malloc failed
77-
std::memcpy(_new_data, this->_data, data_size);
114+
template <typename T> void vector<T>::pop_back() {
115+
if (!(_size > 0)) {
116+
return;
117+
}
78118

79-
delete[] this->_data; // should be no-op if _data == NULL
80-
this->_data = _new_data;
81-
this->_capacity = capacity;
82-
}
119+
_size--;
120+
_data[_size].~T(); // explicit destructor call
83121

84-
template <typename T> void vector<T>::clear() {
85-
// not reducing capacity for now
86-
this->_size = 0;
122+
// not reducing the allocated capacity.
87123
}
88124

89-
template <typename T> bool vector<T>::empty() const { return this->_size == 0; }
125+
template <typename T> void vector<T>::clear() { resize(0); }
90126

91-
template <typename T> std::size_t vector<T>::size() const {
92-
return this->_size;
127+
template <typename T> typename vector<T>::iterator vector<T>::begin() {
128+
return _data;
93129
}
94130

95-
template <typename T> void vector<T>::push_back(const T &val) {
96-
if (this->_size == this->_capacity) {
97-
resize_capacity(this->_capacity * 2);
98-
}
99-
this->_data[this->_size++] = val;
131+
template <typename T> typename vector<T>::iterator vector<T>::end() {
132+
return _data + _size;
100133
}
101134

102-
template <typename T> void vector<T>::pop_back() {
103-
// not reducing the capacity for now
104-
if (this->_size > 0) {
105-
this->_size--;
106-
}
135+
template <typename T>
136+
typename vector<T>::const_iterator vector<T>::begin() const {
137+
return _data;
107138
}
108139

109-
template <typename T> T &vector<T>::back() {
110-
return this->_data[this->_size - 1];
140+
template <typename T>
141+
typename vector<T>::const_iterator vector<T>::end() const {
142+
return _data + _size;
111143
}
112144

113-
template <typename T> T &vector<T>::front() { return this->_data[0]; }
145+
template <typename T> bool vector<T>::empty() const { return _size == 0; }
114146

115-
template <typename T> T &vector<T>::at(std::size_t pos) {
116-
return this->_data[pos];
117-
}
147+
template <typename T> std::size_t vector<T>::size() const { return _size; }
148+
149+
template <typename T> T &vector<T>::back() { return _data[_size - 1]; }
150+
151+
template <typename T> T &vector<T>::front() { return _data[0]; }
152+
153+
template <typename T> T &vector<T>::at(std::size_t pos) { return _data[pos]; }
118154

119155
template <typename T> T &vector<T>::operator[](std::size_t pos) {
120-
return this->_data[pos];
156+
return _data[pos];
121157
}
122158

123159
template <typename T> const T &vector<T>::operator[](std::size_t pos) const {
124-
return this->_data[pos];
160+
return _data[pos];
125161
}
126162

127-
} // namespace std
163+
} // namespace std

src/usr/lib/new.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ void *operator new[](std::size_t size) { return ::operator new(size); }
88

99
void operator delete(void *ptr) { std::free(ptr); }
1010

11-
void operator delete[](void *ptr) { ::operator delete(ptr); }
11+
void operator delete[](void *ptr) { ::operator delete(ptr); }
12+
13+
void *operator new(std::size_t s, void *ptr) { return ptr; }

0 commit comments

Comments
 (0)