ADMB Documentation  11.5.3197
 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 
00027 fixed_smartlist2::fixed_smartlist2():
00028   endof_file_ptr(-1),
00029   doubleptr(NULL),
00030   recend(NULL),
00031   sbptr(NULL),
00032   fp(-1)
00033 {
00034   nentries=0;
00035   end_saved=0;
00036   eof_flag=0;
00037   noreadflag=0;
00038   written_flag=0;
00039   direction=0;
00040   bufsize=0;
00041   true_buffer=0;
00042   true_buffend=0;
00043   buffer=0;
00044   buffend=0;
00045   bptr=buffer;
00046 }
00050 fixed_smartlist2::fixed_smartlist2(const size_t _bufsize,
00051   const adstring& _filename):
00052   endof_file_ptr(-1),
00053   recend(NULL),
00054   sbptr(NULL)
00055 {
00056   allocate(_bufsize,_filename);
00057 }
00058 
00063 void fixed_smartlist2::allocate(const size_t _bufsize,
00064   const adstring& _filename)
00065 {
00066   nentries=_bufsize/sizeof(int);
00067   end_saved=0;
00068   eof_flag=0;
00069   noreadflag=0;
00070   written_flag=0;
00071   direction=0;
00072   bufsize=_bufsize;
00073   filename=_filename;
00074   AD_ALLOCATE(true_buffer,int,nentries+2,df1b2_gradlist)
00075   doubleptr=(double*)true_buffer;
00076   true_buffend=true_buffer+nentries+1;
00077   buffer=true_buffer+1;
00078   buffend=true_buffend-1;
00079   bptr=buffer;
00080   *true_buffer=5678;
00081   *true_buffend=9999;
00082   fp=open((char*)(filename), O_RDWR | O_CREAT | O_TRUNC |
00083                    O_BINARY, S_IREAD | S_IWRITE);
00084   if (fp < 0)
00085   {
00086     cerr << "Error trying to open file " << filename
00087          << " in class fixed_smartlist2 " << endl;
00088     ad_exit(1);
00089   }
00090   else
00091   {
00092     /*off_t pos=*/lseek(fp, 0L, SEEK_CUR);
00093   }
00094 }
00095 
00099 void fixed_smartlist2::write(const size_t n)
00100 {
00101 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00102   assert(n <= INT_MAX);
00103   ssize_t nw = ::write(fp, buffer, (int)n);
00104 #else
00105   ssize_t nw = ::write(fp, buffer, n);
00106 #endif
00107   if (nw <= -1 || (size_t)nw != n)
00108   {
00109     cerr << "Error writing to file " << filename << endl;
00110     ad_exit(1);
00111   }
00112 }
00113 
00117 void fixed_smartlist2::rewind(void)
00118 {
00119   bptr=buffer;
00120   eof_flag=0;
00121   if (written_flag)
00122   {
00123     lseek(fp,0L,SEEK_SET);
00124     // get the record size
00125     unsigned int nbytes = 0;
00126     ssize_t ret = ::read(fp,&nbytes,sizeof(unsigned int));
00127     assert(ret != -1);
00128     if (nbytes > bufsize)
00129     {
00130       cerr << "Error -- record size in file seems to be larger than"
00131        " the buffer it was created from " << endl
00132         << " buffer size is " << bufsize << " record size is supposedly "
00133         << nbytes << endl;
00134       ad_exit(1);
00135     }
00136     // now read the record into the buffer
00137     ret = ::read(fp,buffer,nbytes);
00138     assert(ret != -1);
00139     //cout << "Number of bytes read " << nr << endl;
00140     // skip over file postion entry in file
00141     // so we are ready to read second record
00142     lseek(fp,(off_t)sizeof(off_t),SEEK_CUR);
00143   }
00144 }
00145 
00150 void fixed_smartlist2::initialize(void)
00151 {
00152   end_saved=0;
00153   eof_flag=0;
00154   bptr=buffer;
00155   //int nbytes=0;
00156   written_flag=0;
00157   lseek(fp,0L,SEEK_SET);
00158   set_forward();
00159 }
00160 
00165 void fixed_smartlist2::check_buffer_size(const size_t nsize)
00166 {
00167   if ( bptr+nsize-1 > buffend)
00168   {
00169     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00170     {
00171       read_buffer();
00172     }
00173     else
00174     {
00175       if (nsize>bufsize)
00176       {
00177          cout << "Need to increase buffsize in list" << endl;
00178          exit(1);
00179       }
00180       write_buffer();
00181     }
00182   }
00183 }
00187 void fixed_smartlist2::restore_end()
00188 {
00189   if (written_flag)
00190   {
00191     if (end_saved)
00192     {
00193 #ifdef OPT_LIB
00194       lseek(fp, endof_file_ptr, SEEK_SET);
00195 #else
00196       off_t ret = lseek(fp, endof_file_ptr, SEEK_SET);
00197       assert(ret >= 0);
00198 #endif
00199       read_buffer();
00200       set_recend();
00201     }
00202   }
00203 }
00204 
00209 void fixed_smartlist2::save_end(void)
00210 {
00211   if (written_flag)
00212   {
00213     if (!end_saved)
00214     {
00215       write_buffer_one_less();
00216       end_saved=1;
00217     }
00218   }
00219 }
00220 
00225 void fixed_smartlist2::write_buffer_one_less(void)
00226 {
00227   int _nbytes=adptr_diff(bptr,buffer);
00228   if (_nbytes > 0)
00229   {
00230     unsigned int nbytes = (unsigned int)_nbytes;
00231 
00232     written_flag=1;
00233     // get the current file position
00234     off_t pos=lseek(fp,0L,SEEK_CUR);
00235 
00236     // write the size of the next record into the file
00237     ssize_t ret = ::write(fp,&nbytes,sizeof(unsigned int));
00238     assert(ret != -1);
00239 
00240     // write the record into the file
00241     ssize_t nw = ::write(fp,buffer,nbytes);
00242     if (nw < _nbytes)
00243     {
00244       cerr << "Error writing to file " << filename << endl;
00245       ad_exit(1);
00246     }
00247     // reset the pointer to the beginning of the buffer
00248     bptr=buffer;
00249 
00250     // now write the previous file position into the file so we can back up
00251     // when we want to.
00252     ret = ::write(fp,&pos,sizeof(off_t));
00253     assert(ret != -1);
00254 
00255     endof_file_ptr=lseek(fp,0L,SEEK_CUR);
00256 
00257     //cout << lseek(fp,0L,SEEK_CUR) << endl;
00258   }
00259 }
00260 
00265 void fixed_smartlist2::write_buffer(void)
00266 {
00267   int _nbytes=adptr_diff(bptr+1,buffer);
00268   if (_nbytes > 0)
00269   {
00270     unsigned int nbytes = (unsigned int)_nbytes;
00271 
00272     written_flag=1;
00273     // get the current file position
00274     off_t pos=lseek(fp,0L,SEEK_CUR);
00275 
00276     // write the size of the next record into the file
00277     ssize_t ret = ::write(fp, &nbytes, sizeof(unsigned int));
00278     assert(ret != -1);
00279 
00280     // write the record into the file
00281     ret = ::write(fp,buffer,nbytes);
00282     assert(ret != -1);
00283     if (ret < _nbytes)
00284     {
00285       cerr << "Error writing to file " << filename << endl;
00286       ad_exit(1);
00287     }
00288     // reset the pointer to the beginning of the buffer
00289     bptr=buffer;
00290 
00291     // now write the previous file position into the file so we can back up
00292     // when we want to.
00293     ret = ::write(fp,&pos,sizeof(off_t));
00294     assert(ret != -1);
00295 
00296     endof_file_ptr=lseek(fp,0L,SEEK_CUR);
00297 
00298     //cout << lseek(fp,0L,SEEK_CUR) << endl;
00299   }
00300 }
00301 
00305 void fixed_smartlist2::read_buffer(void)
00306 {
00307   if (!written_flag)
00308   {
00309     if (direction ==-1)
00310       eof_flag=-1;
00311     else
00312       eof_flag=1;
00313   }
00314   else
00315   {
00316     off_t pos = 0;
00317     if (direction ==-1) // we are going backwards
00318     {
00319       off_t ipos=lseek(fp,0L,SEEK_CUR);
00320       if (ipos ==0)
00321       {
00322         eof_flag=-1;
00323         return;
00324       }
00325       // offset of the begining of the record is at the end
00326       // of the record
00327 #ifdef OPT_LIB
00328       lseek(fp,-((off_t)sizeof(off_t)),SEEK_CUR);
00329 #else
00330       off_t ret2 = lseek(fp,-((off_t)sizeof(off_t)),SEEK_CUR);
00331       assert(ret2 >= 0);
00332 #endif
00333       ssize_t ret = read(fp,&pos,sizeof(off_t));
00334       assert(ret != -1);
00335 
00336       // back up to the beginning of the record (plus record size)
00337 #ifdef OPT_LIB
00338       lseek(fp,pos,SEEK_SET);
00339 #else
00340       ret2 = lseek(fp,pos,SEEK_SET);
00341       assert(ret2 >= 0);
00342 #endif
00343       //*(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00344     }
00345     // get the record size
00346     int _nbytes = 0;
00347     ssize_t ret = ::read(fp,&_nbytes,sizeof(int));
00348     assert(ret != -1);
00349     if (_nbytes > 0)
00350     {
00351       const size_t nbytes = (size_t)_nbytes;
00352       if (nbytes > bufsize)
00353       {
00354         cerr << "Error -- record size in file seems to be larger than"
00355          " the buffer it was created from " << endl
00356           << " buffer size is " << bufsize << " record size is supposedly "
00357           << nbytes << endl;
00358         ad_exit(1);
00359       }
00360       // now read the record into the buffer
00361 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00362       ssize_t nr = ::read(fp,buffer,_nbytes);
00363 #else
00364       ssize_t nr = ::read(fp,buffer,nbytes);
00365 #endif
00366       assert(nr != -1);
00367       if (nr != _nbytes)
00368       {
00369         cerr << "Error: read only " << nr << " of " << nbytes << "bytes.\n";
00370         exit(1);
00371       }
00372       // reset the pointer to the beginning of the buffer
00373       bptr=buffer;
00374       size_t ns = nbytes / sizeof(int);
00375       recend=bptr+ns-1;
00376       //cout << "Number of bytes read " << nr
00377        //    << "  recend value = " << recend << endl;
00378       if (direction ==-1) // we are going backwards
00379       {
00380         // backup the file pointer again
00381 #ifdef OPT_LIB
00382         lseek(fp,pos,SEEK_SET);
00383 #else
00384         off_t ret = lseek(fp,pos,SEEK_SET);
00385         assert(ret >= 0);
00386 #endif
00387         // *(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00388       }
00389       else  // we are going forward
00390       {
00391         //\todo need test
00392 
00393         // skip over file postion entry in file
00394 #ifdef OPT_LIB
00395         lseek(fp, (off_t)sizeof(off_t), SEEK_CUR);
00396 #else
00397         off_t ret = lseek(fp, (off_t)sizeof(off_t), SEEK_CUR);
00398         assert(ret >= 0);
00399 #endif
00400       }
00401     }
00402   }
00403 }
00404 
00409 void memcpy(const fixed_smartlist2 & _list,void * p, const size_t nsize)
00410 {
00411   ADUNCONST(fixed_smartlist2,list)
00412   if ( list.bptr+nsize-1 > list.buffend)
00413   {
00414     cerr << " Trying to write outside list buffer" << endl;
00415     exit(1);
00416   }
00417   memcpy(list.bptr,p,nsize);
00418   list.bptr+=nsize;
00419 }
00420 
00425 void memcpy(void * p,const fixed_smartlist2 & _list, const size_t nsize)
00426 {
00427   ADUNCONST(fixed_smartlist2,list)
00428   if ( list.bptr+nsize-1 > list.buffend)
00429   {
00430     cerr << " Trying to write outside list buffer" << endl;
00431     exit(1);
00432   }
00433   memcpy(p,list.bptr,nsize);
00434   list.bptr+=nsize;
00435 }
00436 
00441 void fixed_smartlist2::operator -= (int n)
00442 {
00443   if (bptr-n<buffer)
00444   {
00445     if (bptr != buffer)
00446     {
00447       cerr << " Sanity error in fixed_smartlist2::operator -= (int)" << endl;
00448       exit(1);
00449     }
00450     else
00451     {
00452       // get previous record from the file
00453       read_buffer();
00454       bptr=recend-n+1;
00455     }
00456   }
00457   else
00458   {
00459     bptr-=n;
00460   }
00461 }
00462 
00467 void fixed_smartlist2::operator -- (void)
00468 {
00469   if (bptr-1<buffer)
00470   {
00471     if (bptr != buffer)
00472     {
00473       cerr << " Sanity error in fixed_smartlist2::operator -= (int)" << endl;
00474       exit(1);
00475     }
00476     else
00477     {
00478       // get previous record from the file
00479       read_buffer();
00480       //bptr=recend+1;
00481       bptr=recend;
00482     }
00483   }
00484   else
00485   {
00486     bptr--;
00487   }
00488 }
00489 
00494 void fixed_smartlist2::operator += (int nsize)
00495 {
00496   if ( bptr+nsize-1 > buffend)
00497   {
00498     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00499     {
00500       read_buffer();
00501     }
00502     else
00503     {
00504       if ((unsigned int)nsize>bufsize)
00505       {
00506          cout << "Need to increase buffsize in list" << endl;
00507          exit(1);
00508       }
00509       write_buffer();
00510     }
00511   }
00512   else
00513   {
00514     bptr+=nsize;
00515   }
00516 }
00517 
00522 void fixed_smartlist2::operator ++ (void)
00523 {
00524   if ( bptr==buffend)
00525   {
00526     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00527     {
00528       read_buffer();
00529     }
00530     else
00531     {
00532       write_buffer();
00533     }
00534   }
00535   else
00536   {
00537     bptr++;
00538   }
00539 }
00540 
00544 void fixed_smartlist2::read_file(void)
00545 {
00546   //rewind the file
00547   off_t pos=lseek(fp,0L,SEEK_SET);
00548   char buffer[50000];
00549   int offset=0;
00550   fixed_list_entry * b= (fixed_list_entry*) &(buffer[0]);
00551   cout << b << endl;
00552   ssize_t nw = 0;
00553   do
00554   {
00555     int nbytes = 0;
00556     nw = ::read(fp,&nbytes,sizeof(int));
00557     if (nw != -1)
00558     {
00559       nw = ::read(fp, buffer + offset, (size_t)nbytes);
00560       if (nw != -1)
00561       {
00562         offset+=nbytes;
00563         nw = ::read(fp,&pos,sizeof(off_t));
00564       }
00565     }
00566   }
00567   while(nw);
00568 }