ADMB Documentation  11.2.2828
 All Classes Files Functions Variables Typedefs Friends Defines
df1b2f14.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: df1b2f14.cpp 2811 2014-12-17 21:48:01Z johnoel $
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 == -1)
00080   {
00081     cerr << "Error trying to open file " << filename
00082          << " in class fixed_smartlist2 " << endl;
00083     ad_exit(1);
00084   }
00085 
00086   /*off_t pos=*/lseek(fp,0L,SEEK_CUR);
00087 }
00088 
00092 void fixed_smartlist2::write(const size_t n)
00093 {
00094 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00095   assert(n <= INT_MAX);
00096   ssize_t nw = ::write(fp, buffer, (int)n);
00097 #else
00098   ssize_t nw = ::write(fp, buffer, n);
00099 #endif
00100   if (nw <= -1 || (size_t)nw != n)
00101   {
00102     cerr << "Error writing to file " << filename << endl;
00103     ad_exit(1);
00104   }
00105 }
00106 
00110 void fixed_smartlist2::rewind(void)
00111 {
00112   bptr=buffer;
00113   eof_flag=0;
00114   if (written_flag)
00115   {
00116     lseek(fp,0L,SEEK_SET);
00117     // get the record size
00118     unsigned int nbytes = 0;
00119     ssize_t ret = ::read(fp,&nbytes,sizeof(unsigned int));
00120     assert(ret != -1);
00121     if (nbytes > bufsize)
00122     {
00123       cerr << "Error -- record size in file seems to be larger than"
00124        " the buffer it was created from " << endl
00125         << " buffer size is " << bufsize << " record size is supposedly "
00126         << nbytes << endl;
00127       ad_exit(1);
00128     }
00129     // now read the record into the buffer
00130     ret = ::read(fp,buffer,nbytes);
00131     assert(ret != -1);
00132     //cout << "Number of bytes read " << nr << endl;
00133     // skip over file postion entry in file
00134     // so we are ready to read second record
00135     lseek(fp,(off_t)sizeof(off_t),SEEK_CUR);
00136   }
00137 }
00138 
00143 void fixed_smartlist2::initialize(void)
00144 {
00145   end_saved=0;
00146   eof_flag=0;
00147   bptr=buffer;
00148   //int nbytes=0;
00149   written_flag=0;
00150   lseek(fp,0L,SEEK_SET);
00151   set_forward();
00152 }
00153 
00158 void fixed_smartlist2::check_buffer_size(const size_t nsize)
00159 {
00160   if ( bptr+nsize-1 > buffend)
00161   {
00162     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00163     {
00164       read_buffer();
00165     }
00166     else
00167     {
00168       if (nsize>bufsize)
00169       {
00170          cout << "Need to increase buffsize in list" << endl;
00171          exit(1);
00172       }
00173       write_buffer();
00174     }
00175   }
00176 }
00177 
00182 void fixed_smartlist2::restore_end(void)
00183 {
00184   if (written_flag)
00185   {
00186     if (end_saved)
00187     {
00188       /*off_t ipos=*/lseek(fp,endof_file_ptr,SEEK_SET);
00189       read_buffer();
00190       set_recend();
00191     }
00192   }
00193 }
00194 
00199 void fixed_smartlist2::save_end(void)
00200 {
00201   if (written_flag)
00202   {
00203     if (!end_saved)
00204     {
00205       write_buffer_one_less();
00206       end_saved=1;
00207     }
00208   }
00209 }
00210 
00215 void fixed_smartlist2::write_buffer_one_less(void)
00216 {
00217   int _nbytes=adptr_diff(bptr,buffer);
00218   if (_nbytes > 0)
00219   {
00220     unsigned int nbytes = (unsigned int)_nbytes;
00221 
00222     written_flag=1;
00223     // get the current file position
00224     off_t pos=lseek(fp,0L,SEEK_CUR);
00225 
00226     // write the size of the next record into the file
00227     ssize_t ret = ::write(fp,&nbytes,sizeof(unsigned int));
00228     assert(ret != -1);
00229 
00230     // write the record into the file
00231     ssize_t nw = ::write(fp,buffer,nbytes);
00232     if (nw < _nbytes)
00233     {
00234       cerr << "Error writing to file " << filename << endl;
00235       ad_exit(1);
00236     }
00237     // reset the pointer to the beginning of the buffer
00238     bptr=buffer;
00239 
00240     // now write the previous file position into the file so we can back up
00241     // when we want to.
00242     ret = ::write(fp,&pos,sizeof(off_t));
00243     assert(ret != -1);
00244 
00245     endof_file_ptr=lseek(fp,0L,SEEK_CUR);
00246 
00247     //cout << lseek(fp,0L,SEEK_CUR) << endl;
00248   }
00249 }
00250 
00255 void fixed_smartlist2::write_buffer(void)
00256 {
00257   int _nbytes=adptr_diff(bptr+1,buffer);
00258   if (_nbytes > 0)
00259   {
00260     unsigned int nbytes = (unsigned int)_nbytes;
00261 
00262     written_flag=1;
00263     // get the current file position
00264     off_t pos=lseek(fp,0L,SEEK_CUR);
00265 
00266     // write the size of the next record into the file
00267     ssize_t ret = ::write(fp, &nbytes, sizeof(unsigned int));
00268     assert(ret != -1);
00269 
00270     // write the record into the file
00271     ret = ::write(fp,buffer,nbytes);
00272     assert(ret != -1);
00273     if (ret < _nbytes)
00274     {
00275       cerr << "Error writing to file " << filename << endl;
00276       ad_exit(1);
00277     }
00278     // reset the pointer to the beginning of the buffer
00279     bptr=buffer;
00280 
00281     // now write the previous file position into the file so we can back up
00282     // when we want to.
00283     ret = ::write(fp,&pos,sizeof(off_t));
00284     assert(ret != -1);
00285 
00286     endof_file_ptr=lseek(fp,0L,SEEK_CUR);
00287 
00288     //cout << lseek(fp,0L,SEEK_CUR) << endl;
00289   }
00290 }
00291 
00296 void fixed_smartlist2::read_buffer(void)
00297 {
00298   if (!written_flag)
00299   {
00300     if (direction ==-1)
00301       eof_flag=-1;
00302     else
00303       eof_flag=1;
00304   }
00305   else
00306   {
00307     off_t pos = 0;
00308     if (direction ==-1) // we are going backwards
00309     {
00310       off_t ipos=lseek(fp,0L,SEEK_CUR);
00311       if (ipos ==0)
00312       {
00313         eof_flag=-1;
00314         return;
00315       }
00316       // offset of the begining of the record is at the end
00317       // of the record
00318       lseek(fp,-((off_t)sizeof(off_t)),SEEK_CUR);
00319       ssize_t ret = read(fp,&pos,sizeof(off_t));
00320       assert(ret != -1);
00321       // back up to the beginning of the record (plus record size)
00322       lseek(fp,pos,SEEK_SET);
00323       //*(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00324     }
00325     // get the record size
00326     int _nbytes = 0;
00327     ssize_t ret = ::read(fp,&_nbytes,sizeof(int));
00328     assert(ret != -1);
00329     if (_nbytes > 0)
00330     {
00331       const size_t nbytes = (size_t)_nbytes;
00332       if (nbytes > bufsize)
00333       {
00334         cerr << "Error -- record size in file seems to be larger than"
00335          " the buffer it was created from " << endl
00336           << " buffer size is " << bufsize << " record size is supposedly "
00337           << nbytes << endl;
00338         ad_exit(1);
00339       }
00340       // now read the record into the buffer
00341 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00342       ssize_t nr = ::read(fp,buffer,_nbytes);
00343 #else
00344       ssize_t nr = ::read(fp,buffer,nbytes);
00345 #endif
00346       assert(nr != -1);
00347       if (nr != _nbytes)
00348       {
00349         cerr << "Error: read only " << nr << " of " << nbytes << "bytes.\n";
00350         exit(1);
00351       }
00352       // reset the pointer to the beginning of the buffer
00353       bptr=buffer;
00354       size_t ns = nbytes / sizeof(int);
00355       recend=bptr+ns-1;
00356       //cout << "Number of bytes read " << nr
00357        //    << "  recend value = " << recend << endl;
00358       if (direction ==-1) // we are going backwards
00359       {
00360         // backup the file pointer again
00361         lseek(fp,pos,SEEK_SET);
00362         // *(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00363       }
00364       else  // we are going forward
00365       {
00366         //\todo need test
00367         // skip over file postion entry in file
00368         lseek(fp,(off_t)sizeof(off_t),SEEK_CUR);
00369       }
00370     }
00371   }
00372 }
00373 
00378 void memcpy(const fixed_smartlist2 & _list,void * p, const size_t nsize)
00379 {
00380   ADUNCONST(fixed_smartlist2,list)
00381   if ( list.bptr+nsize-1 > list.buffend)
00382   {
00383     cerr << " Trying to write outside list buffer" << endl;
00384     exit(1);
00385   }
00386   memcpy(list.bptr,p,nsize);
00387   list.bptr+=nsize;
00388 }
00389 
00394 void memcpy(void * p,const fixed_smartlist2 & _list, const size_t nsize)
00395 {
00396   ADUNCONST(fixed_smartlist2,list)
00397   if ( list.bptr+nsize-1 > list.buffend)
00398   {
00399     cerr << " Trying to write outside list buffer" << endl;
00400     exit(1);
00401   }
00402   memcpy(p,list.bptr,nsize);
00403   list.bptr+=nsize;
00404 }
00405 
00410 void fixed_smartlist2::operator -= (int n)
00411 {
00412   if (bptr-n<buffer)
00413   {
00414     if (bptr != buffer)
00415     {
00416       cerr << " Sanity error in fixed_smartlist2::operator -= (int)" << endl;
00417       exit(1);
00418     }
00419     else
00420     {
00421       // get previous record from the file
00422       read_buffer();
00423       bptr=recend-n+1;
00424     }
00425   }
00426   else
00427   {
00428     bptr-=n;
00429   }
00430 }
00431 
00436 void fixed_smartlist2::operator -- (void)
00437 {
00438   if (bptr-1<buffer)
00439   {
00440     if (bptr != buffer)
00441     {
00442       cerr << " Sanity error in fixed_smartlist2::operator -= (int)" << endl;
00443       exit(1);
00444     }
00445     else
00446     {
00447       // get previous record from the file
00448       read_buffer();
00449       //bptr=recend+1;
00450       bptr=recend;
00451     }
00452   }
00453   else
00454   {
00455     bptr--;
00456   }
00457 }
00458 
00463 void fixed_smartlist2::operator += (int nsize)
00464 {
00465   if ( bptr+nsize-1 > buffend)
00466   {
00467     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00468     {
00469       read_buffer();
00470     }
00471     else
00472     {
00473       if ((unsigned int)nsize>bufsize)
00474       {
00475          cout << "Need to increase buffsize in list" << endl;
00476          exit(1);
00477       }
00478       write_buffer();
00479     }
00480   }
00481   else
00482   {
00483     bptr+=nsize;
00484   }
00485 }
00486 
00491 void fixed_smartlist2::operator ++ (void)
00492 {
00493   if ( bptr==buffend)
00494   {
00495     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00496     {
00497       read_buffer();
00498     }
00499     else
00500     {
00501       write_buffer();
00502     }
00503   }
00504   else
00505   {
00506     bptr++;
00507   }
00508 }
00509 
00513 void fixed_smartlist2::read_file(void)
00514 {
00515   //rewind the file
00516   off_t pos=lseek(fp,0L,SEEK_SET);
00517   char buffer[50000];
00518   int offset=0;
00519   fixed_list_entry * b= (fixed_list_entry*) &(buffer[0]);
00520   cout << b << endl;
00521   ssize_t nw = 0;
00522   do
00523   {
00524     int nbytes = 0;
00525     nw = ::read(fp,&nbytes,sizeof(int));
00526     if (nw != -1)
00527     {
00528       nw = ::read(fp, buffer + offset, (size_t)nbytes);
00529       if (nw != -1)
00530       {
00531         offset+=nbytes;
00532         nw = ::read(fp,&pos,sizeof(off_t));
00533       }
00534     }
00535   }
00536   while(nw);
00537 }