ADMB Documentation  11.5.3152
 All Classes Files Functions Variables Typedefs Friends Defines
df1b2f14.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Author: David Fournier
00005  * Copyright (c) 2008-2012 Regents of the University of California
00006  */
00011 #include <df1b2fun.h>
00012 #include <cassert>
00013 
00014 #ifdef _MSC_VER
00015   #ifdef _M_X64
00016   typedef __int64 ssize_t;
00017   #else
00018   typedef int ssize_t;
00019   #endif
00020 #else
00021   #include <unistd.h>
00022 #endif
00023 
00028 fixed_smartlist2::fixed_smartlist2(void)
00029 {
00030   nentries=0;
00031   end_saved=0;
00032   eof_flag=0;
00033   noreadflag=0;
00034   written_flag=0;
00035   direction=0;
00036   bufsize=0;
00037   true_buffer=0;
00038   true_buffend=0;
00039   buffer=0;
00040   buffend=0;
00041   bptr=buffer;
00042 }
00043 
00048 fixed_smartlist2::fixed_smartlist2(const size_t _bufsize,
00049   const adstring& _filename)
00050 {
00051   allocate(_bufsize,_filename);
00052 }
00053 
00058 void fixed_smartlist2::allocate(const size_t _bufsize,
00059   const adstring& _filename)
00060 {
00061   nentries=_bufsize/sizeof(int);
00062   end_saved=0;
00063   eof_flag=0;
00064   noreadflag=0;
00065   written_flag=0;
00066   direction=0;
00067   bufsize=_bufsize;
00068   filename=_filename;
00069   AD_ALLOCATE(true_buffer,int,nentries+2,df1b2_gradlist)
00070   doubleptr=(double*)true_buffer;
00071   true_buffend=true_buffer+nentries+1;
00072   buffer=true_buffer+1;
00073   buffend=true_buffend-1;
00074   bptr=buffer;
00075   *true_buffer=5678;
00076   *true_buffend=9999;
00077   fp=open((char*)(filename), O_RDWR | O_CREAT | O_TRUNC |
00078                    O_BINARY, S_IREAD | S_IWRITE);
00079   if (fp < 0)
00080   {
00081     cerr << "Error trying to open file " << filename
00082          << " in class fixed_smartlist2 " << endl;
00083     ad_exit(1);
00084   }
00085   else
00086   {
00087     /*off_t pos=*/lseek(fp, 0L, SEEK_CUR);
00088   }
00089 }
00090 
00094 void fixed_smartlist2::write(const size_t n)
00095 {
00096 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00097   assert(n <= INT_MAX);
00098   ssize_t nw = ::write(fp, buffer, (int)n);
00099 #else
00100   ssize_t nw = ::write(fp, buffer, n);
00101 #endif
00102   if (nw <= -1 || (size_t)nw != n)
00103   {
00104     cerr << "Error writing to file " << filename << endl;
00105     ad_exit(1);
00106   }
00107 }
00108 
00112 void fixed_smartlist2::rewind(void)
00113 {
00114   bptr=buffer;
00115   eof_flag=0;
00116   if (written_flag)
00117   {
00118     lseek(fp,0L,SEEK_SET);
00119     // get the record size
00120     unsigned int nbytes = 0;
00121     ssize_t ret = ::read(fp,&nbytes,sizeof(unsigned int));
00122     assert(ret != -1);
00123     if (nbytes > bufsize)
00124     {
00125       cerr << "Error -- record size in file seems to be larger than"
00126        " the buffer it was created from " << endl
00127         << " buffer size is " << bufsize << " record size is supposedly "
00128         << nbytes << endl;
00129       ad_exit(1);
00130     }
00131     // now read the record into the buffer
00132     ret = ::read(fp,buffer,nbytes);
00133     assert(ret != -1);
00134     //cout << "Number of bytes read " << nr << endl;
00135     // skip over file postion entry in file
00136     // so we are ready to read second record
00137     lseek(fp,(off_t)sizeof(off_t),SEEK_CUR);
00138   }
00139 }
00140 
00145 void fixed_smartlist2::initialize(void)
00146 {
00147   end_saved=0;
00148   eof_flag=0;
00149   bptr=buffer;
00150   //int nbytes=0;
00151   written_flag=0;
00152   lseek(fp,0L,SEEK_SET);
00153   set_forward();
00154 }
00155 
00160 void fixed_smartlist2::check_buffer_size(const size_t nsize)
00161 {
00162   if ( bptr+nsize-1 > buffend)
00163   {
00164     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00165     {
00166       read_buffer();
00167     }
00168     else
00169     {
00170       if (nsize>bufsize)
00171       {
00172          cout << "Need to increase buffsize in list" << endl;
00173          exit(1);
00174       }
00175       write_buffer();
00176     }
00177   }
00178 }
00179 
00184 void fixed_smartlist2::restore_end(void)
00185 {
00186   if (written_flag)
00187   {
00188     if (end_saved)
00189     {
00190       /*off_t ipos=*/lseek(fp,endof_file_ptr,SEEK_SET);
00191       read_buffer();
00192       set_recend();
00193     }
00194   }
00195 }
00196 
00201 void fixed_smartlist2::save_end(void)
00202 {
00203   if (written_flag)
00204   {
00205     if (!end_saved)
00206     {
00207       write_buffer_one_less();
00208       end_saved=1;
00209     }
00210   }
00211 }
00212 
00217 void fixed_smartlist2::write_buffer_one_less(void)
00218 {
00219   int _nbytes=adptr_diff(bptr,buffer);
00220   if (_nbytes > 0)
00221   {
00222     unsigned int nbytes = (unsigned int)_nbytes;
00223 
00224     written_flag=1;
00225     // get the current file position
00226     off_t pos=lseek(fp,0L,SEEK_CUR);
00227 
00228     // write the size of the next record into the file
00229     ssize_t ret = ::write(fp,&nbytes,sizeof(unsigned int));
00230     assert(ret != -1);
00231 
00232     // write the record into the file
00233     ssize_t nw = ::write(fp,buffer,nbytes);
00234     if (nw < _nbytes)
00235     {
00236       cerr << "Error writing to file " << filename << endl;
00237       ad_exit(1);
00238     }
00239     // reset the pointer to the beginning of the buffer
00240     bptr=buffer;
00241 
00242     // now write the previous file position into the file so we can back up
00243     // when we want to.
00244     ret = ::write(fp,&pos,sizeof(off_t));
00245     assert(ret != -1);
00246 
00247     endof_file_ptr=lseek(fp,0L,SEEK_CUR);
00248 
00249     //cout << lseek(fp,0L,SEEK_CUR) << endl;
00250   }
00251 }
00252 
00257 void fixed_smartlist2::write_buffer(void)
00258 {
00259   int _nbytes=adptr_diff(bptr+1,buffer);
00260   if (_nbytes > 0)
00261   {
00262     unsigned int nbytes = (unsigned int)_nbytes;
00263 
00264     written_flag=1;
00265     // get the current file position
00266     off_t pos=lseek(fp,0L,SEEK_CUR);
00267 
00268     // write the size of the next record into the file
00269     ssize_t ret = ::write(fp, &nbytes, sizeof(unsigned int));
00270     assert(ret != -1);
00271 
00272     // write the record into the file
00273     ret = ::write(fp,buffer,nbytes);
00274     assert(ret != -1);
00275     if (ret < _nbytes)
00276     {
00277       cerr << "Error writing to file " << filename << endl;
00278       ad_exit(1);
00279     }
00280     // reset the pointer to the beginning of the buffer
00281     bptr=buffer;
00282 
00283     // now write the previous file position into the file so we can back up
00284     // when we want to.
00285     ret = ::write(fp,&pos,sizeof(off_t));
00286     assert(ret != -1);
00287 
00288     endof_file_ptr=lseek(fp,0L,SEEK_CUR);
00289 
00290     //cout << lseek(fp,0L,SEEK_CUR) << endl;
00291   }
00292 }
00293 
00298 void fixed_smartlist2::read_buffer(void)
00299 {
00300   if (!written_flag)
00301   {
00302     if (direction ==-1)
00303       eof_flag=-1;
00304     else
00305       eof_flag=1;
00306   }
00307   else
00308   {
00309     off_t pos = 0;
00310     if (direction ==-1) // we are going backwards
00311     {
00312       off_t ipos=lseek(fp,0L,SEEK_CUR);
00313       if (ipos ==0)
00314       {
00315         eof_flag=-1;
00316         return;
00317       }
00318       // offset of the begining of the record is at the end
00319       // of the record
00320       lseek(fp,-((off_t)sizeof(off_t)),SEEK_CUR);
00321       ssize_t ret = read(fp,&pos,sizeof(off_t));
00322       assert(ret != -1);
00323       // back up to the beginning of the record (plus record size)
00324       lseek(fp,pos,SEEK_SET);
00325       //*(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00326     }
00327     // get the record size
00328     int _nbytes = 0;
00329     ssize_t ret = ::read(fp,&_nbytes,sizeof(int));
00330     assert(ret != -1);
00331     if (_nbytes > 0)
00332     {
00333       const size_t nbytes = (size_t)_nbytes;
00334       if (nbytes > bufsize)
00335       {
00336         cerr << "Error -- record size in file seems to be larger than"
00337          " the buffer it was created from " << endl
00338           << " buffer size is " << bufsize << " record size is supposedly "
00339           << nbytes << endl;
00340         ad_exit(1);
00341       }
00342       // now read the record into the buffer
00343 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00344       ssize_t nr = ::read(fp,buffer,_nbytes);
00345 #else
00346       ssize_t nr = ::read(fp,buffer,nbytes);
00347 #endif
00348       assert(nr != -1);
00349       if (nr != _nbytes)
00350       {
00351         cerr << "Error: read only " << nr << " of " << nbytes << "bytes.\n";
00352         exit(1);
00353       }
00354       // reset the pointer to the beginning of the buffer
00355       bptr=buffer;
00356       size_t ns = nbytes / sizeof(int);
00357       recend=bptr+ns-1;
00358       //cout << "Number of bytes read " << nr
00359        //    << "  recend value = " << recend << endl;
00360       if (direction ==-1) // we are going backwards
00361       {
00362         // backup the file pointer again
00363         lseek(fp,pos,SEEK_SET);
00364         // *(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00365       }
00366       else  // we are going forward
00367       {
00368         //\todo need test
00369         // skip over file postion entry in file
00370         lseek(fp,(off_t)sizeof(off_t),SEEK_CUR);
00371       }
00372     }
00373   }
00374 }
00375 
00380 void memcpy(const fixed_smartlist2 & _list,void * p, const size_t nsize)
00381 {
00382   ADUNCONST(fixed_smartlist2,list)
00383   if ( list.bptr+nsize-1 > list.buffend)
00384   {
00385     cerr << " Trying to write outside list buffer" << endl;
00386     exit(1);
00387   }
00388   memcpy(list.bptr,p,nsize);
00389   list.bptr+=nsize;
00390 }
00391 
00396 void memcpy(void * p,const fixed_smartlist2 & _list, const size_t nsize)
00397 {
00398   ADUNCONST(fixed_smartlist2,list)
00399   if ( list.bptr+nsize-1 > list.buffend)
00400   {
00401     cerr << " Trying to write outside list buffer" << endl;
00402     exit(1);
00403   }
00404   memcpy(p,list.bptr,nsize);
00405   list.bptr+=nsize;
00406 }
00407 
00412 void fixed_smartlist2::operator -= (int n)
00413 {
00414   if (bptr-n<buffer)
00415   {
00416     if (bptr != buffer)
00417     {
00418       cerr << " Sanity error in fixed_smartlist2::operator -= (int)" << endl;
00419       exit(1);
00420     }
00421     else
00422     {
00423       // get previous record from the file
00424       read_buffer();
00425       bptr=recend-n+1;
00426     }
00427   }
00428   else
00429   {
00430     bptr-=n;
00431   }
00432 }
00433 
00438 void fixed_smartlist2::operator -- (void)
00439 {
00440   if (bptr-1<buffer)
00441   {
00442     if (bptr != buffer)
00443     {
00444       cerr << " Sanity error in fixed_smartlist2::operator -= (int)" << endl;
00445       exit(1);
00446     }
00447     else
00448     {
00449       // get previous record from the file
00450       read_buffer();
00451       //bptr=recend+1;
00452       bptr=recend;
00453     }
00454   }
00455   else
00456   {
00457     bptr--;
00458   }
00459 }
00460 
00465 void fixed_smartlist2::operator += (int nsize)
00466 {
00467   if ( bptr+nsize-1 > buffend)
00468   {
00469     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00470     {
00471       read_buffer();
00472     }
00473     else
00474     {
00475       if ((unsigned int)nsize>bufsize)
00476       {
00477          cout << "Need to increase buffsize in list" << endl;
00478          exit(1);
00479       }
00480       write_buffer();
00481     }
00482   }
00483   else
00484   {
00485     bptr+=nsize;
00486   }
00487 }
00488 
00493 void fixed_smartlist2::operator ++ (void)
00494 {
00495   if ( bptr==buffend)
00496   {
00497     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00498     {
00499       read_buffer();
00500     }
00501     else
00502     {
00503       write_buffer();
00504     }
00505   }
00506   else
00507   {
00508     bptr++;
00509   }
00510 }
00511 
00515 void fixed_smartlist2::read_file(void)
00516 {
00517   //rewind the file
00518   off_t pos=lseek(fp,0L,SEEK_SET);
00519   char buffer[50000];
00520   int offset=0;
00521   fixed_list_entry * b= (fixed_list_entry*) &(buffer[0]);
00522   cout << b << endl;
00523   ssize_t nw = 0;
00524   do
00525   {
00526     int nbytes = 0;
00527     nw = ::read(fp,&nbytes,sizeof(int));
00528     if (nw != -1)
00529     {
00530       nw = ::read(fp, buffer + offset, (size_t)nbytes);
00531       if (nw != -1)
00532       {
00533         offset+=nbytes;
00534         nw = ::read(fp,&pos,sizeof(off_t));
00535       }
00536     }
00537   }
00538   while(nw);
00539 }