ADMB Documentation  11.4.2891
 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(void)
00045 {
00046   bufsize=0;
00047   buffer=0;
00048   true_buffer=0;
00049   buffend=0;
00050   bptr=0;
00051   fp=-1;
00052 }
00053 
00058 test_smartlist::test_smartlist(const size_t _bufsize,const adstring& _filename)
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   true_buffend=true_buffer+bufsize+2*sizeof(double)-1;
00086   buffer=true_buffer+sizeof(double);
00087   buffend=true_buffer+bufsize-1;
00088   bptr=buffer;
00089   fp=open((char*)(filename), O_RDWR | O_CREAT | O_TRUNC |
00090                    O_BINARY, S_IREAD | S_IWRITE);
00091   if (fp == -1)
00092   {
00093     cerr << "Error trying to open file " << filename
00094          << " in class test_smartlist " << endl;
00095     exit(1);
00096   }
00097 
00098   /*off_t pos=*/lseek(fp,0L,SEEK_CUR);
00099 }
00100 
00105 void test_smartlist::write(const size_t n)
00106 {
00107 #if defined(__MINGW64__) || (defined(_MSC_VER) && defined(_WIN64))
00108   #ifndef OPT_LIB
00109   assert(n <= UINT_MAX);
00110   #endif
00111   ssize_t nw = ::write(fp,buffer,(unsigned int)n);
00112 #else
00113   ssize_t nw = ::write(fp,buffer,n);
00114 #endif
00115   if (nw <= -1 || n != (size_t)nw)
00116   {
00117     cerr << "Error writing to file " << filename << endl;
00118     ad_exit(1);
00119   }
00120 }
00121 
00126 void test_smartlist::rewind(void)
00127 {
00128   bptr=buffer;
00129   if (written_flag)
00130   {
00131     lseek(fp,0L,SEEK_SET);
00132     // get the record size
00133     unsigned int nbytes = 0;
00134 #ifdef OPT_LIB
00135     ::read(fp,&nbytes,sizeof(unsigned int));
00136 #else
00137     ssize_t ret = ::read(fp,&nbytes,sizeof(unsigned int));
00138     assert(ret != -1);
00139 #endif
00140     if (nbytes > bufsize)
00141     {
00142       cerr << "Error -- record size in file seems to be larger than"
00143        " the buffer it was created from " << endl
00144         << " buffer size is " << bufsize << " record size is supposedly "
00145         << nbytes << endl;
00146     }
00147 #ifdef OPT_LIB
00148     ::read(fp,buffer,nbytes);
00149 #else
00150     // now read the record into the buffer
00151     ret = ::read(fp,buffer,nbytes);
00152     assert(ret != -1);
00153 #endif
00154     //cout << "Number of bytes read " << nr << endl;
00155     // skip over file postion entry in file
00156     // so we are ready to read second record
00157     lseek(fp, (off_t)sizeof(off_t), SEEK_CUR);
00158   }
00159 }
00160 
00165 void test_smartlist::initialize(void)
00166 {
00167   end_saved=0;
00168   bptr=buffer;
00169   //int nbytes=0;
00170   written_flag=0;
00171   lseek(fp,0L,SEEK_SET);
00172   set_forward();
00173 }
00174 
00179 void test_smartlist::check_buffer_size(const size_t nsize)
00180 {
00181   if ( bptr+nsize-1 > buffend)
00182   {
00183     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00184     {
00185       read_buffer();
00186     }
00187     else
00188     {
00189       if (nsize>bufsize)
00190       {
00191          cout << "Need to increase buffsize in list" << endl;
00192          exit(1);
00193       }
00194       write_buffer();
00195     }
00196   }
00197 }
00198 
00203 void test_smartlist::restore_end(void)
00204 {
00205   if (written_flag)
00206   {
00207     if (end_saved)
00208     {
00209       read_buffer();
00210       set_recend();
00211     }
00212   }
00213 }
00214 
00219 void test_smartlist::save_end(void)
00220 {
00221   if (written_flag)
00222   {
00223     if (!end_saved)
00224     {
00225       write_buffer();
00226       end_saved=1;
00227     }
00228   }
00229 }
00230 
00235 void test_smartlist::write_buffer(void)
00236 {
00237   int _nbytes=adptr_diff(bptr,buffer);
00238   if (_nbytes > 0)
00239   {
00240     const unsigned int nbytes = (unsigned int)_nbytes;
00241 
00242     written_flag=1;
00243     // get the current file position
00244     off_t pos=lseek(fp,0L,SEEK_CUR);
00245 
00246     // write the size of the next record into the file
00247 #if defined(OPT_LIB) && !defined(_MSC_VER)
00248     ::write(fp,&nbytes,sizeof(int));
00249 #else
00250     ssize_t ret = ::write(fp,&nbytes,sizeof(int));
00251     assert(ret != -1);
00252 #endif
00253 
00254     // write the record into the file
00255     ssize_t nw=::write(fp,buffer,nbytes);
00256     if (nw <= -1 || (unsigned int)nw != nbytes)
00257     {
00258       cerr << "Error writing to file " << filename << endl;
00259       ad_exit(1);
00260     }
00261     // reset the pointer to the beginning of the buffer
00262     bptr=buffer;
00263 
00264     // now write the previous file position into the file so we can back up
00265     // when we want to.
00266 #if defined(OPT_LIB) && !defined(_MSC_VER)
00267     ::write(fp,&pos,sizeof(off_t));
00268 #else
00269     ret = ::write(fp,&pos,sizeof(off_t));
00270     assert(ret != -1);
00271 #endif
00272 
00273     //cout << lseek(fp,0L,SEEK_CUR) << endl;
00274   }
00275 }
00276 
00281 void test_smartlist::read_buffer(void)
00282 {
00283   if (!written_flag)
00284   {
00285     if (direction ==-1)
00286       eof_flag=-1;
00287     else
00288       eof_flag=1;
00289   }
00290   else
00291   {
00292     off_t pos = sizeof(off_t);
00293     if (direction ==-1) // we are going backwards
00294     {
00295       // offset of the begining of the record is at the end
00296       // of the record
00297       lseek(fp,-pos,SEEK_CUR);
00298 #ifdef OPT_LIB
00299       ::read(fp, &pos, sizeof(off_t));
00300 #else
00301       ssize_t ret = read(fp,&pos,sizeof(off_t));
00302       assert(ret != -1);
00303 #endif
00304       // back up to the beginning of the record (plus record size)
00305       lseek(fp,pos,SEEK_SET);
00306       //*(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00307     }
00308     // get the record size
00309     unsigned int nbytes = 0;
00310 #ifdef OPT_LIB
00311     ::read(fp,&nbytes,sizeof(unsigned int));
00312 #else
00313     ssize_t ret = ::read(fp,&nbytes,sizeof(unsigned int));
00314     assert(ret != -1);
00315 #endif
00316     if (nbytes > bufsize)
00317     {
00318       cerr << "Error -- record size in file seems to be larger than"
00319        " the buffer it was created from " << endl
00320         << " buffer size is " << bufsize << " record size is supposedly "
00321         << nbytes << endl;
00322     }
00323     // now read the record into the buffer
00324     ssize_t nr = ::read(fp,buffer,nbytes);
00325     if (nr <= -1 || (size_t)nr != nbytes)
00326     {
00327       cerr << "Error reading -- should be " << nbytes << " got " << nr << endl;
00328       exit(1);
00329     }
00330     // reset the pointer to the beginning of the buffer
00331     bptr=buffer;
00332     recend=bptr+nbytes-1;
00333     if (direction ==-1) // we are going backwards
00334     {
00335       // backup the file pointer again
00336       lseek(fp,pos,SEEK_SET);
00337       // *(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00338     }
00339     else  // we are going forward
00340     {
00341       // skip over file postion entry in file
00342       lseek(fp, pos, SEEK_CUR);
00343     }
00344   }
00345 }
00346 
00350 void memcpy(test_smartlist& dest, void* source, const size_t nsize)
00351 {
00352 #ifndef OPT_LIB
00353   //Trying to write outside list buffer
00354   assert(dest.bptr + nsize - 1 <= dest.buffend);
00355 #endif
00356 
00357   memcpy(dest.bptr, source, nsize);
00358   dest.bptr += nsize;
00359 }
00360 
00364 void memcpy(void* dest, test_smartlist& source, const size_t nsize)
00365 {
00366 #ifndef OPT_LIB
00367   //Trying to write outside list buffer
00368   assert(source.bptr + nsize - 1 <= source.buffend);
00369 #endif
00370 
00371   memcpy(dest, source.bptr, nsize);
00372   source.bptr += nsize;
00373 }
00374 
00379 void test_smartlist::operator-=(const int n)
00380 {
00381   if (bptr-n<buffer)
00382   {
00383     if (bptr != buffer)
00384     {
00385       cerr << " Sanity error in test_smartlist::operator -= (int)" << endl;
00386       exit(1);
00387     }
00388     else
00389     {
00390       // get previous record from the file
00391       read_buffer();
00392       bptr=recend-n+1;
00393     }
00394   }
00395   else
00396   {
00397     bptr-=n;
00398   }
00399 }
00400 
00405 void test_smartlist::operator+=(const int nsize)
00406 {
00407   if ( bptr+nsize-1 > buffend)
00408   {
00409     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00410     {
00411       read_buffer();
00412     }
00413     else
00414     {
00415       if ((unsigned int)nsize>bufsize)
00416       {
00417          cout << "Need to increase buffsize in list" << endl;
00418          exit(1);
00419       }
00420       write_buffer();
00421     }
00422   }
00423   else
00424   {
00425     bptr+=nsize;
00426   }
00427 }
00431 test_smartlist::~test_smartlist()
00432 {
00433   end_saved=0;
00434   eof_flag=0;
00435   noreadflag=0;
00436   written_flag=0;
00437   direction=0;
00438   bufsize=0;
00439 
00440   if (true_buffer)
00441   {
00442     delete [] true_buffer;
00443     true_buffer=0;
00444   }
00445   true_buffend=0;
00446   buffer=0;
00447   buffend=0;
00448   bptr=0;
00449   off_t pos=lseek(fp,0L,SEEK_END);
00450   int on1=-1;
00451   if ( (on1=option_match(ad_comm::argc,ad_comm::argv,"-fsize"))>-1)
00452   {
00453     if (ad_comm::global_logfile)
00454     {
00455       *ad_comm::global_logfile << "size of file " << filename
00456         << " = " << pos << endl;
00457     }
00458   }
00459   close(fp);
00460   fp=0;
00461 #if defined (_MSC_VER)
00462   remove(filename);
00463 #else
00464   unlink(filename);
00465 #endif
00466 }