1/* -*- c-basic-offset: 2 -*- */
2/*
3 Copyright(C) 2011-2016 Brazil
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License version 2.1 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#pragma once
20
21#include "dat.hpp"
22
23#include <new>
24
25namespace grn {
26namespace dat {
27
28template <typename T>
29class GRN_DAT_API Vector {
30 public:
31 Vector() : buf_(NULL), size_(0), capacity_(0) {}
32 ~Vector() {
33 for (UInt32 i = 0; i < size(); ++i) {
34 buf_[i].~T();
35 }
36 delete [] reinterpret_cast<char *>(buf_);
37 }
38
39 const T &operator[](UInt32 i) const {
40 GRN_DAT_DEBUG_THROW_IF(i >= size());
41 return buf_[i];
42 }
43 T &operator[](UInt32 i) {
44 GRN_DAT_DEBUG_THROW_IF(i >= size());
45 return buf_[i];
46 }
47
48 const T &front() const {
49 GRN_DAT_DEBUG_THROW_IF(empty());
50 return buf_[0];
51 }
52 T &front() {
53 GRN_DAT_DEBUG_THROW_IF(empty());
54 return buf_[0];
55 }
56
57 const T &back() const {
58 GRN_DAT_DEBUG_THROW_IF(empty());
59 return buf_[size() - 1];
60 }
61 T &back() {
62 GRN_DAT_DEBUG_THROW_IF(empty());
63 return buf_[size() - 1];
64 }
65
66 const T *begin() const {
67 return buf_;
68 }
69 T *begin() {
70 return buf_;
71 }
72
73 const T *end() const {
74 return buf_ + size_;
75 }
76 T *end() {
77 return buf_ + size_;
78 }
79
80 void push_back() {
81 reserve(size() + 1);
82 new (&buf_[size()]) T;
83 ++size_;
84 }
85 void push_back(const T &x) {
86 reserve(size() + 1);
87 new (&buf_[size()]) T(x);
88 ++size_;
89 }
90
91 void pop_back() {
92 GRN_DAT_DEBUG_THROW_IF(empty());
93 back().~T();
94 --size_;
95 }
96
97 void clear() {
98 resize(0);
99 }
100
101 void resize(UInt32 new_size) {
102 if (new_size > capacity()) {
103 reserve(new_size);
104 }
105 for (UInt32 i = size(); i < new_size; ++i) {
106 new (&buf_[i]) T;
107 }
108 for (UInt32 i = new_size; i < size(); ++i) {
109 buf_[i].~T();
110 }
111 size_ = new_size;
112 }
113 template <typename U>
114 void resize(UInt32 new_size, const U &value) {
115 if (new_size > capacity()) {
116 reserve(new_size);
117 }
118 for (UInt32 i = size(); i < new_size; ++i) {
119 new (&buf_[i]) T(value);
120 }
121 for (UInt32 i = new_size; i < size(); ++i) {
122 buf_[i].~T();
123 }
124 size_ = new_size;
125 }
126
127 void reserve(UInt32 new_capacity) {
128 if (new_capacity <= capacity()) {
129 return;
130 } else if ((new_capacity / 2) < capacity()) {
131 if (capacity() < (MAX_UINT32 / 2)) {
132 new_capacity = capacity() * 2;
133 } else {
134 new_capacity = MAX_UINT32;
135 }
136 }
137
138 T *new_buf = reinterpret_cast<T *>(
139 new (std::nothrow) char[sizeof(new_capacity) * new_capacity]);
140 GRN_DAT_THROW_IF(MEMORY_ERROR, new_buf == NULL);
141
142 for (UInt32 i = 0; i < size(); ++i) {
143 new (&new_buf[i]) T(buf_[i]);
144 }
145 for (UInt32 i = 0; i < size(); ++i) {
146 buf_[i].~T();
147 }
148
149 T *old_buf = buf_;
150 buf_ = new_buf;
151 delete [] reinterpret_cast<char *>(old_buf);
152
153 capacity_ = new_capacity;
154 }
155
156 void swap(Vector *rhs) {
157 T * const temp_buf = buf_;
158 buf_ = rhs->buf_;
159 rhs->buf_ = temp_buf;
160
161 const UInt32 temp_size = size_;
162 size_ = rhs->size_;
163 rhs->size_ = temp_size;
164
165 const UInt32 temp_capacity = capacity_;
166 capacity_ = rhs->capacity_;
167 rhs->capacity_ = temp_capacity;
168 }
169
170 bool empty() const {
171 return size_ == 0;
172 }
173 UInt32 size() const {
174 return size_;
175 }
176 UInt32 capacity() const {
177 return capacity_;
178 }
179
180 private:
181 T *buf_;
182 UInt32 size_;
183 UInt32 capacity_;
184
185 // Disallows copy and assignment.
186 Vector(const Vector &);
187 Vector &operator=(const Vector &);
188};
189
190} // namespace dat
191} // namespace grn
192