00001 #ifndef _PFC_LIST_H_
00002 #define _PFC_LIST_H_
00003
00004 namespace pfc {
00005
00006 template<typename T>
00007 class NOVTABLE list_base_const_t {
00008 private: typedef list_base_const_t<T> t_self;
00009 public:
00010 virtual t_size get_count() const = 0;
00011 virtual void get_item_ex(T& p_out, t_size n) const = 0;
00012
00013 inline t_size get_size() const {return get_count();}
00014
00015 inline T get_item(t_size n) const {T temp; get_item_ex(temp,n); return temp;}
00016 inline T operator[](t_size n) const {T temp; get_item_ex(temp,n); return temp;}
00017
00018 template<typename t_compare>
00019 t_size find_duplicates_sorted_t(t_compare p_compare,bit_array_var & p_out) const
00020 {
00021 return pfc::find_duplicates_sorted_t<list_base_const_t<T> const &,t_compare>(*this,get_count(),p_compare,p_out);
00022 }
00023
00024 template<typename t_compare,typename t_permutation>
00025 t_size find_duplicates_sorted_permutation_t(t_compare p_compare,t_permutation const & p_permutation,bit_array_var & p_out)
00026 {
00027 return pfc::find_duplicates_sorted_permutation_t<list_base_const_t<T> const &,t_compare,t_permutation>(*this,get_count(),p_compare,p_permutation,p_out);
00028 }
00029
00030 template<typename t_search>
00031 t_size find_item(const t_search & p_item) const
00032 {
00033 t_size n,max = get_count();
00034 for(n=0;n<max;n++)
00035 if (get_item(n)==p_item) return n;
00036 return ~0;
00037 }
00038
00039 template<typename t_search>
00040 inline bool have_item(const t_search & p_item) const {return find_item<t_search>(p_item)!=~0;}
00041
00042
00043 template<typename t_compare, typename t_param>
00044 bool bsearch_t(t_compare p_compare,t_param const & p_param,t_size &p_index) const {
00045 return pfc::bsearch_t(get_count(),*this,p_compare,p_param,p_index);
00046 }
00047
00048 template<typename t_compare,typename t_param,typename t_permutation>
00049 bool bsearch_permutation_t(t_compare p_compare,t_param const & p_param,const t_permutation & p_permutation,t_size & p_index) {
00050 return pfc::bsearch_permutation_t(get_count(),*this,p_compare,p_param,p_permutation,p_index);
00051 }
00052
00053 template<typename t_compare,typename t_permutation>
00054 void sort_get_permutation_t(t_compare p_compare,t_permutation const & p_permutation) const {
00055 pfc::sort_get_permutation_t<list_base_const_t<T>,t_compare,t_permutation>(*this,p_compare,get_count(),p_permutation);
00056 }
00057
00058 template<typename t_compare,typename t_permutation>
00059 void sort_stable_get_permutation_t(t_compare p_compare,t_permutation const & p_permutation) const {
00060 pfc::sort_stable_get_permutation_t<list_base_const_t<T>,t_compare,t_permutation>(*this,p_compare,get_count(),p_permutation);
00061 }
00062
00063 template<typename t_callback>
00064 void enumerate(t_callback & p_callback) const {
00065 for(t_size n = 0, m = get_count(); n < m; ++n ) {
00066 p_callback( (*this)[n] );
00067 }
00068 }
00069
00070 protected:
00071 list_base_const_t() {}
00072 ~list_base_const_t() {}
00073 private:
00074 const t_self & operator=(const t_self &) {throw pfc::exception_not_implemented();}
00075 };
00076
00077
00078 template<typename T>
00079 class list_single_ref_t : public list_base_const_t<T>
00080 {
00081 public:
00082 list_single_ref_t(const T & p_item,t_size p_count = 1) : m_item(p_item), m_count(p_count) {}
00083 t_size get_count() const {return m_count;}
00084 void get_item_ex(T& p_out,t_size n) const {PFC_ASSERT(n<m_count); p_out = m_item;}
00085 private:
00086 const T & m_item;
00087 t_size m_count;
00088 };
00089
00090 template<typename T>
00091 class list_partial_ref_t : public list_base_const_t<T>
00092 {
00093 public:
00094 list_partial_ref_t(const list_base_const_t<T> & p_list,t_size p_base,t_size p_count)
00095 : m_list(p_list), m_base(p_base), m_count(p_count)
00096 {
00097 PFC_ASSERT(m_base + m_count <= m_list.get_count());
00098 }
00099
00100 private:
00101 const list_base_const_t<T> & m_list;
00102 t_size m_base,m_count;
00103
00104 t_size get_count() const {return m_count;}
00105 void get_item_ex(T & p_out,t_size n) const {m_list.get_item_ex(p_out,n+m_base);}
00106 };
00107
00108 template<typename T,typename A>
00109 class list_const_array_t : public list_base_const_t<T>
00110 {
00111 public:
00112 inline list_const_array_t(A p_data,t_size p_count) : m_data(p_data), m_count(p_count) {}
00113 t_size get_count() const {return m_count;}
00114 void get_item_ex(T & p_out,t_size n) const {p_out = m_data[n];}
00115 private:
00116 A m_data;
00117 t_size m_count;
00118 };
00119
00120 template<typename to,typename from>
00121 class list_const_cast_t : public list_base_const_t<to>
00122 {
00123 public:
00124 list_const_cast_t(const list_base_const_t<from> & p_from) : m_from(p_from) {}
00125 t_size get_count() const {return m_from.get_count();}
00126 void get_item_ex(to & p_out,t_size n) const
00127 {
00128 from temp;
00129 m_from.get_item_ex(temp,n);
00130 p_out = temp;
00131 }
00132 private:
00133 const list_base_const_t<from> & m_from;
00134 };
00135
00136 template<typename T,typename A>
00137 class ptr_list_const_array_t : public list_base_const_t<T*>
00138 {
00139 public:
00140 inline ptr_list_const_array_t(A p_data,t_size p_count) : m_data(p_data), m_count(p_count) {}
00141 t_size get_count() const {return m_count;}
00142 void get_item_ex(T* & p_out,t_size n) const {p_out = &m_data[n];}
00143 private:
00144 A m_data;
00145 t_size m_count;
00146 };
00147 template<typename T>
00148 class list_const_ptr_t : public list_base_const_t<T>
00149 {
00150 public:
00151 inline list_const_ptr_t(const T * p_data,t_size p_count) : m_data(p_data), m_count(p_count) {}
00152 t_size get_count() const {return m_count;}
00153 void get_item_ex(T & p_out,t_size n) const {p_out = m_data[n];}
00154 private:
00155 const T * m_data;
00156 t_size m_count;
00157 };
00158
00159 template<typename T>
00160 class NOVTABLE list_base_t : public list_base_const_t<T> {
00161 private:
00162 typedef list_base_t<T> t_self;
00163 public:
00164 class NOVTABLE sort_callback
00165 {
00166 public:
00167 virtual int compare(const T& p_item1,const T& p_item2) = 0;
00168 };
00169
00170 virtual void filter_mask(const bit_array & mask) = 0;
00171 virtual t_size insert_items(const list_base_const_t<T> & items,t_size base) = 0;
00172 virtual void reorder_partial(t_size p_base,const t_size * p_data,t_size p_count) = 0;
00173 virtual void sort(sort_callback & p_callback) = 0;
00174 virtual void sort_stable(sort_callback & p_callback) = 0;
00175 virtual void replace_item(t_size p_index,const T& p_item) = 0;
00176 virtual void swap_item_with(t_size p_index,T & p_item) = 0;
00177 virtual void swap_items(t_size p_index1,t_size p_index2) = 0;
00178
00179 inline void reorder(const t_size * p_data) {reorder_partial(0,p_data,this->get_count());}
00180
00181 inline t_size insert_item(const T & item,t_size base) {return insert_items(list_single_ref_t<T>(item),base);}
00182 t_size insert_items_repeat(const T & item,t_size num,t_size base) {return insert_items(list_single_ref_t<T>(item,num),base);}
00183 inline t_size add_items_repeat(T item,t_size num) {return insert_items_repeat(item,num,this->get_count());}
00184 t_size insert_items_fromptr(const T* source,t_size num,t_size base) {return insert_items(list_const_ptr_t<T>(source,num),base);}
00185 inline t_size add_items_fromptr(const T* source,t_size num) {return insert_items_fromptr(source,num,this->get_count());}
00186
00187 inline t_size add_items(const list_base_const_t<T> & items) {return insert_items(items,this->get_count());}
00188 inline t_size add_item(const T& item) {return insert_item(item,this->get_count());}
00189
00190 inline void remove_mask(const bit_array & mask) {filter_mask(bit_array_not(mask));}
00191 inline void remove_all() {filter_mask(bit_array_false());}
00192 inline void truncate(t_size val) {if (val < this->get_count()) remove_mask(bit_array_range(val,this->get_count()-val,true));}
00193
00194 inline T replace_item_ex(t_size p_index,const T & p_item) {T ret = p_item;swap_item_with(p_index,ret);return ret;}
00195
00196 inline T operator[](t_size n) const {return this->get_item(n);}
00197
00198 template<typename t_compare>
00199 class sort_callback_impl_t : public sort_callback
00200 {
00201 public:
00202 sort_callback_impl_t(t_compare p_compare) : m_compare(p_compare) {}
00203 int compare(const T& p_item1,const T& p_item2) {return m_compare(p_item1,p_item2);}
00204 private:
00205 t_compare m_compare;
00206 };
00207
00208 class sort_callback_auto : public sort_callback
00209 {
00210 public:
00211 int compare(const T& p_item1,const T& p_item2) {return pfc::compare_t(p_item1,p_item2);}
00212 };
00213
00214 void sort() {sort(sort_callback_auto());}
00215 template<typename t_compare> void sort_t(t_compare p_compare) {sort(sort_callback_impl_t<t_compare>(p_compare));}
00216 template<typename t_compare> void sort_stable_t(t_compare p_compare) {sort_stable(sort_callback_impl_t<t_compare>(p_compare));}
00217
00218 template<typename t_compare> void sort_remove_duplicates_t(t_compare p_compare)
00219 {
00220 sort_t<t_compare>(p_compare);
00221 bit_array_bittable array(this->get_count());
00222 if (this->template find_duplicates_sorted_t<t_compare>(p_compare,array) > 0)
00223 remove_mask(array);
00224 }
00225
00226 template<typename t_compare> void sort_stable_remove_duplicates_t(t_compare p_compare)
00227 {
00228 sort_stable_t<t_compare>(p_compare);
00229 bit_array_bittable array(this->get_count());
00230 if (this->template find_duplicates_sorted_t<t_compare>(p_compare,array) > 0)
00231 remove_mask(array);
00232 }
00233
00234
00235 template<typename t_compare> void remove_duplicates_t(t_compare p_compare)
00236 {
00237 order_helper order(this->get_count());
00238 sort_get_permutation_t<t_compare,order_helper&>(p_compare,order);
00239 bit_array_bittable array(this->get_count());
00240 if (this->template find_duplicates_sorted_permutation_t<t_compare,order_helper const&>(p_compare,order,array) > 0)
00241 remove_mask(array);
00242 }
00243
00244 template<typename t_func>
00245 void for_each(t_func p_func) {
00246 t_size n,max=this->get_count();
00247 for(n=0;n<max;n++) p_func(this->get_item(n));
00248 }
00249
00250 template<typename t_func>
00251 void for_each(t_func p_func,const bit_array & p_mask) {
00252 t_size n,max=this->get_count();
00253 for(n=p_mask.find(true,0,max);n<max;n=p_mask.find(true,n+1,max-n-1)) {
00254 p_func(this->get_item(n));
00255 }
00256 }
00257
00258 template<typename t_releasefunc>
00259 void remove_mask_ex(const bit_array & p_mask,t_releasefunc p_func) {
00260 this->template for_each<t_releasefunc>(p_func,p_mask);
00261 remove_mask(p_mask);
00262 }
00263
00264 template<typename t_releasefunc>
00265 void remove_all_ex(t_releasefunc p_func) {
00266 this->template for_each<t_releasefunc>(p_func);
00267 remove_all();
00268 }
00269
00270 const t_self & operator=(const t_self & p_source) {remove_all(); add_items(p_source);return *this;}
00271 protected:
00272 list_base_t() {}
00273 ~list_base_t() {}
00274 };
00275
00276
00277 template<typename T,typename t_storage>
00278 class list_impl_t : public list_base_t<T>
00279 {
00280 public:
00281 list_impl_t() {}
00282 list_impl_t(const list_impl_t<T,t_storage> & p_source) { *this = p_source; }
00283
00284 void prealloc(t_size count) {m_buffer.prealloc(count);}
00285
00286 void set_count(t_size p_count) {m_buffer.set_size(p_count);}
00287 void set_size(t_size p_count) {m_buffer.set_size(p_count);}
00288
00289 t_size insert_item(const T& item,t_size idx)
00290 {
00291 t_size max = m_buffer.get_size();
00292 if (idx > max) idx = max;
00293 max++;
00294 m_buffer.set_size(max);
00295 t_size n;
00296 for(n=max-1;n>idx;n--)
00297 m_buffer[n]=m_buffer[n-1];
00298 m_buffer[idx]=item;
00299 return idx;
00300 }
00301
00302 T remove_by_idx(t_size idx)
00303 {
00304 T ret = m_buffer[idx];
00305 t_size n;
00306 t_size max = m_buffer.get_size();
00307 for(n=idx+1;n<max;n++)
00308 {
00309 pfc::swap_t(m_buffer[n-1],m_buffer[n]);
00310 }
00311 m_buffer.set_size(max-1);
00312 return ret;
00313 }
00314
00315
00316 inline void get_item_ex(T& p_out,t_size n) const
00317 {
00318 PFC_ASSERT(n>=0);
00319 PFC_ASSERT(n<get_count());
00320 p_out = m_buffer[n];
00321 }
00322
00323 inline const T& get_item_ref(t_size n) const
00324 {
00325 PFC_ASSERT(n>=0);
00326 PFC_ASSERT(n<get_count());
00327 return m_buffer[n];
00328 }
00329
00330 inline T get_item(t_size n) const
00331 {
00332 PFC_ASSERT(n >= 0);
00333 PFC_ASSERT(n < get_count() );
00334 return m_buffer[n];
00335 };
00336
00337 inline t_size get_count() const {return m_buffer.get_size();}
00338 inline t_size get_size() const {return get_count();}
00339
00340 inline const T & operator[](t_size n) const
00341 {
00342 PFC_ASSERT(n>=0);
00343 PFC_ASSERT(n<get_count());
00344 return m_buffer[n];
00345 }
00346
00347 inline const T* get_ptr() const {return m_buffer.get_ptr();}
00348 inline T* get_ptr() {return m_buffer.get_ptr();}
00349
00350 inline T& operator[](t_size n) {return m_buffer[n];}
00351
00352 inline void remove_from_idx(t_size idx,t_size num)
00353 {
00354 remove_mask(bit_array_range(idx,num));
00355 }
00356
00357 t_size insert_items(const list_base_const_t<T> & source,t_size base)
00358 {
00359 t_size count = get_count();
00360 if (base>count) base = count;
00361 t_size num = source.get_count();
00362 m_buffer.set_size(count+num);
00363 if (count > base)
00364 {
00365 t_size n;
00366 for(n=count-1;(int)n>=(int)base;n--)
00367 {
00368 pfc::swap_t(m_buffer[n+num],m_buffer[n]);
00369 }
00370 }
00371
00372 {
00373 t_size n;
00374 for(n=0;n<num;n++)
00375 {
00376 source.get_item_ex(m_buffer[n+base],n);
00377 }
00378 }
00379 return base;
00380
00381 }
00382
00383 void get_items_mask(list_impl_t<T,t_storage> & out,const bit_array & mask)
00384 {
00385 t_size n,count = get_count();
00386 for_each_bit_array(n,mask,true,0,count)
00387 out.add_item(m_buffer[n]);
00388 }
00389
00390 void filter_mask(const bit_array & mask)
00391 {
00392 t_size n,count = get_count(), total = 0;
00393
00394 n = total = mask.find(false,0,count);
00395
00396 if (n<count)
00397 {
00398 for(n=mask.find(true,n+1,count-n-1);n<count;n=mask.find(true,n+1,count-n-1))
00399 pfc::swap_t(m_buffer[total++],m_buffer[n]);
00400
00401 m_buffer.set_size(total);
00402 }
00403 }
00404
00405 void replace_item(t_size idx,const T& item)
00406 {
00407 PFC_ASSERT(idx>=0);
00408 PFC_ASSERT(idx<get_count());
00409 m_buffer[idx] = item;
00410 }
00411
00412 void sort()
00413 {
00414 pfc::sort_callback_impl_auto_wrap_t<t_storage> wrapper(m_buffer);
00415 pfc::sort(wrapper,get_count());
00416 }
00417
00418 template<typename t_compare>
00419 void sort_t(t_compare p_compare)
00420 {
00421 pfc::sort_callback_impl_simple_wrap_t<t_storage,t_compare> wrapper(m_buffer,p_compare);
00422 pfc::sort(wrapper,get_count());
00423 }
00424
00425 template<typename t_compare>
00426 void sort_stable_t(t_compare p_compare)
00427 {
00428 pfc::sort_callback_impl_simple_wrap_t<t_storage,t_compare> wrapper(m_buffer,p_compare);
00429 pfc::sort_stable(wrapper,get_count());
00430 }
00431 inline void reorder_partial(t_size p_base,const t_size * p_order,t_size p_count)
00432 {
00433 PFC_ASSERT(p_base+p_count<=get_count());
00434 pfc::reorder_partial_t(m_buffer,p_base,p_order,p_count);
00435 }
00436
00437 template<typename t_compare>
00438 t_size find_duplicates_sorted_t(t_compare p_compare,bit_array_var & p_out) const
00439 {
00440 return pfc::find_duplicates_sorted_t<list_impl_t<T,t_storage> const &,t_compare>(*this,get_count(),p_compare,p_out);
00441 }
00442
00443 template<typename t_compare,typename t_permutation>
00444 t_size find_duplicates_sorted_permutation_t(t_compare p_compare,t_permutation p_permutation,bit_array_var & p_out)
00445 {
00446 return pfc::find_duplicates_sorted_permutation_t<list_impl_t<T,t_storage> const &,t_compare,t_permutation>(*this,get_count(),p_compare,p_permutation,p_out);
00447 }
00448
00449
00450 private:
00451 class sort_callback_wrapper
00452 {
00453 public:
00454 explicit inline sort_callback_wrapper(sort_callback & p_callback) : m_callback(p_callback) {}
00455 inline int operator()(const T& item1,const T& item2) const {return m_callback.compare(item1,item2);}
00456 private:
00457 sort_callback & m_callback;
00458 };
00459 public:
00460 void sort(sort_callback & p_callback)
00461 {
00462 sort_t(sort_callback_wrapper(p_callback));
00463 }
00464
00465 void sort_stable(sort_callback & p_callback)
00466 {
00467 sort_stable_t(sort_callback_wrapper(p_callback));
00468 }
00469
00470 void remove_mask(const bit_array & mask) {filter_mask(bit_array_not(mask));}
00471
00472 void remove_mask(const bool * mask) {remove_mask(bit_array_table(mask,get_count()));}
00473 void filter_mask(const bool * mask) {filter_mask(bit_array_table(mask,get_count()));}
00474
00475 t_size add_item(const T& item)
00476 {
00477 t_size idx = get_count();
00478 insert_item(item,idx);
00479 return idx;
00480 }
00481
00482 void remove_all() {remove_mask(bit_array_true());}
00483
00484 void remove_item(const T& item)
00485 {
00486 t_size n,max = get_count();
00487 bit_array_bittable mask(max);
00488 for(n=0;n<max;n++)
00489 mask.set(n,get_item(n)==item);
00490 remove_mask(mask);
00491 }
00492
00493 void swap_item_with(t_size p_index,T & p_item)
00494 {
00495 PFC_ASSERT(p_index < get_count());
00496 pfc::swap_t(m_buffer[p_index],p_item);
00497 }
00498
00499 void swap_items(t_size p_index1,t_size p_index2)
00500 {
00501 PFC_ASSERT(p_index1 < get_count());
00502 PFC_ASSERT(p_index1 < get_count());
00503 pfc::swap_t(m_buffer[p_index1],m_buffer[p_index2]);
00504 }
00505
00506 inline static void g_swap(list_impl_t<T,t_storage> & p_item1,list_impl_t<T,t_storage> & p_item2)
00507 {
00508 pfc::swap_t(p_item1.m_buffer,p_item2.m_buffer);
00509 }
00510
00511 template<typename t_search>
00512 t_size find_item(const t_search & p_item) const
00513 {
00514 t_size n,max = get_count();
00515 for(n=0;n<max;n++)
00516 if (m_buffer[n]==p_item) return n;
00517 return ~0;
00518 }
00519
00520 template<typename t_search>
00521 inline bool have_item(const t_search & p_item) const {return this->template find_item<t_search>(p_item)!=~0;}
00522
00523 protected:
00524 t_storage m_buffer;
00525 };
00526
00527 template<typename t_item, template<typename> class t_alloc = pfc::alloc_fast >
00528 class list_t : public list_impl_t<t_item,pfc::array_t<t_item,t_alloc> > { };
00529
00530 template<typename t_item, t_size p_fixed_count, template<typename> class t_alloc = pfc::alloc_fast >
00531 class list_hybrid_t : public list_impl_t<t_item,pfc::array_hybrid_t<t_item,p_fixed_count,t_alloc> > {};
00532
00533 template<typename T>
00534 class ptr_list_const_cast_t : public list_base_const_t<const T *>
00535 {
00536 public:
00537 inline ptr_list_const_cast_t(const list_base_const_t<T*> & p_param) : m_param(p_param) {}
00538 t_size get_count() const {return m_param.get_count();}
00539 void get_item_ex(const T * & p_out,t_size n) const {T* temp; m_param.get_item_ex(temp,n); p_out = temp;}
00540 private:
00541 const list_base_const_t<T*> & m_param;
00542
00543 };
00544
00545
00546 template<typename T,typename P>
00547 class list_const_permutation_t : public list_base_const_t<T>
00548 {
00549 public:
00550 inline list_const_permutation_t(const list_base_const_t<T> & p_list,P p_permutation) : m_list(p_list), m_permutation(p_permutation) {}
00551 t_size get_count() const {return m_list.get_count();}
00552 void get_item_ex(T & p_out,t_size n) const {m_list.get_item_ex(p_out,m_permutation[n]);}
00553 private:
00554 P m_permutation;
00555 const list_base_const_t<T> & m_list;
00556 };
00557
00558
00559 template<class T>
00560 class list_permutation_t : public list_base_const_t<T>
00561 {
00562 public:
00563 t_size get_count() const {return m_count;}
00564 void get_item_ex(T & p_out,t_size n) const {m_base.get_item_ex(p_out,m_order[n]);}
00565 list_permutation_t(const list_base_const_t<T> & p_base,const t_size * p_order,t_size p_count)
00566 : m_base(p_base), m_order(p_order), m_count(p_count)
00567 {
00568 PFC_ASSERT(m_base.get_count() >= m_count);
00569 }
00570 private:
00571 const list_base_const_t<T> & m_base;
00572 const t_size * m_order;
00573 t_size m_count;
00574 };
00575
00576 }
00577 #endif //_PFC_LIST_H_