#pragma once namespace pfc { template class NOVTABLE list_base_const_t { private: typedef list_base_const_t t_self; public: typedef T t_item; virtual t_size get_count() const = 0; virtual void get_item_ex(T& p_out, t_size n) const = 0; inline t_size get_size() const {return get_count();} inline T get_item(t_size n) const {T temp; get_item_ex(temp,n); return temp;} inline T operator[](t_size n) const {T temp; get_item_ex(temp,n); return temp;} template t_size find_duplicates_sorted_t(t_compare p_compare,bit_array_var & p_out) const { return ::pfc::find_duplicates_sorted_t const &,t_compare>(*this,get_count(),p_compare,p_out); } template t_size find_duplicates_sorted_permutation_t(t_compare p_compare,t_permutation const & p_permutation,bit_array_var & p_out) { return ::pfc::find_duplicates_sorted_permutation_t const &,t_compare,t_permutation>(*this,get_count(),p_compare,p_permutation,p_out); } template t_size find_item(const t_search & p_item) const//returns index of first occurance, infinite if not found { t_size n,max = get_count(); for(n=0;n inline bool have_item(const t_search & p_item) const {return find_item(p_item)!=~0;} template bool bsearch_t(t_compare p_compare,t_param const & p_param,t_size &p_index) const { return ::pfc::bsearch_t(get_count(),*this,p_compare,p_param,p_index); } template bool bsearch_permutation_t(t_compare p_compare,t_param const & p_param,const t_permutation & p_permutation,t_size & p_index) const { return ::pfc::bsearch_permutation_t(get_count(),*this,p_compare,p_param,p_permutation,p_index); } template void sort_get_permutation_t(t_compare p_compare,t_permutation const & p_permutation) const { ::pfc::sort_get_permutation_t,t_compare,t_permutation>(*this,p_compare,get_count(),p_permutation); } template void sort_stable_get_permutation_t(t_compare p_compare,t_permutation const & p_permutation) const { ::pfc::sort_stable_get_permutation_t,t_compare,t_permutation>(*this,p_compare,get_count(),p_permutation); } template void enumerate(t_callback & p_callback) const { for(t_size n = 0, m = get_count(); n < m; ++n ) { p_callback( (*this)[n] ); } } static bool g_equals(const t_self & item1, const t_self & item2) { const t_size count = item1.get_count(); if (count != item2.get_count()) return false; for(t_size walk = 0; walk < count; ++walk) if (item1[walk] != item2[walk]) return false; return true; } bool operator==(const t_self & item2) const {return g_equals(*this,item2);} bool operator!=(const t_self & item2) const {return !g_equals(*this,item2);} protected: list_base_const_t() {} ~list_base_const_t() {} list_base_const_t(const t_self &) {} void operator=(const t_self &) {} }; template class list_single_ref_t : public list_base_const_t { public: list_single_ref_t(const T & p_item,t_size p_count = 1) : m_item(p_item), m_count(p_count) {} t_size get_count() const {return m_count;} void get_item_ex(T& p_out,t_size n) const {PFC_ASSERT(n class list_partial_ref_t : public list_base_const_t { public: list_partial_ref_t(const list_base_const_t & p_list,t_size p_base,t_size p_count) : m_list(p_list), m_base(p_base), m_count(p_count) { PFC_ASSERT(m_base + m_count <= m_list.get_count()); } private: const list_base_const_t & m_list; t_size m_base,m_count; t_size get_count() const {return m_count;} void get_item_ex(T & p_out,t_size n) const {m_list.get_item_ex(p_out,n+m_base);} }; template class list_const_array_t : public list_base_const_t { public: inline list_const_array_t(A p_data,t_size p_count) : m_data(p_data), m_count(p_count) {} t_size get_count() const {return m_count;} void get_item_ex(T & p_out,t_size n) const {p_out = m_data[n];} private: A m_data; t_size m_count; }; template class list_const_array_ref_t : public list_base_const_t { public: list_const_array_ref_t(const t_array & data) : m_data(data) {} t_size get_count() const {return m_data.get_size();} void get_item_ex(typename t_array::t_item & out, t_size n) const {out = m_data[n];} private: const t_array & m_data; }; template class list_const_cast_t : public list_base_const_t { public: list_const_cast_t(const list_base_const_t & p_from) : m_from(p_from) {} t_size get_count() const {return m_from.get_count();} void get_item_ex(to & p_out,t_size n) const { from temp; m_from.get_item_ex(temp,n); p_out = temp; } private: const list_base_const_t & m_from; }; template class ptr_list_const_array_t : public list_base_const_t { public: inline ptr_list_const_array_t(A p_data,t_size p_count) : m_data(p_data), m_count(p_count) {} t_size get_count() const {return m_count;} void get_item_ex(T* & p_out,t_size n) const {p_out = &m_data[n];} private: A m_data; t_size m_count; }; template class list_const_ptr_t : public list_base_const_t { public: inline list_const_ptr_t(const T * p_data,t_size p_count) : m_data(p_data), m_count(p_count) {} t_size get_count() const {return m_count;} void get_item_ex(T & p_out,t_size n) const {p_out = m_data[n];} private: const T * m_data; t_size m_count; }; template class NOVTABLE list_base_t : public list_base_const_t { private: typedef list_base_t t_self; typedef const list_base_const_t t_self_const; public: class NOVTABLE sort_callback { public: virtual int compare(const T& p_item1,const T& p_item2) = 0; }; virtual void filter_mask(const bit_array & mask) = 0; virtual t_size insert_items(const list_base_const_t & items,t_size base) = 0; virtual void reorder_partial(t_size p_base,const t_size * p_data,t_size p_count) = 0; virtual void sort(sort_callback & p_callback) = 0; virtual void sort_stable(sort_callback & p_callback) = 0; virtual void replace_item(t_size p_index,const T& p_item) = 0; virtual void swap_item_with(t_size p_index,T & p_item) = 0; virtual void swap_items(t_size p_index1,t_size p_index2) = 0; inline void reorder(const t_size * p_data) {reorder_partial(0,p_data,this->get_count());} inline t_size insert_item(const T & item,t_size base) {return insert_items(list_single_ref_t(item),base);} t_size insert_items_repeat(const T & item,t_size num,t_size base) {return insert_items(list_single_ref_t(item,num),base);} inline t_size add_items_repeat(T item,t_size num) {return insert_items_repeat(item,num,~0);} t_size insert_items_fromptr(const T* source,t_size num,t_size base) {return insert_items(list_const_ptr_t(source,num),base);} inline t_size add_items_fromptr(const T* source,t_size num) {return insert_items_fromptr(source,num,~0);} inline t_size add_items(const list_base_const_t & items) {return insert_items(items,~0);} inline t_size add_item(const T& item) {return insert_item(item,~0);} inline void remove_mask(const bit_array & mask) {filter_mask(bit_array_not(mask));} inline void remove_all() {filter_mask(bit_array_false());} inline void truncate(t_size val) {if (val < this->get_count()) remove_mask(bit_array_range(val,this->get_count()-val,true));} 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;} inline T operator[](t_size n) const {return this->get_item(n);} template class sort_callback_impl_t : public sort_callback { public: sort_callback_impl_t(t_compare p_compare) : m_compare(p_compare) {} int compare(const T& p_item1,const T& p_item2) {return m_compare(p_item1,p_item2);} private: t_compare m_compare; }; class sort_callback_auto : public sort_callback { public: int compare(const T& p_item1,const T& p_item2) {return ::pfc::compare_t(p_item1,p_item2);} }; void sort() {sort_callback_auto cb;sort(cb);} template void sort_t(t_compare p_compare) {sort_callback_impl_t cb(p_compare);sort(cb);} template void sort_stable_t(t_compare p_compare) {sort_callback_impl_t cb(p_compare); sort_stable(cb);} template void sort_remove_duplicates_t(t_compare p_compare) { sort_t(p_compare); bit_array_bittable array(this->get_count()); if (this->template find_duplicates_sorted_t(p_compare,array) > 0) remove_mask(array); } template void sort_stable_remove_duplicates_t(t_compare p_compare) { sort_stable_t(p_compare); bit_array_bittable array(this->get_count()); if (this->template find_duplicates_sorted_t(p_compare,array) > 0) remove_mask(array); } template void remove_duplicates_t(t_compare p_compare) { order_helper order(this->get_count()); sort_get_permutation_t(p_compare,order); bit_array_bittable array(this->get_count()); if (this->template find_duplicates_sorted_permutation_t(p_compare,order,array) > 0) remove_mask(array); } template void for_each(t_func p_func) { t_size n,max=this->get_count(); for(n=0;nget_item(n)); } template void for_each(t_func p_func,const bit_array & p_mask) { t_size n,max=this->get_count(); for(n=p_mask.find(true,0,max);nget_item(n)); } } template void remove_mask_ex(const bit_array & p_mask,t_releasefunc p_func) { this->template for_each(p_func,p_mask); remove_mask(p_mask); } template void remove_all_ex(t_releasefunc p_func) { this->template for_each(p_func); remove_all(); } template t_self & operator=(t_in const & source) {remove_all(); add_items(source); return *this;} template t_self & operator+=(t_in const & p_source) {add_item(p_source); return *this;} template t_self & operator|=(t_in const & p_source) {add_items(p_source); return *this;} protected: list_base_t() {} ~list_base_t() {} list_base_t(const t_self&) {} void operator=(const t_self&) {} }; template class list_impl_t : public list_base_t { public: typedef list_base_t t_base; typedef list_impl_t t_self; list_impl_t() {} list_impl_t(const t_self & p_source) { add_items(p_source); } void prealloc(t_size count) {m_buffer.prealloc(count);} void set_count(t_size p_count) {m_buffer.set_size(p_count);} void set_size(t_size p_count) {m_buffer.set_size(p_count);} template t_size _insert_item_t(const t_in & item, t_size idx) { return ::pfc::insert_t(m_buffer, item, idx); } template t_size insert_item(const t_in & item, t_size idx) { return _insert_item_t(item, idx); } t_size insert_item(const T& item,t_size idx) { return _insert_item_t(item, idx); } T remove_by_idx(t_size idx) { T ret = m_buffer[idx]; t_size n; t_size max = m_buffer.get_size(); for(n=idx+1;n=0); PFC_ASSERT(n=0); PFC_ASSERT(n= 0); PFC_ASSERT(n < get_size() ); return m_buffer[n]; }; inline t_size get_count() const {return m_buffer.get_size();} inline t_size get_size() const {return m_buffer.get_size();} inline const T & operator[](t_size n) const { PFC_ASSERT(n>=0); PFC_ASSERT(n & source,t_size base) { //workaround for inefficient operator[] on virtual-interface-accessed lists t_size count = get_size(); if (base>count) base = count; t_size num = source.get_count(); m_buffer.set_size(count+num); if (count > base) { for(t_size n=count-1;(int)n>=(int)base;n--) { ::pfc::move_t(m_buffer[n+num],m_buffer[n]); } } for(t_size n=0;n & source,t_size base) {return _insert_items_v(source, base);} t_size insert_items(const list_base_t & source,t_size base) {return _insert_items_v(source, base);} template t_size insert_items(const t_in & source,t_size base) { t_size count = get_size(); if (base>count) base = count; t_size num = array_size_t(source); m_buffer.set_size(count+num); if (count > base) { for(t_size n=count-1;(int)n>=(int)base;n--) { ::pfc::move_t(m_buffer[n+num],m_buffer[n]); } } for(t_size n=0;n void add_items(const t_in & in) {insert_items(in, ~0);} void get_items_mask(list_impl_t & out,const bit_array & mask) { mask.walk( get_size(), [&] (size_t n) { out.add_item(m_buffer[n]); } ); } void filter_mask(const bit_array & mask) { t_size n,count = get_size(), total = 0; n = total = mask.find(false,0,count); if (n=0); PFC_ASSERT(idx wrapper(m_buffer); ::pfc::sort(wrapper,get_size()); } template void sort_t(t_compare p_compare) { ::pfc::sort_callback_impl_simple_wrap_t wrapper(m_buffer,p_compare); ::pfc::sort(wrapper,get_size()); } template void sort_stable_t(t_compare p_compare) { ::pfc::sort_callback_impl_simple_wrap_t wrapper(m_buffer,p_compare); ::pfc::sort_stable(wrapper,get_size()); } inline void reorder_partial(t_size p_base,const t_size * p_order,t_size p_count) { PFC_ASSERT(p_base+p_count<=get_size()); ::pfc::reorder_partial_t(m_buffer,p_base,p_order,p_count); } template t_size find_duplicates_sorted_t(t_compare p_compare,bit_array_var & p_out) const { return ::pfc::find_duplicates_sorted_t const &,t_compare>(*this,get_size(),p_compare,p_out); } template t_size find_duplicates_sorted_permutation_t(t_compare p_compare,t_permutation p_permutation,bit_array_var & p_out) { return ::pfc::find_duplicates_sorted_permutation_t const &,t_compare,t_permutation>(*this,get_size(),p_compare,p_permutation,p_out); } void move_from(t_self & other) { remove_all(); m_buffer = std::move(other.m_buffer); } private: class sort_callback_wrapper { public: explicit inline sort_callback_wrapper(typename t_base::sort_callback & p_callback) : m_callback(p_callback) {} inline int operator()(const T& item1,const T& item2) const {return m_callback.compare(item1,item2);} private: typename t_base::sort_callback & m_callback; }; public: void sort(typename t_base::sort_callback & p_callback) { sort_t(sort_callback_wrapper(p_callback)); } void sort_stable(typename t_base::sort_callback & p_callback) { sort_stable_t(sort_callback_wrapper(p_callback)); } void remove_mask(const bit_array & mask) {filter_mask(bit_array_not(mask));} void remove_mask(const bool * mask) {remove_mask(bit_array_table(mask,get_size()));} void filter_mask(const bool * mask) {filter_mask(bit_array_table(mask,get_size()));} t_size add_item(const T& item) { return insert_item(item, ~0); } template t_size add_item(const t_in & item) { return insert_item(item, ~0); } void remove_all() {remove_mask(bit_array_true());} void remove_item(const T& item) { t_size n,max = get_size(); bit_array_bittable mask(max); for(n=0;n & p_item1,list_impl_t & p_item2) { swap_t(p_item1.m_buffer,p_item2.m_buffer); } template t_size find_item(const t_search & p_item) const//returns index of first occurance, infinite if not found { t_size n,max = get_size(); for(n=0;n inline bool have_item(const t_search & p_item) const {return this->template find_item(p_item)!=~0;} template t_self & operator=(t_in const & source) {remove_all(); add_items(source); return *this;} template t_self & operator+=(t_in const & p_source) {add_item(p_source); return *this;} template t_self & operator|=(t_in const & p_source) {add_items(p_source); return *this;} protected: t_storage m_buffer; }; template class t_alloc = alloc_fast > class list_t : public list_impl_t > { public: typedef list_t t_self; template t_self & operator=(t_in const & source) {this->remove_all(); this->add_items(source); return *this;} template t_self & operator+=(t_in const & p_source) {this->add_item(p_source); return *this;} template t_self & operator|=(t_in const & p_source) {this->add_items(p_source); return *this;} }; template class t_alloc = alloc_fast > class list_hybrid_t : public list_impl_t > { public: typedef list_hybrid_t t_self; template t_self & operator=(t_in const & source) {this->remove_all(); this->add_items(source); return *this;} template t_self & operator+=(t_in const & p_source) {this->add_item(p_source); return *this;} template t_self & operator|=(t_in const & p_source) {this->add_items(p_source); return *this;} }; template class ptr_list_const_cast_t : public list_base_const_t { public: inline ptr_list_const_cast_t(const list_base_const_t & p_param) : m_param(p_param) {} t_size get_count() const {return m_param.get_count();} void get_item_ex(const T * & p_out,t_size n) const {T* temp; m_param.get_item_ex(temp,n); p_out = temp;} private: const list_base_const_t & m_param; }; template class list_const_permutation_t : public list_base_const_t { public: inline list_const_permutation_t(const list_base_const_t & p_list,P p_permutation) : m_list(p_list), m_permutation(p_permutation) {} t_size get_count() const {return m_list.get_count();} void get_item_ex(T & p_out,t_size n) const {m_list.get_item_ex(p_out,m_permutation[n]);} private: P m_permutation; const list_base_const_t & m_list; }; template class list_permutation_t : public list_base_const_t { public: t_size get_count() const {return m_count;} void get_item_ex(T & p_out,t_size n) const {m_base.get_item_ex(p_out,m_order[n]);} list_permutation_t(const list_base_const_t & p_base,const t_size * p_order,t_size p_count) : m_base(p_base), m_order(p_order), m_count(p_count) { PFC_ASSERT(m_base.get_count() >= m_count); } private: const list_base_const_t & m_base; const t_size * m_order; t_size m_count; }; template class alloc> class traits_t > : public combine_traits >, traits_vtable> {}; }