SourceForge.jp

array_onebyone_msvc.hpp

説明を見る。
00001 
00028 #ifndef _dkutilTL_array_onebyone_msvc_hpp_
00029 #define _dkutilTL_array_onebyone_msvc_hpp_
00030 
00031 //#include "dKingyoMacro.h"
00032 
00033 
00034 
00035 namespace dkutil{
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00053 template<class T,typename A=std::allocator<T>,class VECTOR=std::vector<T,A> ,class DEQUE=std::deque<VECTOR::size_type,A> ,unsigned int SizeAfterInit=200>
00054 class array_onebyone_ex{
00055 public:
00056     enum{
00057         enuExtendSize = SizeAfterInit,
00058     };
00059     typedef A allocator_type;
00060   typedef A::size_type size_type;
00061   typedef A::difference_type difference_type;
00062   typedef A::reference reference;
00063   typedef A::const_reference const_reference;
00064   typedef A::value_type value_type;
00065     typedef size_type handle;
00066     typedef VECTOR VECTOR_TYPE;
00067     typedef DEQUE DEQUE_TYPE;
00068 #ifndef BOOST_NO_PRIVATE_IN_AGGREGATE //なぜか boost 対応・・・
00069 protected:
00070 #endif
00071     DEQUE mq;
00072     VECTOR mv;
00073     
00074     VECTOR_TYPE::size_type now_size;
00075 
00076 public:
00077     //array_onebyone_ex(){clear();now_size = 0;}
00078     array_onebyone_ex(size_type construct_size=enuExtendSize){
00079         clear();
00080         mv.reserve(construct_size);
00081         now_size = 0;
00082     }
00083 
00084 
00085     virtual ~array_onebyone_ex(){clear();}
00090 
00091     handle push(const T &x){
00092         
00093         now_size++;//今のサイズをいんくりめんとぉ!
00094         
00095         if(mq.empty())
00096         {//キューが空だったら? 
00097             //そのままvector配列にぶち込む
00098             mv.push_back(x);
00099             return (now_size - 1);
00100             //return (mv.size() - 1);//これでいいのかは不明・・・
00101         }
00102         else//キューの中身が空じゃなかったら
00103         {
00104             size_type temp;
00105             mv[temp = mq.front()]=x;//キューのフロントを参照して添え字を見つけ、データ挿入。
00106             mq.pop_front();//frontを削除
00107             return temp;//添え字をハンドルとして返す。
00108         }
00109         //実際、ありえないけど念のため書いておく^^;
00110         throw std::logic_error("array_onebyone_ex:push:logic error");
00111         return NULL;
00112     }
00113     
00115     void pop(const handle &h){
00116         if(now_size == UINT_MAX){//buffer overflow
00117             throw std::invalid_argument("buffer overflow ");
00118             return;
00119         }
00120         if(now_size ==0){
00121             throw std::invalid_argument("now_size == 0 push() is not called. ");
00122             return;
00123         }
00124         now_size--;
00125         //コンテナに入っているデストラクタは呼び出しておく・・・
00126         A alc = mv.get_allocator();
00127         alc.destroy(alc.address(mv.at(h)));
00128         //使われていないよキュー にぶち込む
00129         mq.push_back(h);
00130     }
00132     A get_allocator() const{return mv.get_allocator();} 
00134     size_type size()const{ 
00135         return now_size;//mv.size();
00136     }
00137     //size_type max_size()const{    return mv.max_size();}
00139     size_type capacity()const{  return mv.capacity();}
00141     VECTOR &get_vector()const{return mv;}
00143     DEQUE &get_deque()const{return mq;}
00144     bool empty()const{  //return (mv.empty() && mq.empty());
00145         return (now_size == 0);
00146         //return mv.empty();
00147     }
00148     void resize(size_type new_size,const T &x=T()){
00149         if(new_size < mv.size()){
00150             throw std::invalid_argument("resize member function :argument new_size is too small."));
00151             return;
00152         }
00153         mv.resize(new_size,x);
00154     }
00155     void reserve(size_type n){
00156         if(n < mv.size()){
00157             throw
00158                 std::invalid_argument("reserve member function :argument n is too small.");
00159             return;
00160         }
00161         mv.reserve(n);
00162     }
00163     bool empty_free_queue(){    return mp.empty();}
00164     //要素の参照
00166     reference at(size_type pos){return mv.at(pos);}
00168     T *at_ptr(size_type pos){return &at(pos);}
00169   const_reference at(size_type pos) const{return mv.at(pos);}
00171     reference operator[](size_type pos){return mv[pos]; }
00172   const_reference operator[](size_type pos)const{   return mv[pos]; }
00173     
00175     void insert(handle pos,T &x){
00176         //now_size ++;
00177 #   ifdef _DEBUG
00178         try{
00179             mv.at(pos);
00180         }catch(...){
00181             char *str="posが無効です。";
00182             DEBUGMB(str);
00183             ::assert(!str);
00184         }
00185 #   endif
00186         mv[pos] = x;
00187         
00188     } 
00189     
00190     void clear(){ now_size = 0;mv.clear(); mq.clear(); }
00191 
00192 };
00193 
00194 
00196 template<class T>
00197 inline int ReallocateByNew(T **before,DWORD oldcount,T **after,DWORD extend,UINT *aftercount)
00198 {
00199     DWORD total = oldcount + extend;//合計の新規確保分
00200     T *get = new T[total];//maxcountはここで更新
00201     if(get==NULL){
00202         return -1;//だめじゃん!!最悪〜〜
00203     }
00204     //メモリコピー
00205     for(DWORD i=0;i<oldcount;i++){
00206         get[i]=(*before)[i];
00207     }
00208     //memcpyはC++のオブジェクトも出来るかどうか分からないので^^;
00209 
00210     delete[] (*before);//元のは開放
00211     (*after) = get;//アドレスを入れる。
00212     (*aftercount) = total;//合計の確保した数を入れる
00213     return 0;
00214 }
00215 
00216 
00217 
00218 
00219 
00225 
00226 template <class T,unsigned int EXTEND_ARRAY=enuDefaultExpandSize,typename A = std::allocator<T> >
00227 class array_onebyone{
00228 public:
00229     typedef A allocator_type;
00230   typedef A::size_type size_type;
00231   typedef A::difference_type difference_type;
00232   typedef A::reference reference;
00233   typedef A::const_reference const_reference;
00234   typedef A::value_type value_type;
00235     typedef std::deque<unsigned int,A> DEQUE_TYPE;
00236 #ifndef BOOST_NO_PRIVATE_IN_AGGREGATE //なぜか boost 対応・・・
00237 protected:
00238 #endif
00239     A allocator;
00240 
00241     T *m;// Memory
00242     unsigned int maxcount;//配列の最大数
00243     unsigned int nowmp;//now  m point
00244     bool mflag;//is OK?)
00245     DEQUE_TYPE mp;//添え字のキュー
00246     enum{//,DWORD EXTEND_ARRAY=100
00247         enuExtendArray=EXTEND_ARRAY,
00248     };
00249     
00250 public:
00251     typedef unsigned int handle;
00252     explicit array_onebyone(){
00253         maxcount=NULL;
00254         //nowmp=NULL;rend();をサポートするため・・・ 0では困る。Initで1にしておく
00255         nowmp=0;
00256         m=NULL;
00257         mflag=false;
00258         Init(enuExtendArray);
00259     }
00260   array_onebyone(const array_onebyone<T,EXTEND_ARRAY,A> &a){
00261         mflag=false;
00262         maxcount = a.maxcount;
00263       nowmp = a.nowmp;
00264       //getflag = a.getflag;
00265       mp = a.mp;
00266         if(a.maxcount > 0){
00267             m = new T[a.maxcount];
00268             if(!m)
00269             {//例外発生しました!!
00270                 //ここでなぎぇたいのぬぃ〜〜〜!!!!
00271                 // throw std::domain_error("array_onebyone:copy constructor:memory allocate error");
00272                 return;
00273             }
00274             for(int i = 0; i < a.maxcount; i++){//メモリコピー
00275                  *(m + i) = *(a.m + i);
00276             }
00277             //memcpy(m, a.m, a.maxcount);これだとC++のオブジェクトも出来るかどうかは不明
00278         }
00279         else{
00280             m = NULL;
00281         }
00282         mflag=true;//初期化済み
00283     }
00284 
00285     bool empty_free_queue(){
00286         return mp.empty();
00287     }
00288 
00289   void resize(size_type n){
00290         if(maxcount >= n){
00291             std::domain_error("Size is not made small.");
00292         }
00293         ReallocateByNew<T>(&m,maxcount,&m,n,&maxcount);
00294     }
00295   size_type size() const{return nowmp-1;}
00296   size_type max_size() const{return maxcount;}
00297   bool empty() const{
00298         if((mp.empty() && nowmp<=1) || mp.size()==nowmp)
00299             return true;
00300         return false;
00301     }
00302   A get_allocator() const{return allocator;}
00303   reference at(size_type pos){
00304         if(nowmp <= pos){
00305             throw std::range_error("range error");
00306         }
00307         return m[pos];
00308     }
00309     
00310   const_reference at(size_type pos) const{
00311         if(nowmp <= pos){
00312             throw std::range_error("range error");
00313         }
00314         return m[pos];
00315     }
00316   reference operator[](size_type pos){return m[pos]; }
00317   const_reference operator[](size_type pos)const{   return m[pos]; }
00318   //reference front(){  return m;}
00319   //const_reference front() const;
00320   //reference back(){return m[nowmp-1];}
00321   //const_reference back() const;
00322   handle push(const T& x){
00323         if(mflag==false){
00324             Init(enuExtendArray);
00325         }
00326         if(nowmp>=maxcount)
00327         {//ちょっとこのままじゃアクセスバイオレーションだ〜よ!
00328             if(mp.empty())
00329             {//キューが空だったら? 
00330                 if(-1==Reallocate())//リアロックする。
00331                 {
00332                     return NULL;//最悪〜〜失敗。
00333                 }
00334                 else//上手くできたようなので
00335                 {
00336                     return push(x);//再起呼び出し
00337                 }
00338             }
00339             else//キューの中身が空じゃなかったら
00340             {
00341                 DWORD l_num;//配列の添え字をゲットする
00342                 l_num=(mp.front());//ってことでGET!
00343                 mp.pop_front();//削除する
00344                 m[l_num]=x;//データ挿入。
00345                 return l_num;//添え字をハンドルとして返す。
00346             }
00347         }else{
00348             m[nowmp] = x;//でーたを入れとく
00349             return nowmp++;//添え字をハンドルとして返す
00350         }
00351         //実際、ありえないけど念のため書いておく^^;
00352         return NULL;
00353     }
00354   void pop(handle item){mp.push_back(item);}
00355   //void assign(const_iterator first, const_iterator last);
00356   //void assign(size_type n, const T& x = T());
00357   //iterator insert(iterator it, const T& x = T());
00358   //void insert(iterator it, size_type n, const T& x);
00359   //void insert(iterator it,  const_iterator first, const_iterator last);
00360   //iterator erase(iterator it);
00361   //iterator erase(iterator first, iterator last);
00362   void clear(){
00363         if(m){
00364             delete[] m;
00365             m=NULL;
00366         }   
00367         maxcount=NULL;
00368         nowmp=NULL;
00369         m=NULL;
00370         mp.clear();//キューもすべて削除
00371         mflag=false;//フラグを下ろす
00372     }
00373   //void swap(deque x);
00374    
00375     virtual ~array_onebyone(){
00376         clear();
00377     }
00378 protected:
00382 
00383     int Init(size_t memory_count)
00384     {
00385         if(mflag==true)return 1;//もう一回呼び出しはダメです。
00386         maxcount=memory_count;
00387         //Dyanamic memoryだったらnewしかないでしょ^^;
00388         m = new T[memory_count];
00389         if(!m) return -1;//だめじゃんNULLじゃ
00390 
00391         nowmp=1;//rend()を使うため
00392         mflag=true;//フラグを立てる
00393         
00394         return 0;
00395     }
00397     int Reallocate(){
00398         if(mflag==false){
00399             if(-1==Init(100)){//百個くらい^^;
00400                 throw std::runtime_error("The worst error");
00401             }
00402         }
00403         return ReallocateByNew<T>(&m,maxcount,&m,enuExtendArray,&maxcount);
00404     }
00405 };
00406 
00407 }//end of dkutil namespace
00408 
00409 
00410 #endif // end of include once

dkutil 1.02リリース前 d金魚専用マニュアルバージョンに対してSun Dec 28 21:23:07 2003に生成されました。 doxygen 1.3.5