00001
00002
00003 #include <algorithm>
00004
00005 #include "BCP_os.hpp"
00006 #include "BCP_error.hpp"
00007 #include "BCP_vector.hpp"
00008 #include "BCP_vector_sanity.hpp"
00009
00010
00011
00012 template <class T> void
00013 BCP_vec<T>::deallocate() {
00014 if (start) {
00015 while (finish != start) {
00016 BCP_DESTROY(--finish);
00017 }
00018 ::operator delete(start);
00019 }
00020 }
00021
00022
00023
00024 template <class T> void
00025 BCP_vec<T>::insert_aux(iterator position, const_reference x){
00026 if (finish != end_of_storage) {
00027 BCP_CONSTRUCT(finish, *(finish - 1));
00028 std::copy_backward(position, finish - 1, finish);
00029 *position = x;
00030 ++finish;
00031 } else {
00032 const size_t len = (2*size() + 0x1000) * sizeof(T);
00033 iterator tmp = allocate(len);
00034 iterator tmp_finish = std::uninitialized_copy(start, position, tmp);
00035 BCP_CONSTRUCT(tmp_finish++, x);
00036 tmp_finish = std::uninitialized_copy(position, finish, tmp_finish);
00037 deallocate();
00038 start = tmp;
00039 finish = tmp_finish;
00040 end_of_storage = tmp + len;
00041 }
00042 }
00043
00044
00045
00046 template <class T>
00047 BCP_vec<T>::BCP_vec(const size_t n, const_reference value) :
00048 start(0), finish(0), end_of_storage(0)
00049 {
00050 if (n > 0) {
00051 start = allocate(n);
00052 end_of_storage = finish = start + n;
00053 std::uninitialized_fill_n(start, n, value);
00054 }
00055 }
00056
00057 template <class T>
00058 BCP_vec<T>::BCP_vec(const_iterator first, const_iterator last) :
00059 start(0), finish(0), end_of_storage(0)
00060 {
00061 const size_t len = last - first;
00062 if (len > 0) {
00063 start = allocate(len);
00064 end_of_storage = finish = std::uninitialized_copy(first, last, start);
00065 }
00066 }
00067
00068 template <class T>
00069 BCP_vec<T>::BCP_vec(const T* x, const size_t num) :
00070 start(0), finish(0), end_of_storage(0)
00071 {
00072 if (num > 0) {
00073 finish = start = allocate(num);
00074 const T* const lastx = x + num;
00075 while (x != lastx)
00076 BCP_CONSTRUCT(finish++, *x++);
00077 end_of_storage = finish;
00078 }
00079 }
00080
00081
00082
00083 template <class T> void
00084 BCP_vec<T>::keep(iterator pos) {
00085 iterator oldfinish = finish;
00086 finish = std::copy(pos, pos + 1, start);
00087 BCP_DESTROY_RANGE(finish, oldfinish);
00088 }
00089
00090 template <class T> void
00091 BCP_vec<T>::keep(iterator first, iterator last) {
00092 iterator oldfinish = finish;
00093 finish = std::copy(first, last, start);
00094 BCP_DESTROY_RANGE(finish, oldfinish);
00095 }
00096
00097
00098
00099 template <class T> void
00100 BCP_vec<T>::erase(iterator position) {
00101 if (position + 1 != finish)
00102 std::copy(position + 1, finish, position);
00103 BCP_DESTROY(--finish);
00104 }
00105
00106 template <class T> void
00107 BCP_vec<T>::erase(iterator first, iterator last) {
00108 iterator oldfinish = finish;
00109 finish = std::copy(last, finish, first);
00110 BCP_DESTROY_RANGE(finish, oldfinish);
00111 }
00112
00113
00114
00115
00116 template <class T> void
00117 BCP_vec<T>::reserve(const size_t n){
00118 if (capacity() < n) {
00119 iterator tmp = allocate(n);
00120 iterator tmp_finish = std::uninitialized_copy(start, finish, tmp);
00121 deallocate();
00122 start = tmp;
00123 finish = tmp_finish;
00124 end_of_storage = start + n;
00125 }
00126 }
00127
00128
00129
00130 template <class T> void
00131 BCP_vec<T>::swap(BCP_vec<T>& x) {
00132 std::swap(start, x.start);
00133 std::swap(finish, x.finish);
00134 std::swap(end_of_storage, x.end_of_storage);
00135 }
00136
00137
00138
00139 template <class T> BCP_vec<T>&
00140 BCP_vec<T>::operator=(const BCP_vec<T>& x){
00141 if (&x != this) {
00142 const size_t x_size = x.size();
00143 if (x_size > capacity()) {
00144 deallocate();
00145 start = allocate(x_size);
00146 end_of_storage = start + x_size;
00147 finish = std::uninitialized_copy(x.begin(), x.end(), start);
00148 } else {
00149 if (x_size < size()) {
00150 iterator oldfinish = finish;
00151 finish = std::copy(x.begin(), x.end(), start);
00152 BCP_DESTROY_RANGE(finish, oldfinish);
00153 } else {
00154 std::copy(x.begin(), x.entry(size()), start);
00155 finish = std::uninitialized_copy(x.entry(size()), x.end(), finish);
00156 }
00157 }
00158 }
00159 return *this;
00160 }
00161
00162
00163
00164
00165 template <class T> void
00166 BCP_vec<T>::assign(const void* x, const size_t num){
00167 if (num > capacity()){
00168 deallocate();
00169 start = allocate(num);
00170 end_of_storage = start + num;
00171 } else {
00172 BCP_DESTROY_RANGE(start, finish);
00173 }
00174 T entry;
00175 finish = start;
00176 const char* charx = static_cast<const char*>(x);
00177 for (int i = num; i > 0; --i) {
00178 memcpy(&entry, charx, sizeof(T));
00179 BCP_CONSTRUCT(finish++, entry);
00180 charx += sizeof(T);
00181 }
00182 }
00183
00184
00185
00186 template <class T> void
00187 BCP_vec<T>::insert(iterator position, const void* first, const size_t n){
00188 if (n == 0) return;
00189 T entry;
00190 const char* charx = static_cast<const char*>(first);
00191 if ((size_t) (end_of_storage - finish) >= n) {
00192 const size_t to_move = finish - position;
00193 if (to_move <= n) {
00194 std::uninitialized_copy(position, finish, position + n);
00195 finish += n;
00196 size_t i = n;
00197 for ( ; i > to_move; --i) {
00198 memcpy(&entry, charx, sizeof(T));
00199 BCP_CONSTRUCT(position++, entry);
00200 charx += sizeof(T);
00201 }
00202 for ( ; i > 0; --i) {
00203 memcpy(&entry, charx, sizeof(T));
00204 *position++ = entry;
00205 charx += sizeof(T);
00206 }
00207 } else {
00208 std::uninitialized_copy(finish - n, finish, finish);
00209 std::copy_backward(position, finish - n, finish);
00210 finish += n;
00211 for (int i = n; i > 0; --i) {
00212 memcpy(&entry, charx, sizeof(T));
00213 *position++ = entry;
00214 charx += sizeof(T);
00215 }
00216 }
00217 } else {
00218 const size_t new_size = (2*size() + n) * sizeof(T);
00219 iterator tmp = allocate(new_size);
00220 iterator tmp_finish = std::uninitialized_copy(start, position, tmp);
00221 for (int i = n; i > 0; --i) {
00222 memcpy(&entry, charx, sizeof(T));
00223 BCP_CONSTRUCT(tmp_finish++, entry);
00224 charx += sizeof(T);
00225 }
00226 tmp_finish = std::uninitialized_copy(position, finish, tmp_finish);
00227 deallocate();
00228 start = tmp;
00229 finish = tmp_finish;
00230 end_of_storage = tmp + new_size;
00231 }
00232 }
00233
00234
00235
00236 template <class T> void
00237 BCP_vec<T>::insert(iterator position,
00238 const_iterator first, const_iterator last){
00239 if (first == last) return;
00240 const size_t n = last - first;
00241 if ((size_t) (end_of_storage - finish) >= n) {
00242 const size_t to_move = finish - position;
00243 if (to_move <= n) {
00244 std::uninitialized_copy(position, finish, position + n);
00245 std::copy(first, first + to_move, position);
00246 std::uninitialized_copy(first + to_move, last, finish);
00247 } else {
00248 std::uninitialized_copy(finish - n, finish, finish);
00249 std::copy_backward(position, finish - n, finish);
00250 std::copy(first, last, position);
00251 }
00252 finish += n;
00253 } else {
00254 const size_t new_size = (2*size() + n) * sizeof(T);
00255 iterator tmp = allocate(new_size);
00256 iterator tmp_finish = std::uninitialized_copy(start, position, tmp);
00257 tmp_finish = std::uninitialized_copy(first, last, tmp_finish);
00258 tmp_finish = std::uninitialized_copy(position, finish, tmp_finish);
00259 deallocate();
00260 start = tmp;
00261 finish = tmp_finish;
00262 end_of_storage = tmp + new_size;
00263 }
00264 }
00265
00266
00267
00268 template <class T> void
00269 BCP_vec<T>::insert(iterator position, const size_t n, const_reference x) {
00270 if (n == 0) return;
00271 if ((size_t) (end_of_storage - finish) >= n) {
00272 const size_t to_move = finish - position;
00273 if (to_move <= n) {
00274 std::uninitialized_copy(position, finish, position + n);
00275 std::fill_n(position, to_move, x);
00276 std::uninitialized_fill_n(finish, n - to_move, x);
00277 } else {
00278 std::uninitialized_copy(finish - n, finish, finish);
00279 std::copy_backward(position, finish - n, finish);
00280 std::fill_n(position, n, x);
00281 }
00282 finish += n;
00283 } else {
00284 const size_t new_size = (2*size() + n) * sizeof(T);
00285 iterator tmp = allocate(new_size);
00286 iterator tmp_finish = std::uninitialized_copy(start, position, tmp);
00287 std::uninitialized_fill_n(tmp_finish, n, x);
00288 tmp_finish += n;
00289 tmp_finish = std::uninitialized_copy(position, finish, tmp_finish);
00290 deallocate();
00291 start = tmp;
00292 finish = tmp_finish;
00293 end_of_storage = tmp + new_size;
00294 }
00295 }
00296
00297
00298
00299 template <class T> typename BCP_vec<T>::iterator
00300 BCP_vec<T>::insert(iterator position, const_reference x){
00301 const size_t n = position - start;
00302 if (finish != end_of_storage && position == finish) {
00303 BCP_CONSTRUCT(finish++, x);
00304 } else {
00305 insert_aux(position, x);
00306 }
00307 return start + n;
00308 }
00309
00310
00311
00312
00313 template <class T> void
00314 BCP_vec<T>::keep_by_index(const BCP_vec<int>& positions){
00315 BCP_vec_sanity_check(positions.begin(), positions.end(), size());
00316 unchecked_keep_by_index(positions.begin(), positions.end());
00317 }
00318
00319
00320 template <class T> void
00321 BCP_vec<T>::unchecked_keep_by_index(const BCP_vec<int>& positions){
00322 unchecked_keep_by_index(positions.begin(), positions.end());
00323 }
00324
00325
00326
00327 template <class T> void
00328 BCP_vec<T>::erase_by_index(const BCP_vec<int>& positions){
00329 BCP_vec_sanity_check(positions.begin(), positions.end(), size());
00330 unchecked_erase_by_index(positions.begin(), positions.end());
00331 }
00332
00333
00334
00335 template <class T> void
00336 BCP_vec<T>::unchecked_erase_by_index(const BCP_vec<int>& positions){
00337 unchecked_erase_by_index(positions.begin(), positions.end());
00338 }
00339
00340
00341
00342 template <class T> void
00343 BCP_vec<T>::keep_by_index(BCP_vec<int>::const_iterator firstpos,
00344 BCP_vec<int>::const_iterator lastpos) {
00345 BCP_vec_sanity_check(firstpos, lastpos, size());
00346 unchecked_keep_by_index(firstpos, lastpos);
00347 }
00348
00349
00350
00351 template <class T> void
00352 BCP_vec<T>::unchecked_keep_by_index(BCP_vec<int>::const_iterator firstpos,
00353 BCP_vec<int>::const_iterator lastpos) {
00354 if (firstpos == lastpos) {
00355 clear();
00356 } else {
00357 iterator target = start;
00358 while ( firstpos != lastpos )
00359 *target++ = operator[](*firstpos++);
00360 BCP_DESTROY_RANGE(target, finish);
00361 finish = target;
00362 }
00363 }
00364
00365
00366
00367 template <class T> void
00368 BCP_vec<T>::erase_by_index(BCP_vec<int>::const_iterator firstpos,
00369 BCP_vec<int>::const_iterator lastpos) {
00370 BCP_vec_sanity_check(firstpos, lastpos, size());
00371 unchecked_erase_by_index(firstpos, lastpos);
00372 }
00373
00374
00375
00376 template <class T> void
00377 BCP_vec<T>::unchecked_erase_by_index(BCP_vec<int>::const_iterator firstpos,
00378 BCP_vec<int>::const_iterator lastpos) {
00379 if (firstpos == lastpos)
00380 return;
00381 --lastpos;
00382 int source;
00383 iterator target = entry(*firstpos);
00384 while (firstpos != lastpos){
00385 source = *firstpos + 1;
00386 ++firstpos;
00387 if (*firstpos > source)
00388 target = std::copy( entry(source), entry(*firstpos), target );
00389 }
00390 iterator oldfinish = finish;
00391 finish = std::copy( entry(*firstpos + 1), end(), target );
00392 BCP_DESTROY_RANGE(finish, oldfinish);
00393 }
00394
00395
00396
00397 template <class T> void
00398 BCP_vec<T>::update(const BCP_vec<int>& positions,
00399 const BCP_vec<T>& values){
00400 if (positions.size() != values.size())
00401 throw BCP_fatal_error("BCP_vec::update() called with unequal sizes.\n");
00402 BCP_vec_sanity_check(positions.begin(), positions.end(), size());
00403 unchecked_update(positions, values);
00404 }
00405
00406
00407
00408 template <class T> void
00409 BCP_vec<T>::unchecked_update(const BCP_vec<int>& positions,
00410 const BCP_vec<T>& values){
00411 if (positions.size() == 0)
00412 return;
00413 const_iterator val = values.begin();
00414 BCP_vec<int>::const_iterator pos = positions.begin();
00415 const BCP_vec<int>::const_iterator lastpos = positions.end();
00416 while (pos != lastpos)
00417 operator[](*pos++) = *val++;
00418 }
00419
00420
00421
00422 template <class T>
00423 bool operator==(const BCP_vec<T>& x, const BCP_vec<T>& y) {
00424 return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
00425 }
00426
00427 template <class T>
00428 bool operator< (BCP_vec<T>& x, BCP_vec<T>& y) {
00429 return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
00430 }