ADMB Documentation  11.4.2890
 All Classes Files Functions Variables Typedefs Friends Defines
df1b2f13.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 
00027 fixed_smartlist::fixed_smartlist()
00028 {
00029   nentries=0;
00030   bufsize=0;
00031   buffer=0;
00032   true_buffer=0;
00033   buffend=0;
00034   bptr=0;
00035   fp=-1;
00036 }
00037 
00042 void fixed_smartlist::reset(void)
00043 {
00044   end_saved=0;
00045   bptr=buffer;
00046   eof_flag=0;
00047   /*off_t pos=*/lseek(fp,0L,SEEK_CUR);
00048   endof_file_ptr=lseek(fp,0L,SEEK_SET);
00049   written_flag=0;
00050 }
00055 fixed_smartlist::fixed_smartlist(const size_t _bufsize,
00056   const adstring& _filename)
00057 {
00058   allocate(_bufsize,_filename);
00059 }
00060 void fixed_smartlist::allocate(const size_t _bufsize,const adstring& _filename)
00061 {
00062   nentries=_bufsize/sizeof(fixed_list_entry);
00063   end_saved=0;
00064   eof_flag=0;
00065   noreadflag=0;
00066   written_flag=0;
00067   direction=0;
00068   bufsize=_bufsize;
00069   filename=_filename;
00070   AD_ALLOCATE(true_buffer, fixed_list_entry, nentries + 2, df1b2_gradlist)
00071 #ifndef OPT_LIB
00072   memset(true_buffer, 0, (nentries + 2) * sizeof(fixed_list_entry));
00073 #endif
00074   true_buffend=true_buffer+nentries+1;
00075   buffer=true_buffer+1;
00076   buffend=true_buffend-2;
00077   bptr=buffer;
00078   fp=open((char*)(filename), O_RDWR | O_CREAT | O_TRUNC |
00079                    O_BINARY, S_IREAD | S_IWRITE);
00080   if (fp == -1)
00081   {
00082     cerr << "Error trying to open file " << filename
00083          << " in class fixed_smartlist " << endl;
00084     ad_exit(1);
00085   }
00086 
00087   /*off_t pos=*/lseek(fp,0L,SEEK_CUR);
00088 }
00089 
00093 void fixed_smartlist::write(const size_t n)
00094 {
00095 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00096   #ifndef OPT_LIB
00097   assert(n <= UINT_MAX);
00098   #endif
00099   ssize_t nw = ::write(fp,buffer,(unsigned int)n);
00100 #else
00101   ssize_t nw = ::write(fp, buffer, n);
00102 #endif
00103   if (nw <= -1 || (size_t)nw != n)
00104   {
00105     cerr << "Error writing to file " << filename << endl;
00106     ad_exit(1);
00107   }
00108 }
00109 
00114 void fixed_smartlist::rewind(void)
00115 {
00116   bptr=buffer;
00117   eof_flag=0;
00118   if (written_flag)
00119   {
00120     lseek(fp,0L,SEEK_SET);
00121     // get the record size
00122     unsigned int nbytes=0;
00123     ssize_t ret = ::read(fp,&nbytes,sizeof(unsigned int));
00124     assert(ret != -1);
00125     if (nbytes > bufsize)
00126     {
00127       cerr << "Error -- record size in file seems to be larger than"
00128        " the buffer it was created from " << endl
00129         << " buffer size is " << bufsize << " record size is supposedly "
00130         << nbytes << endl;
00131       ad_exit(1);
00132     }
00133     // now read the record into the buffer
00134     ret = ::read(fp,buffer,nbytes);
00135     assert(ret != -1);
00136     //cout << "Number of bytes read " << nr << endl;
00137     // skip over file postion entry in file
00138     // so we are ready to read second record
00139     lseek(fp,(off_t)sizeof(off_t),SEEK_CUR);
00140   }
00141 }
00142 
00147 void fixed_smartlist::initialize(void)
00148 {
00149   end_saved=0;
00150   eof_flag=0;
00151   bptr=buffer;
00152   //int nbytes=0;
00153   written_flag=0;
00154   lseek(fp,0L,SEEK_SET);
00155   set_forward();
00156 }
00157 
00162 void fixed_smartlist::check_buffer_size(const size_t nsize)
00163 {
00164   if ( bptr+nsize-1 > buffend)
00165   {
00166     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00167     {
00168       read_buffer();
00169     }
00170     else
00171     {
00172       if (nsize>bufsize)
00173       {
00174          cout << "Need to increase buffsize in list" << endl;
00175          exit(1);
00176       }
00177       write_buffer();
00178     }
00179   }
00180 }
00181 
00186 void fixed_smartlist::restore_end(void)
00187 {
00188   if (written_flag)
00189   {
00190     if (end_saved)
00191     {
00192       /*off_t ipos=*/lseek(fp,0L,SEEK_END);
00193       lseek(fp,endof_file_ptr,SEEK_SET);
00194       read_buffer();
00195       set_recend();
00196     }
00197   }
00198 }
00199 
00204 void fixed_smartlist::save_end(void)
00205 {
00206   if (written_flag)
00207   {
00208     if (!end_saved)
00209     {
00210       write_buffer_one_less();
00211       end_saved=1;
00212     }
00213   }
00214 }
00215 
00220 void fixed_smartlist::write_buffer_one_less(void)
00221 {
00222   int _nbytes=adptr_diff(bptr,buffer);
00223   if (_nbytes > 0)
00224   {
00225     const unsigned int nbytes = (unsigned int)_nbytes;
00226 
00227     written_flag=1;
00228     // get the current file position
00229     off_t pos=lseek(fp,0L,SEEK_CUR);
00230 
00231     // write the size of the next record into the file
00232 #if defined(OPT_LIB) && !defined(_MSC_VER)
00233     ::write(fp, &nbytes, sizeof(unsigned int));
00234 #else
00235     ssize_t ret = ::write(fp, &nbytes, sizeof(unsigned int));
00236     assert(ret != -1);
00237 #endif
00238 
00239     // write the record into the file
00240     ssize_t nw = ::write(fp,buffer,nbytes);
00241 #ifndef OPT_LIB
00242     assert(nw != -1);
00243 #endif
00244     if ((size_t)nw < nbytes)
00245     {
00246       cerr << "Error writing to file " << filename << endl;
00247       ad_exit(1);
00248     }
00249     // reset the pointer to the beginning of the buffer
00250     bptr=buffer;
00251 
00252     // now write the previous file position into the file so we can back up
00253     // when we want to.
00254 #if defined(OPT_LIB) && !defined(_MSC_VER)
00255     ::write(fp,&pos,sizeof(off_t));
00256 #else
00257     ret = ::write(fp,&pos,sizeof(off_t));
00258     assert(ret != -1);
00259 #endif
00260 
00261     endof_file_ptr=lseek(fp,0L,SEEK_CUR);
00262     //cout << lseek(fp,0L,SEEK_CUR) << endl;
00263   }
00264 }
00265 
00270 void fixed_smartlist::write_buffer(void)
00271 {
00272   int _nbytes=adptr_diff(bptr+1,buffer);
00273   if (_nbytes > 0)
00274   {
00275     unsigned int nbytes = (unsigned int)_nbytes;
00276     if (nbytes > bufsize)
00277     {
00278       cerr << "n bytes > bufsize in "
00279         "fixed_smartlist::write_buffer(void) this can't happen!" << endl;
00280     }
00281     written_flag=1;
00282     // get the current file position
00283     off_t pos=lseek(fp,0L,SEEK_CUR);
00284 
00285     // write the size of the next record into the file
00286     ssize_t ret = ::write(fp,&nbytes,sizeof(unsigned int));
00287     assert(ret != -1);
00288 
00289     // write the record into the file
00290     ssize_t nw=::write(fp,buffer,nbytes);
00291 #ifndef OPT_LIB
00292     assert(nw != -1);
00293 #endif
00294     if ((size_t)nw < nbytes)
00295     {
00296       cerr << "Error writing to file " << filename << endl;
00297       ad_exit(1);
00298     }
00299     // reset the pointer to the beginning of the buffer
00300     bptr=buffer;
00301 
00302     // now write the previous file position into the file so we can back up
00303     // when we want to.
00304     ret = ::write(fp,&pos,sizeof(off_t));
00305     assert(ret != -1);
00306 
00307     endof_file_ptr=lseek(fp,0L,SEEK_CUR);
00308     //cout << lseek(fp,0L,SEEK_CUR) << endl;
00309   }
00310 }
00311 
00316 void fixed_smartlist::read_buffer(void)
00317 {
00318   if (!written_flag)
00319   {
00320     if (direction ==-1)
00321       eof_flag=-1;
00322     else
00323       eof_flag=1;
00324   }
00325   else
00326   {
00327     off_t pos = 0;
00328     if (direction ==-1) // we are going backwards
00329     {
00330       off_t ipos=lseek(fp,0L,SEEK_CUR);
00331       if (ipos ==0)
00332       {
00333         eof_flag=-1;
00334         return;
00335       }
00336       // offset of the begining of the record is at the end
00337       // of the record
00338       lseek(fp,-((off_t)sizeof(off_t)),SEEK_CUR);
00339       ssize_t ret = read(fp,&pos,sizeof(off_t));
00340       assert(ret != -1);
00341       // back up to the beginning of the record (plus record size)
00342       lseek(fp,pos,SEEK_SET);
00343       //*(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00344     }
00345     // get the record size
00346     unsigned int nbytes = 0;
00347     ssize_t ret = ::read(fp,&nbytes,sizeof(unsigned int));
00348     assert(ret != -1);
00349     if (nbytes > bufsize)
00350     {
00351       cerr << "Error -- record size in file seems to be larger than"
00352        " the buffer it was created from " << endl
00353         << " buffer size is " << bufsize << " record size is supposedly "
00354         << nbytes << endl;
00355       ad_exit(1);
00356     }
00357     // now read the record into the buffer
00358     ssize_t nr = ::read(fp,buffer,nbytes);
00359 #ifndef OPT_LIB
00360     assert(nr != -1);
00361 #endif
00362     if ((size_t)nr != nbytes)
00363     {
00364       cerr << "Error reading -- should be " << nbytes << " got " << nr << endl;
00365       exit(1);
00366     }
00367 
00368     // reset the pointer to the beginning of the buffer
00369     bptr=buffer;
00370     int ns=nbytes/(int)sizeof(fixed_list_entry);
00371     recend=bptr+ns-1;
00372     //cout << "Number of bytes read " << nr
00373      //    << "  recend value = " << recend << endl;
00374     if (direction ==-1) // we are going backwards
00375     {
00376       // backup the file pointer again
00377       lseek(fp,pos,SEEK_SET);
00378       // *(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00379     }
00380     else  // we are going forward
00381     {
00382       // skip over file postion entry in file
00383       lseek(fp,(off_t)sizeof(off_t),SEEK_CUR);
00384     }
00385   }
00386 }
00387 
00392 void memcpy(const fixed_smartlist& _list, void* p, const size_t nsize)
00393 {
00394   ADUNCONST(fixed_smartlist,list)
00395   if (list.bptr+nsize-1 > list.buffend)
00396   {
00397     cerr << " Trying to write outside list buffer" << endl;
00398     exit(1);
00399   }
00400   memcpy(list.bptr,p,nsize);
00401   list.bptr+=nsize;
00402 }
00403 
00408 void memcpy(void* p, const fixed_smartlist& _list, const size_t nsize)
00409 {
00410   ADUNCONST(fixed_smartlist,list)
00411   if (list.bptr+nsize-1 > list.buffend)
00412   {
00413     cerr << " Trying to write outside list buffer" << endl;
00414     exit(1);
00415   }
00416   memcpy(p,list.bptr,nsize);
00417   list.bptr+=nsize;
00418 }
00419 
00420 void fixed_smartlist::operator -= (int n)
00421 {
00422   if (bptr-n<buffer)
00423   {
00424     if (bptr != buffer)
00425     {
00426       cerr << " Sanity error in fixed_smartlist::operator -= (int)" << endl;
00427       exit(1);
00428     }
00429     else
00430     {
00431       // get previous record from the file
00432       read_buffer();
00433       bptr=recend-n+1;
00434     }
00435   }
00436   else
00437   {
00438     bptr-=n;
00439   }
00440 }
00441 void fixed_smartlist::operator -- (void)
00442 {
00443   if (bptr-1<buffer)
00444   {
00445     if (bptr != buffer)
00446     {
00447       cerr << " Sanity error in fixed_smartlist::operator -= (int)" << endl;
00448       exit(1);
00449     }
00450     else
00451     {
00452       // get previous record from the file
00453       read_buffer();
00454       //bptr=recend+1;
00455       bptr=recend;
00456     }
00457   }
00458   else
00459   {
00460     bptr--;
00461   }
00462 }
00463 
00464 void fixed_smartlist::operator += (int nsize)
00465 {
00466   if ( bptr+nsize-1 > buffend)
00467   {
00468     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00469     {
00470       read_buffer();
00471     }
00472     else
00473     {
00474       if ((unsigned int)nsize>bufsize)
00475       {
00476         cout << "Need to increase buffsize in list" << endl;
00477         exit(1);
00478       }
00479       write_buffer();
00480     }
00481   }
00482   else
00483   {
00484     bptr+=nsize;
00485   }
00486 }
00487 
00492 void fixed_smartlist::operator ++ (void)
00493 {
00494   if ( bptr==buffend)
00495   {
00496     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00497     {
00498       read_buffer();
00499     }
00500     else
00501     {
00502       write_buffer();
00503     }
00504   }
00505   else
00506   {
00507     bptr++;
00508   }
00509 }
00510 
00514 void fixed_smartlist::read_file(void)
00515 {
00516   //rewind the file
00517   off_t pos=lseek(fp,0L,SEEK_SET);
00518   char buffer[50000];
00519   int offset=0;
00520   fixed_list_entry * b= (fixed_list_entry*) &(buffer[0]);
00521   cout << b << endl;
00522   ssize_t nw = 0;
00523   do
00524   {
00525     unsigned int nbytes=0;
00526     nw = ::read(fp,&nbytes,sizeof(unsigned int));
00527     if (nw != -1)
00528     {
00529       nw = ::read(fp, buffer + offset, (size_t)nbytes);
00530       if (nw != -1)
00531       {
00532         offset+=nbytes;
00533         nw = ::read(fp, &pos, sizeof(off_t));
00534       }
00535     }
00536   }
00537   while(nw);
00538 }