00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef BK_LIB_LEFT_RIGHT_SEQUENCE_INCLUDED
00021 #define BK_LIB_LEFT_RIGHT_SEQUENCE_INCLUDED
00022 #ifdef _MSC_VER
00023 #pragma warning( push )
00024 #pragma warning (disable : 4200)
00025 #endif
00026 #include "type_manip.h"
00027 #include <iterator>
00028 #include <cassert>
00029 #include <cstring>
00030 namespace bk_lib { namespace detail {
00031
00032
00033
00034 template <class L, class R>
00035 class left_right_rep {
00036 public:
00037 typedef L left_type;
00038 typedef R right_type;
00039 typedef unsigned int size_type;
00040 typedef L* left_iterator;
00041 typedef const L* const_left_iterator;
00042 typedef std::reverse_iterator<R*> right_iterator;
00043 typedef std::reverse_iterator<const R*> const_right_iterator;
00044
00045 typedef typename bk_lib::detail::align_of<left_type>::type left_align_type;
00046 typedef typename bk_lib::detail::align_of<right_type>::type right_align_type;
00047
00048 typedef typename bk_lib::detail::if_then_else<
00049 sizeof(left_type) >= sizeof(right_type),
00050 left_type,
00051 right_type>::type max_type;
00052 typedef typename bk_lib::detail::if_then_else<
00053 sizeof(left_align_type) >= sizeof(right_align_type),
00054 left_align_type,
00055 right_align_type>::type align_type;
00056
00057 left_right_rep() : buf_(0), cap_(0), free_(0), left_(0), right_(0) {}
00058
00059 bool empty() const { return left_ == 0 && right_ == cap_; }
00060 size_type left_size() const { return left_/sizeof(left_type); }
00061 size_type right_size() const { return (cap_-right_)/sizeof(right_type); }
00062 size_type size() const { return left_size() + right_size(); }
00063 size_type left_capacity() const { return (cap_ / sizeof(left_type)); }
00064 size_type right_capacity()const { return (cap_ / sizeof(right_type)); }
00065 const_left_iterator left_begin() const { return const_left_iterator(reinterpret_cast<const left_type*>(begin())); }
00066 const_left_iterator left_end() const { return const_left_iterator(reinterpret_cast<const left_type*>(buf_+left_)); }
00067 left_iterator left_begin() { return left_iterator(reinterpret_cast<left_type*>(begin())); }
00068 left_iterator left_end() { return left_iterator(reinterpret_cast<left_type*>(buf_+left_)); }
00069 const_right_iterator right_begin()const { return const_right_iterator(reinterpret_cast<const right_type*>(end())); }
00070 const_right_iterator right_end() const { return const_right_iterator(reinterpret_cast<const right_type*>(buf_+right_)); }
00071 right_iterator right_begin() { return right_iterator(reinterpret_cast<right_type*>(end())); }
00072 right_iterator right_end() { return right_iterator(reinterpret_cast<right_type*>(buf_+right_)); }
00073 const left_type& left(size_type i)const { return *(left_begin()+i); }
00074 left_type& left(size_type i) { return *(left_begin()+i); }
00075
00076 void clear(bool releaseMem = false) {
00077 if (releaseMem) {
00078 release();
00079 buf_ = 0;
00080 cap_ = 0;
00081 free_ = 0;
00082 }
00083 left_ = 0;
00084 right_= cap_;
00085 }
00086 void push_left(const left_type& x) {
00087 if ((left_ + sizeof(left_type)) > right_) {
00088 realloc();
00089 }
00090 new (left())left_type(x);
00091 left_ += sizeof(left_type);
00092 }
00093
00094 void push_right(const right_type& x) {
00095 if ( (left_ + sizeof(right_type)) > right_ ) {
00096 realloc();
00097 }
00098 right_ -= sizeof(right_type);
00099 new (right()) right_type(x);
00100 }
00101 void pop_left() {
00102 assert(left_size() != 0);
00103 left_ -= sizeof(left_type);
00104 }
00105 void pop_right() {
00106 assert(right_size() != 0);
00107 right_ += sizeof(right_type);
00108 }
00109
00110 void erase_left(left_iterator it) {
00111 if (it != left_end()) {
00112 left_iterator x = it++;
00113 std::memmove(x, it, (left_end()-it)*sizeof(left_type));
00114 left_ -= sizeof(left_type);
00115 }
00116 }
00117 void erase_left_unordered(left_iterator it) {
00118 if (it != left_end()) {
00119 left_ -= sizeof(left_type);
00120 *it = *reinterpret_cast<left_type*>(left());
00121 }
00122 }
00123 void erase_right(right_iterator it) {
00124 if (it != right_end()) {
00125 right_type* r = (++it).base();
00126 right_type* b = reinterpret_cast<right_type*>(right());
00127 assert(r >= b);
00128 std::memmove(b+1, b, (r-b)*sizeof(right_type));
00129 right_ += sizeof(right_type);
00130 }
00131 }
00132 void erase_right_unordered(right_iterator it) {
00133 if (it != right_end()) {
00134 *it = *reinterpret_cast<right_type*>(right());
00135 right_+= sizeof(right_type);
00136 }
00137 }
00138 void shrink_left(left_iterator it) {
00139 left_ = static_cast<size_type>((it - left_begin())*sizeof(left_type));
00140 }
00141 void shrink_right(right_iterator it) {
00142 buf_type* x = reinterpret_cast<buf_type*>(it.base());
00143 right_ = static_cast<size_type>(x - begin());
00144 }
00145 enum { block_size = ((sizeof(max_type)+(sizeof(align_type)-1)) / sizeof(align_type)) * sizeof(align_type) };
00146 protected:
00147 left_right_rep(const left_right_rep&) { }
00148 left_right_rep& operator=(const left_right_rep&) { return *this; }
00149 typedef unsigned char buf_type;
00150 buf_type* begin() { return buf_; }
00151 const buf_type* begin()const { return buf_; }
00152 buf_type* end() { return buf_+cap_; }
00153 const buf_type* end() const { return buf_+cap_; }
00154 buf_type* left() { return buf_+left_; }
00155 buf_type* right() { return buf_+right_; }
00156 size_type capacity()const { return cap_ / block_size; }
00157 size_type raw_size()const { return left_ + (cap_-right_); }
00158 void release() { if (free_ != 0) { ::operator delete(buf_); } }
00159 void realloc();
00160 buf_type* buf_;
00161 size_type cap_ : 31;
00162 size_type free_: 1;
00163 size_type left_;
00164 size_type right_;
00165 };
00166
00167 template <class L, class R>
00168 void left_right_rep<L, R>::realloc() {
00169 size_type new_cap = ((capacity()*3)>>1) * block_size;
00170 size_type min_cap = 4 * block_size;
00171 if (new_cap < min_cap) new_cap = min_cap;
00172 buf_type* temp = (buf_type*)::operator new(new_cap*sizeof(buf_type));
00173
00174 std::memcpy(temp, begin(), left_size()*sizeof(L));
00175
00176 size_type r = cap_ - right_;
00177 std::memcpy(temp+(new_cap-r), right(), right_size() * sizeof(R));
00178
00179 release();
00180 buf_ = temp;
00181 cap_ = new_cap;
00182 free_ = 1;
00183 right_ = new_cap - r;
00184 }
00185
00186
00187 template <class L, class R>
00188 struct no_inline_buffer : public left_right_rep<L, R> {
00189 typedef typename left_right_rep<L, R>::buf_type buf_type;
00190 enum { inline_raw_cap = 0 };
00191 buf_type* extra() { return 0; }
00192 };
00193
00194
00195 template <class L, class R, unsigned cap>
00196 struct with_inline_buffer : public left_right_rep<L, R> {
00197 typedef typename left_right_rep<L, R>::buf_type buf_type;
00198 typedef typename left_right_rep<L, R>::align_type align_type;
00199 enum { inline_raw_cap = cap };
00200 buf_type* extra() { return rep_.mem; }
00201 union X {
00202 align_type align;
00203 buf_type mem[inline_raw_cap];
00204 } rep_;
00205 };
00206
00207
00208
00209 template <class L, class R, unsigned i>
00210 struct select_base {
00211 private:
00212 typedef unsigned char buf_type;
00213 typedef left_right_rep<L, R> base_type;
00214 typedef typename base_type::size_type size_type;
00215 typedef typename base_type::align_type align_type;
00216 typedef no_inline_buffer<L, R> no_extra_type;
00217 typedef with_inline_buffer<L, R, sizeof(align_type)> with_extra_type;
00218
00219 enum { padding = sizeof(with_extra_type) - (sizeof(no_extra_type)+sizeof(align_type)) };
00220 enum { size_with_pad = sizeof(no_extra_type) + padding };
00221 enum { store_extra = (i > size_with_pad) && (i - size_with_pad) >= base_type::block_size };
00222 enum { inline_raw_cap = store_extra ? ((i - size_with_pad)/base_type::block_size)*base_type::block_size : 0 };
00223 public:
00224 typedef typename if_then_else<
00225 store_extra!=0,
00226 with_inline_buffer<L, R, inline_raw_cap>,
00227 no_inline_buffer<L, R> >::type type;
00228 };
00229
00230
00231 }
00232
00234
00244 template <class L, class R, unsigned i>
00245 class left_right_sequence : public bk_lib::detail::select_base<L, R, i>::type {
00246 public:
00247 typedef typename bk_lib::detail::select_base<L, R, i>::type base_type;
00248 typedef typename base_type::left_type left_type;
00249 typedef typename base_type::right_type right_type;
00250 typedef typename base_type::size_type size_type;
00251 typedef typename base_type::align_type align_type;
00252 typedef typename base_type::max_type max_type;
00253 typedef typename base_type::buf_type buf_type;
00254
00255 typedef typename base_type::left_iterator left_iterator;
00256 typedef typename base_type::const_left_iterator const_left_iterator;
00257 typedef typename base_type::right_iterator right_iterator;
00258 typedef typename base_type::const_right_iterator const_right_iterator;
00259
00260 left_right_sequence() {
00261 this->buf_ = this->extra();
00262 this->cap_ = base_type::inline_raw_cap;
00263 this->free_ = 0;
00264 this->left_ = 0;
00265 this->right_= base_type::inline_raw_cap;
00266 }
00267 left_right_sequence(const left_right_sequence& other);
00268 ~left_right_sequence() { this->release(); }
00269 left_right_sequence& operator=(const left_right_sequence&);
00270
00271 void try_shrink() {
00272 if (this->raw_size() <= base_type::inline_raw_cap && this->buf_ != this->extra()) {
00273 buf_type* e = this->extra();
00274 size_type c = base_type::inline_raw_cap;
00275 size_type r = c - (this->right_size()*sizeof(right_type));
00276 std::memcpy(e, this->begin(), this->left_size() * sizeof(left_type));
00277 std::memcpy(e+r, this->right(), this->right_size()* sizeof(right_type));
00278 this->release();
00279 this->buf_ = e;
00280 this->cap_ = c;
00281 this->free_ = 0;
00282 this->right_= r;
00283 }
00284 }
00285 void move(left_right_sequence& other) {
00286 this->clear(true);
00287 if (other.raw_size() <= base_type::inline_raw_cap) {
00288 copy(other);
00289 other.clear(true);
00290 }
00291 else {
00292 this->buf_ = other.buf_;
00293 this->cap_ = other.cap_;
00294 this->free_ = other.free_;
00295 this->left_ = other.left_;
00296 this->right_ = other.right_;
00297 other.buf_ = other.extra();
00298 other.cap_ = base_type::inline_raw_cap;
00299 other.free_ = 0;
00300 other.left_ = 0;
00301 other.right_= base_type::inline_raw_cap;
00302 }
00303 }
00304 private:
00305 void copy(const left_right_sequence&);
00306 };
00307
00308 template <class L, class R, unsigned i>
00309 void left_right_sequence<L, R, i>::copy(const left_right_sequence& other) {
00310 size_type os = other.raw_size();
00311 if ( os <= base_type::inline_raw_cap ) {
00312 this->buf_ = this->extra();
00313 this->cap_ = base_type::inline_raw_cap;
00314 this->free_= 0;
00315 }
00316 else {
00317 os = ((os + (base_type::block_size-1)) / base_type::block_size) * base_type::block_size;
00318 this->buf_ = (buf_type*)::operator new(os*sizeof(buf_type));
00319 this->cap_ = os;
00320 this->free_= 1;
00321 }
00322 this->left_ = other.left_;
00323 this->right_= this->cap_ - (other.right_size()*sizeof(right_type));
00324 std::memcpy(this->begin(), other.begin(), other.left_size()*sizeof(left_type));
00325 std::memcpy(this->right(), const_cast<left_right_sequence&>(other).right(), other.right_size()*sizeof(right_type));
00326 }
00327
00328 template <class L, class R, unsigned i>
00329 left_right_sequence<L, R, i>::left_right_sequence(const left_right_sequence& other) : base_type(other) {
00330 copy(other);
00331 }
00332
00333 template <class L, class R, unsigned i>
00334 left_right_sequence<L, R, i>& left_right_sequence<L, R, i>::operator=(const left_right_sequence& other) {
00335 if (this != &other) {
00336 this->release();
00337 copy(other);
00338 }
00339 return *this;
00340 }
00341
00342
00343 }
00344
00345
00346 #ifdef _MSC_VER
00347 #pragma warning(pop)
00348 #endif
00349 #endif
00350