00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef BK_LIB_POD_VECTOR_H_INCLUDED
00021 #define BK_LIB_POD_VECTOR_H_INCLUDED
00022 #include "type_manip.h"
00023 #include <iterator>
00024 #include <memory>
00025 #include <cstring>
00026 #include <algorithm>
00027 #include <cassert>
00028 #include <stdexcept>
00029 namespace bk_lib { namespace detail {
00030 template <class T>
00031 void fill(T* first, T* last, const T& x) {
00032 assert(first <= last);
00033 switch ((last - first) & 7u)
00034 {
00035 case 0:
00036 while (first != last)
00037 {
00038 new(first++) T(x);
00039 case 7: new(first++) T(x);
00040 case 6: new(first++) T(x);
00041 case 5: new(first++) T(x);
00042 case 4: new(first++) T(x);
00043 case 3: new(first++) T(x);
00044 case 2: new(first++) T(x);
00045 case 1: new(first++) T(x);
00046 assert(first <= last);
00047 }
00048 }
00049 }
00050 template <class Iter, class T>
00051 void copy(Iter first, Iter last, std::size_t s, T* out) {
00052 switch (s & 7u)
00053 {
00054 case 0:
00055 while (first != last)
00056 {
00057 new(out++) T(*first++);
00058 case 7: new(out++) T(*first++);
00059 case 6: new(out++) T(*first++);
00060 case 5: new(out++) T(*first++);
00061 case 4: new(out++) T(*first++);
00062 case 3: new(out++) T(*first++);
00063 case 2: new(out++) T(*first++);
00064 case 1: new(out++) T(*first++);
00065 }
00066 }
00067 }
00068 template <class T>
00069 struct Fill {
00070 Fill(const T& val) : val_(val) {}
00071 void operator()(T* first, std::size_t n) const { detail::fill(first, first + n, val_); }
00072 const T& val_;
00073 private: Fill& operator=(const Fill&);
00074 };
00075 template <class Iter>
00076 struct Copy {
00077 Copy(Iter first, Iter last) : first_(first), last_(last) {}
00078 template <class T>
00079 void operator()(T* out, std::size_t n) const { detail::copy(first_, last_, n, out); }
00080 Iter first_;
00081 Iter last_;
00082 };
00083 template <class T>
00084 struct Memcpy {
00085 Memcpy(const T* first) : first_(first) {}
00086 void operator()(T* out, std::size_t n) const {
00087 std::memcpy(out, first_, n*sizeof(T));
00088 }
00089 const T* first_;
00090 };
00091 typedef char yes_type;
00092 typedef char (&no_type)[2];
00093 template <class T>
00094 struct IterType {
00095 static yes_type isPtr(const volatile void*);
00096 static no_type isPtr(...);
00097 static yes_type isLong(int64);
00098 static no_type isLong(...);
00099 static T& makeT();
00100 enum { ptr = sizeof(isPtr(makeT())) == sizeof(yes_type) };
00101 enum { num = sizeof(isLong(makeT())) == sizeof(yes_type) };
00102 enum { value = ptr ? 1 : num ? 2 : 0 };
00103 };
00104
00105 }
00106
00108
00114 template <class T, class Allocator = std::allocator<T> >
00115 class pod_vector {
00116 public:
00117
00118 typedef pod_vector<T,Allocator> this_type;
00119 typedef Allocator allocator_type;
00120 typedef typename Allocator::reference reference;
00121 typedef typename Allocator::const_reference const_reference;
00122 typedef typename Allocator::pointer iterator;
00123 typedef typename Allocator::const_pointer const_iterator;
00124 typedef typename Allocator::pointer pointer;
00125 typedef typename Allocator::const_pointer const_pointer;
00126 typedef std::reverse_iterator<iterator> reverse_iterator;
00127 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00128 typedef T value_type;
00129 typedef typename detail::if_then_else<
00130 sizeof(typename Allocator::size_type)<=sizeof(unsigned int),
00131 typename Allocator::size_type,
00132 unsigned int>::type size_type;
00133 typedef typename detail::if_then_else<
00134 sizeof(typename Allocator::difference_type)<=sizeof(int),
00135 typename Allocator::difference_type,
00136 int>::type difference_type;
00137
00139
00142 pod_vector() : ebo_(0, allocator_type()) { }
00143
00145
00148 explicit pod_vector(const allocator_type& a) : ebo_(0, a) { }
00149
00151
00154 explicit pod_vector(size_type n, const T& value = T(), const allocator_type& a = allocator_type())
00155 : ebo_(n, a) {
00156 detail::fill(ebo_.buf, ebo_.buf + n, value);
00157 ebo_.size = n;
00158 }
00159
00161
00164 template <class Iter>
00165 pod_vector(Iter first, Iter last, const allocator_type& a = allocator_type(), typename detail::disable_if<detail::IterType<Iter>::num>::type* = 0)
00166 : ebo_(0, a) {
00167 insert_range(end(), first, last, typename std::iterator_traits<Iter>::iterator_category());
00168 }
00169
00171
00174 pod_vector(const pod_vector& other) : ebo_(other.size(), other.get_allocator()) {
00175 std::memcpy(ebo_.buf, other.begin(), other.size()*sizeof(T));
00176 ebo_.size = other.size();
00177 }
00178
00179 pod_vector& operator=(const pod_vector& other) {
00180 if (this != &other) {
00181 assign(other.begin(), other.end());
00182 }
00183 return *this;
00184 }
00185
00187
00190 ~pod_vector() { }
00191
00196
00198 size_type size() const { return ebo_.size; }
00200 size_type max_size() const {
00201 typename allocator_type::size_type x = get_allocator().max_size();
00202 std::size_t y = size_type(-1)/sizeof(T);
00203 return static_cast<size_type>(std::min(std::size_t(x), y));
00204 }
00206 size_type capacity() const { return ebo_.cap; }
00208 bool empty() const { return ebo_.size == 0; }
00209
00210 const_iterator begin() const { return ebo_.buf; }
00211 const_iterator end() const { return ebo_.buf+ebo_.size;}
00212 const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
00213 const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
00214
00215 iterator begin() { return ebo_.buf; }
00216 iterator end() { return ebo_.buf+ebo_.size; }
00217 reverse_iterator rbegin() { return reverse_iterator(end()); }
00218 reverse_iterator rend() { return reverse_iterator(begin()); }
00219
00221 allocator_type get_allocator() const { return ebo_; }
00222
00224
00228
00230
00233 reference operator[](size_type n) {
00234 assert(n < size());
00235 return ebo_.buf[n];
00236 }
00237
00239
00242 const_reference operator[](size_type n) const {
00243 assert(n < size());
00244 return ebo_.buf[n];
00245 }
00246
00248 const_reference at(size_type n) const {
00249 if (n < size()) return ebo_.buf[n];
00250 throw std::range_error("pod_vector::at");
00251 }
00253 reference at(size_type n) {
00254 if (n < size()) return ebo_.buf[n];
00255 throw std::range_error("pod_vector::at");
00256 }
00257
00259 reference front() { assert(!empty()); return *ebo_.buf; }
00261 const_reference front() const { assert(!empty()); return *ebo_.buf; }
00262
00264 reference back() { assert(!empty()); return ebo_.buf[ebo_.size-1]; }
00265
00267 const_reference back() const { assert(!empty()); return ebo_.buf[ebo_.size-1]; }
00268
00270
00274
00276
00279 void clear() { ebo_.size = 0; }
00280
00281 void assign(size_type n, const T& val) {
00282 clear();
00283 insert(end(), n, val);
00284 }
00285
00286 template <class Iter>
00287 void assign(Iter first, Iter last) {
00288 clear();
00289 insert(end(), first, last);
00290 }
00291
00293
00300 iterator erase(iterator pos) {
00301 assert(!empty() && pos != end());
00302 erase(pos, pos + 1);
00303 return pos;
00304 }
00305
00307
00310 iterator erase(iterator first, iterator last) {
00311 if (end() - last > 0) {
00312 std::memmove(first, last, (end() - last) * sizeof(T));
00313 }
00314 ebo_.size -= static_cast<size_type>(last - first);
00315 return first;
00316 }
00317
00319
00326 void resize(size_type ns, const T& val = T()) {
00327 if (ns > size()) {
00328 ns <= capacity() ? detail::fill(end(), end()+(ns-size()), val) : append_realloc(ns-size(), val);
00329 }
00330 ebo_.size = ns;
00331 }
00332
00334
00342 void reserve(size_type n) {
00343 if (n > capacity()) {
00344 T* temp = ebo_.allocate(n);
00345 std::memcpy(temp, ebo_.buf, size()*sizeof(T));
00346 ebo_.release();
00347 ebo_.buf = temp;
00348 ebo_.cap = n;
00349 }
00350 }
00351
00352 void swap(pod_vector& other) {
00353 std::swap(ebo_.buf, other.ebo_.buf);
00354 std::swap(ebo_.size, other.ebo_.size);
00355 std::swap(ebo_.cap, other.ebo_.cap);
00356 }
00357
00359 void push_back(const T& x) {
00360 if (size() < capacity()) {
00361 new ((ebo_.buf+ebo_.size++)) T(x);
00362 }
00363 else {
00364 append_realloc(1, x);
00365 }
00366 }
00367
00369
00372 void pop_back() {
00373 assert(!empty());
00374 --ebo_.size;
00375 }
00376
00378
00385 iterator insert(iterator pos, const T& val) {
00386 return insert(pos, (size_type)1, val);
00387 }
00388
00390
00393 iterator insert(iterator pos, size_type n, const T& val) {
00394 size_type off = static_cast<size_type>(pos-begin());
00395 insert_impl(pos, n, detail::Fill<T>(val));
00396 return ebo_.buf + off;
00397 }
00398
00400
00407 template <class Iter>
00408 void insert(iterator pos, Iter first, Iter last, typename detail::disable_if<detail::IterType<Iter>::num>::type* = 0) {
00409 insert_range(pos, first, last, typename std::iterator_traits<Iter>::iterator_category());
00410 }
00411
00412
00417
00419
00427 void resize_no_init(size_type ns) {
00428 reserve(ns);
00429 ebo_.size = ns;
00430 }
00432 private:
00433 size_type grow_size(size_type n) {
00434 size_type new_cap = size() + n;
00435 assert(new_cap > size() && "pod_vector: max size exceeded!");
00436 assert(new_cap > capacity());
00437 if (new_cap < 4) new_cap = 1 << (new_cap+1);
00438 size_type x = (capacity()*3)>>1;
00439 if (new_cap < x) new_cap = x;
00440 return new_cap;
00441 }
00442 void append_realloc(size_type n, const T& x) {
00443 size_type new_cap = grow_size(n);
00444 pointer temp = ebo_.allocate(new_cap);
00445 std::memcpy(temp, ebo_.buf, size()*sizeof(T));
00446 detail::fill(temp+size(), temp+size()+n, x);
00447 ebo_.release();
00448 ebo_.buf = temp;
00449 ebo_.cap = new_cap;
00450 ebo_.size+= n;
00451 }
00452 void move_right(iterator pos, size_type n) {
00453 assert( (pos || n == 0) && (ebo_.eos() - pos) >= (int)n);
00454 std::memmove(pos + n, pos, (end() - pos) * sizeof(T));
00455 }
00456 template <class It>
00457 void insert_range(iterator pos, It first, It last, std::random_access_iterator_tag,
00458 typename detail::disable_if<detail::same_type<pointer, It>::value == 0 && detail::same_type<const_pointer, It>::value == 0>::type* = 0) {
00459 assert( (first < begin() || first >= end()) && "pod_vec::insert(): Precondition violated!");
00460 typename allocator_type::difference_type diff = std::distance(first, last);
00461 assert(diff == 0 || (static_cast<size_type>(size()+diff) > size() && "pod_vector: max size exceeded!"));
00462 insert_impl(pos, static_cast<size_type>(diff), detail::Memcpy<T>(first));
00463 }
00464 template <class It>
00465 void insert_range(iterator pos, It first, It last, std::forward_iterator_tag) {
00466 typename allocator_type::difference_type diff = std::distance(first, last);
00467 assert(diff == 0 || (static_cast<size_type>(size()+diff) > size() && "pod_vector: max size exceeded!"));
00468 insert_impl(pos, static_cast<size_type>(diff), detail::Copy<It>(first, last));
00469 }
00470 template <class Iter>
00471 void insert_range(iterator pos, Iter first, Iter last, std::input_iterator_tag) {
00472 pod_vector<T> temp;
00473 while (first != last) temp.push_back(*first++);
00474 insert(pos, temp.begin(), temp.end());
00475 }
00476
00477
00478
00479
00480 template <class ST, class P>
00481 void insert_impl(iterator pos, ST n, const P& pred) {
00482 assert(n == 0 || (size()+n) > size() );
00483 if (size()+n <= capacity()) {
00484 move_right(pos, n);
00485 pred(pos, n);
00486 ebo_.size += n;
00487 }
00488 else {
00489 size_type new_cap = grow_size(n);
00490 pointer temp = ebo_.allocate(new_cap);
00491 size_type prefix = static_cast<size_type>(pos-begin());
00492
00493 std::memcpy(temp, begin(), prefix*sizeof(T));
00494
00495 pred(temp+prefix, n);
00496
00497 std::memcpy(temp+prefix+n, pos, (end()-pos)*sizeof(T));
00498 ebo_.release();
00499 ebo_.buf = temp;
00500 ebo_.size+= n;
00501 ebo_.cap = new_cap;
00502 }
00503 }
00504 struct ebo : public Allocator {
00505 typedef typename this_type::size_type size_type;
00506 typedef typename this_type::allocator_type A;
00507 pointer buf;
00508 size_type size;
00509 size_type cap;
00510 ebo(size_type n, const Allocator& a) : Allocator(a), buf(0), size(0), cap(n) {
00511 if (n > 0) { buf = A::allocate(n); }
00512 }
00513 ~ebo() { release(); }
00514 void release() { if (buf) A::deallocate(buf, cap); }
00515 T* eos() const { return buf + cap; }
00516 } ebo_;
00517 };
00518
00519 template <class T, class A>
00520 inline bool operator==(const pod_vector<T, A>& lhs, const pod_vector<T, A>& rhs) {
00521 return lhs.size() == rhs.size()
00522 && std::equal(lhs.begin(), lhs.end(), rhs.begin());
00523 }
00524
00525 template <class T, class A>
00526 inline bool operator!=(const pod_vector<T, A>& lhs, const pod_vector<T, A>& rhs) {
00527 return ! (lhs == rhs);
00528 }
00529
00530 template <class T, class A>
00531 inline bool operator<(const pod_vector<T, A>& lhs, const pod_vector<T, A>& rhs) {
00532 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
00533 }
00534
00535 template <class T, class A>
00536 inline bool operator>(const pod_vector<T, A>& lhs, const pod_vector<T, A>& rhs) {
00537 return rhs < lhs;
00538 }
00539
00540 template <class T, class A>
00541 inline bool operator<=(const pod_vector<T, A>& lhs, const pod_vector<T, A>& rhs) {
00542 return !(rhs < lhs);
00543 }
00544
00545 template <class T, class A>
00546 inline bool operator>=(const pod_vector<T, A>& lhs, const pod_vector<T, A>& rhs) {
00547 return !(lhs < rhs);
00548 }
00549
00550 template <class T, class A>
00551 inline void swap(pod_vector<T, A>& lhs, pod_vector<T, A>& rhs) {
00552 lhs.swap(rhs);
00553 }
00554
00555 }
00556
00557 #endif
00558