list.h

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

Generated on Fri Apr 25 18:49:37 2008 for foobar2000 SDK by  doxygen 1.5.5