ADMB Documentation  11.6rc.3352
 All Classes Files Functions Variables Typedefs Friends Defines
df1b2f10.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 
00013 #ifdef OPT_LIB
00014   #define NDEBUG
00015 #endif
00016 #include <cassert>
00017 
00018 #ifdef _MSC_VER
00019   #ifdef _M_X64
00020   typedef __int64 ssize_t;
00021   #else
00022   typedef int ssize_t;
00023   #endif
00024 #else
00025   #include <unistd.h>
00026 #endif
00027 
00032 void test_smartlist::reset(void)
00033 {
00034   bptr=buffer;
00035   eof_flag=0;
00036   lseek(fp, 0L, SEEK_SET);
00037   written_flag=0;
00038   end_saved=0;
00039 }
00040 
00044 test_smartlist::test_smartlist()
00045 {
00046   bufsize=0;
00047   buffer=0;
00048   true_buffer=0;
00049   buffend=0;
00050   bptr=0;
00051   fp=-1;
00052 }
00056 test_smartlist::test_smartlist(const size_t _bufsize,const adstring& _filename):
00057   recend(NULL),
00058   sbptr(NULL)
00059 {
00060   allocate(_bufsize,_filename);
00061 }
00062 
00067 void test_smartlist::allocate(const size_t _bufsize,const adstring& _filename)
00068 {
00069   //cerr << "need to modify test_smartlist class for multibyte char" << endl;
00070   assert(sizeof(char) == 1);
00071 
00072   end_saved=0;
00073   eof_flag=0;
00074   noreadflag=0;
00075   written_flag=0;
00076   direction=0;
00077   bufsize=_bufsize;
00078   filename=_filename;
00079   //AD_ALLOCATE(true_buffer,char,bufsize+2*sizeof(double),df1b2_gradlist)
00080   if ((true_buffer=new char[(bufsize+2)*sizeof(double) ])==0)
00081   {
00082     cerr << "Allocation error in df1b2_gradlist" << endl;
00083     ad_exit(1);
00084   }
00085   doubleptr=(double*)true_buffer;
00086   true_buffend=true_buffer+bufsize+2*sizeof(double)-1;
00087   buffer=true_buffer+sizeof(double);
00088   *(double*)(true_buffer)=5678.9;
00089   *(double*)(true_buffer+bufsize+sizeof(double))=9876.5;
00090   //buffend=true_buffer+bufsize-1+sizeof(double);
00091   buffend=true_buffer+bufsize-1;
00092   bptr=buffer;
00093   fp=open((char*)(filename), O_RDWR | O_CREAT | O_TRUNC |
00094                    O_BINARY, S_IREAD | S_IWRITE);
00095   if (fp == -1)
00096   {
00097     cerr << "Error trying to open file " << filename
00098          << " in class test_smartlist " << endl;
00099     exit(1);
00100   }
00101 
00102   /*off_t pos=*/lseek(fp,0L,SEEK_CUR);
00103 }
00104 
00109 void test_smartlist::write(const size_t n)
00110 {
00111 #if defined(__MINGW64__) || (defined(_MSC_VER) && defined(_WIN64))
00112   #ifndef OPT_LIB
00113   assert(n <= UINT_MAX);
00114   #endif
00115   ssize_t nw = ::write(fp,buffer,(unsigned int)n);
00116 #else
00117   ssize_t nw = ::write(fp,buffer,n);
00118 #endif
00119   if (nw <= -1 || n != (size_t)nw)
00120   {
00121     cerr << "Error writing to file " << filename << endl;
00122     ad_exit(1);
00123   }
00124 }
00125 
00130 void test_smartlist::rewind(void)
00131 {
00132   bptr=buffer;
00133   if (written_flag)
00134   {
00135     lseek(fp,0L,SEEK_SET);
00136     // get the record size
00137     unsigned int nbytes = 0;
00138 #ifdef OPT_LIB
00139     ::read(fp,&nbytes,sizeof(unsigned int));
00140 #else
00141     ssize_t ret = ::read(fp,&nbytes,sizeof(unsigned int));
00142     assert(ret != -1);
00143 #endif
00144     if (nbytes > bufsize)
00145     {
00146       cerr << "Error -- record size in file seems to be larger than"
00147        " the buffer it was created from " << endl
00148         << " buffer size is " << bufsize << " record size is supposedly "
00149         << nbytes << endl;
00150     }
00151 #ifdef OPT_LIB
00152     ::read(fp,buffer,nbytes);
00153 #else
00154     // now read the record into the buffer
00155     ret = ::read(fp,buffer,nbytes);
00156     assert(ret != -1);
00157 #endif
00158 
00159     // skip over file postion entry in file
00160     // so we are ready to read second record
00161 #ifdef OPT_LIB
00162     lseek(fp, (off_t)sizeof(off_t), SEEK_CUR);
00163 #else
00164     ret = lseek(fp, (off_t)sizeof(off_t), SEEK_CUR);
00165     assert(ret >= 0);
00166 #endif
00167   }
00168 }
00169 
00174 void test_smartlist::initialize(void)
00175 {
00176   end_saved=0;
00177   bptr=buffer;
00178   //int nbytes=0;
00179   written_flag=0;
00180   lseek(fp,0L,SEEK_SET);
00181   set_forward();
00182 }
00183 
00188 void test_smartlist::check_buffer_size(const size_t nsize)
00189 {
00190   if ( bptr+nsize-1 > buffend)
00191   {
00192     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00193     {
00194       read_buffer();
00195     }
00196     else
00197     {
00198       if (nsize>bufsize)
00199       {
00200          cout << "Need to increase buffsize in list" << endl;
00201          exit(1);
00202       }
00203       write_buffer();
00204     }
00205   }
00206 }
00207 
00212 void test_smartlist::restore_end(void)
00213 {
00214   if (written_flag)
00215   {
00216     if (end_saved)
00217     {
00218       read_buffer();
00219       set_recend();
00220     }
00221   }
00222 }
00223 
00228 void test_smartlist::save_end(void)
00229 {
00230   if (written_flag)
00231   {
00232     if (!end_saved)
00233     {
00234       write_buffer();
00235       end_saved=1;
00236     }
00237   }
00238 }
00239 
00244 void test_smartlist::write_buffer(void)
00245 {
00246   int _nbytes=adptr_diff(bptr,buffer);
00247   if (_nbytes > 0)
00248   {
00249     const unsigned int nbytes = (unsigned int)_nbytes;
00250 
00251     written_flag=1;
00252     // get the current file position
00253     off_t pos=lseek(fp,0L,SEEK_CUR);
00254 
00255     // write the size of the next record into the file
00256 #if defined(OPT_LIB) && !defined(_MSC_VER)
00257     ::write(fp,&nbytes,sizeof(int));
00258 #else
00259     ssize_t ret = ::write(fp,&nbytes,sizeof(int));
00260     assert(ret != -1);
00261 #endif
00262 
00263     // write the record into the file
00264     ssize_t nw=::write(fp,buffer,nbytes);
00265     if (nw <= -1 || (unsigned int)nw != nbytes)
00266     {
00267       cerr << "Error writing to file " << filename << endl;
00268       ad_exit(1);
00269     }
00270     // reset the pointer to the beginning of the buffer
00271     bptr=buffer;
00272 
00273     // now write the previous file position into the file so we can back up
00274     // when we want to.
00275 #if defined(OPT_LIB) && !defined(_MSC_VER)
00276     ::write(fp,&pos,sizeof(off_t));
00277 #else
00278     ret = ::write(fp,&pos,sizeof(off_t));
00279     assert(ret != -1);
00280 #endif
00281 
00282     //cout << lseek(fp,0L,SEEK_CUR) << endl;
00283   }
00284 }
00285 
00286 #include <cassert>
00291 void test_smartlist::read_buffer(void)
00292 {
00293   if (!written_flag)
00294   {
00295     if (direction ==-1)
00296       eof_flag=-1;
00297     else
00298       eof_flag=1;
00299   }
00300   else
00301   {
00302     off_t pos = sizeof(off_t);
00303     if (direction ==-1) // we are going backwards
00304     {
00305       // offset of the begining of the record is at the end
00306       // of the record
00307       lseek(fp,-pos,SEEK_CUR);
00308 #ifdef OPT_LIB
00309       ::read(fp, &pos, sizeof(off_t));
00310 #else
00311       ssize_t ret = read(fp,&pos,sizeof(off_t));
00312       assert(ret != -1);
00313 #endif
00314       // back up to the beginning of the record (plus record size)
00315       lseek(fp,pos,SEEK_SET);
00316       //*(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00317     }
00318     // get the record size
00319     unsigned int nbytes = 0;
00320 #ifdef OPT_LIB
00321     ::read(fp,&nbytes,sizeof(unsigned int));
00322 #else
00323     ssize_t ret = ::read(fp,&nbytes,sizeof(unsigned int));
00324     assert(ret != -1);
00325 #endif
00326     if (nbytes <= 0 || nbytes > bufsize)
00327     {
00328       cerr << "Error -- record size in file seems to be larger than"
00329        " the buffer it was created from " << endl
00330         << " buffer size is " << bufsize << " record size is supposedly "
00331         << nbytes << endl;
00332       ad_exit(1);
00333     }
00334     // now read the record into the buffer
00335     ssize_t nr = ::read(fp,buffer,nbytes);
00336     if (nr <= -1 || (size_t)nr != nbytes)
00337     {
00338       cerr << "Error reading -- should be " << nbytes << " got " << nr << endl;
00339       exit(1);
00340     }
00341     // reset the pointer to the beginning of the buffer
00342     bptr=buffer;
00343     recend=bptr+nbytes-1;
00344     if (direction ==-1) // we are going backwards
00345     {
00346       // backup the file pointer again
00347 #ifdef OPT_LIB
00348       lseek(fp,pos,SEEK_SET);
00349 #else
00350       off_t ret = lseek(fp,pos,SEEK_SET);
00351       assert(ret >= 0);
00352 #endif
00353       // *(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00354     }
00355     else  // we are going forward
00356     {
00357       // skip over file postion entry in file
00358 #ifdef OPT_LIB
00359       lseek(fp, pos, SEEK_CUR);
00360 #else
00361       off_t ret = lseek(fp, pos, SEEK_CUR);
00362       assert(ret >= 0);
00363 #endif
00364     }
00365   }
00366 }
00367 
00371 void memcpy(test_smartlist& dest, void* source, const size_t nsize)
00372 {
00373 #ifndef OPT_LIB
00374   //Trying to write outside list buffer
00375   assert(dest.bptr + nsize - 1 <= dest.buffend);
00376 #endif
00377 
00378   memcpy(dest.bptr, source, nsize);
00379   dest.bptr += nsize;
00380 }
00381 
00385 void memcpy(void* dest, test_smartlist& source, const size_t nsize)
00386 {
00387 #ifndef OPT_LIB
00388   //Trying to write outside list buffer
00389   assert(source.bptr + nsize - 1 <= source.buffend);
00390 #endif
00391 
00392   memcpy(dest, source.bptr, nsize);
00393   source.bptr += nsize;
00394 }
00395 
00400 void test_smartlist::operator-=(const int n)
00401 {
00402   if (bptr-n<buffer)
00403   {
00404     if (bptr != buffer)
00405     {
00406       cerr << " Sanity error in test_smartlist::operator -= (int)" << endl;
00407       exit(1);
00408     }
00409     else
00410     {
00411       // get previous record from the file
00412       read_buffer();
00413       bptr=recend-n+1;
00414     }
00415   }
00416   else
00417   {
00418     bptr-=n;
00419   }
00420 }
00421 
00426 void test_smartlist::operator+=(const int nsize)
00427 {
00428   if ( bptr+nsize-1 > buffend)
00429   {
00430     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00431     {
00432       read_buffer();
00433     }
00434     else
00435     {
00436       if ((unsigned int)nsize>bufsize)
00437       {
00438          cout << "Need to increase buffsize in list" << endl;
00439          exit(1);
00440       }
00441       write_buffer();
00442     }
00443   }
00444   else
00445   {
00446     bptr+=nsize;
00447   }
00448 }
00452 test_smartlist::~test_smartlist()
00453 {
00454   end_saved=0;
00455   eof_flag=0;
00456   noreadflag=0;
00457   written_flag=0;
00458   direction=0;
00459   bufsize=0;
00460 
00461   if (true_buffer)
00462   {
00463     delete [] true_buffer;
00464     true_buffer=0;
00465   }
00466   true_buffend=0;
00467   buffer=0;
00468   buffend=0;
00469   bptr=0;
00470   off_t pos=lseek(fp,0L,SEEK_END);
00471   int on1=-1;
00472   if ( (on1=option_match(ad_comm::argc,ad_comm::argv,"-fsize"))>-1)
00473   {
00474     if (ad_comm::global_logfile)
00475     {
00476       *ad_comm::global_logfile << "size of file " << filename
00477         << " = " << pos << endl;
00478     }
00479   }
00480   close(fp);
00481   fp=0;
00482 #if defined (_MSC_VER)
00483   remove(filename);
00484 #else
00485   unlink(filename);
00486 #endif
00487 }