ADMB Documentation  11.4.2890
 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 {
00029   nentries=0;
00030   end_saved=0;
00031   eof_flag=0;
00032   noreadflag=0;
00033   written_flag=0;
00034   direction=0;
00035   bufsize=0;
00036   true_buffer=0;
00037   true_buffend=0;
00038   buffer=0;
00039   buffend=0;
00040   bptr=buffer;
00041 }
00042 
00047 fixed_smartlist2::fixed_smartlist2(const size_t _bufsize,
00048   const adstring& _filename)
00049 {
00050   allocate(_bufsize,_filename);
00051 }
00052 
00057 void fixed_smartlist2::allocate(const size_t _bufsize,
00058   const adstring& _filename)
00059 {
00060   nentries=_bufsize/sizeof(int);
00061   end_saved=0;
00062   eof_flag=0;
00063   noreadflag=0;
00064   written_flag=0;
00065   direction=0;
00066   bufsize=_bufsize;
00067   filename=_filename;
00068   AD_ALLOCATE(true_buffer,int,nentries+2,df1b2_gradlist)
00069   true_buffend=true_buffer+nentries+1;
00070   buffer=true_buffer+1;
00071   buffend=true_buffend-1;
00072   bptr=buffer;
00073   fp=open((char*)(filename), O_RDWR | O_CREAT | O_TRUNC |
00074                    O_BINARY, S_IREAD | S_IWRITE);
00075   if (fp == -1)
00076   {
00077     cerr << "Error trying to open file " << filename
00078          << " in class fixed_smartlist2 " << endl;
00079     ad_exit(1);
00080   }
00081 
00082   /*off_t pos=*/lseek(fp,0L,SEEK_CUR);
00083 }
00084 
00088 void fixed_smartlist2::write(const size_t n)
00089 {
00090 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00091   assert(n <= INT_MAX);
00092   ssize_t nw = ::write(fp, buffer, (int)n);
00093 #else
00094   ssize_t nw = ::write(fp, buffer, n);
00095 #endif
00096   if (nw <= -1 || (size_t)nw != n)
00097   {
00098     cerr << "Error writing to file " << filename << endl;
00099     ad_exit(1);
00100   }
00101 }
00102 
00106 void fixed_smartlist2::rewind(void)
00107 {
00108   bptr=buffer;
00109   eof_flag=0;
00110   if (written_flag)
00111   {
00112     lseek(fp,0L,SEEK_SET);
00113     // get the record size
00114     unsigned int nbytes = 0;
00115     ssize_t ret = ::read(fp,&nbytes,sizeof(unsigned int));
00116     assert(ret != -1);
00117     if (nbytes > bufsize)
00118     {
00119       cerr << "Error -- record size in file seems to be larger than"
00120        " the buffer it was created from " << endl
00121         << " buffer size is " << bufsize << " record size is supposedly "
00122         << nbytes << endl;
00123       ad_exit(1);
00124     }
00125     // now read the record into the buffer
00126     ret = ::read(fp,buffer,nbytes);
00127     assert(ret != -1);
00128     //cout << "Number of bytes read " << nr << endl;
00129     // skip over file postion entry in file
00130     // so we are ready to read second record
00131     lseek(fp,(off_t)sizeof(off_t),SEEK_CUR);
00132   }
00133 }
00134 
00139 void fixed_smartlist2::initialize(void)
00140 {
00141   end_saved=0;
00142   eof_flag=0;
00143   bptr=buffer;
00144   //int nbytes=0;
00145   written_flag=0;
00146   lseek(fp,0L,SEEK_SET);
00147   set_forward();
00148 }
00149 
00154 void fixed_smartlist2::check_buffer_size(const size_t nsize)
00155 {
00156   if ( bptr+nsize-1 > buffend)
00157   {
00158     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00159     {
00160       read_buffer();
00161     }
00162     else
00163     {
00164       if (nsize>bufsize)
00165       {
00166          cout << "Need to increase buffsize in list" << endl;
00167          exit(1);
00168       }
00169       write_buffer();
00170     }
00171   }
00172 }
00173 
00178 void fixed_smartlist2::restore_end(void)
00179 {
00180   if (written_flag)
00181   {
00182     if (end_saved)
00183     {
00184       /*off_t ipos=*/lseek(fp,endof_file_ptr,SEEK_SET);
00185       read_buffer();
00186       set_recend();
00187     }
00188   }
00189 }
00190 
00195 void fixed_smartlist2::save_end(void)
00196 {
00197   if (written_flag)
00198   {
00199     if (!end_saved)
00200     {
00201       write_buffer_one_less();
00202       end_saved=1;
00203     }
00204   }
00205 }
00206 
00211 void fixed_smartlist2::write_buffer_one_less(void)
00212 {
00213   int _nbytes=adptr_diff(bptr,buffer);
00214   if (_nbytes > 0)
00215   {
00216     unsigned int nbytes = (unsigned int)_nbytes;
00217 
00218     written_flag=1;
00219     // get the current file position
00220     off_t pos=lseek(fp,0L,SEEK_CUR);
00221 
00222     // write the size of the next record into the file
00223     ssize_t ret = ::write(fp,&nbytes,sizeof(unsigned int));
00224     assert(ret != -1);
00225 
00226     // write the record into the file
00227     ssize_t nw = ::write(fp,buffer,nbytes);
00228     if (nw < _nbytes)
00229     {
00230       cerr << "Error writing to file " << filename << endl;
00231       ad_exit(1);
00232     }
00233     // reset the pointer to the beginning of the buffer
00234     bptr=buffer;
00235 
00236     // now write the previous file position into the file so we can back up
00237     // when we want to.
00238     ret = ::write(fp,&pos,sizeof(off_t));
00239     assert(ret != -1);
00240 
00241     endof_file_ptr=lseek(fp,0L,SEEK_CUR);
00242 
00243     //cout << lseek(fp,0L,SEEK_CUR) << endl;
00244   }
00245 }
00246 
00251 void fixed_smartlist2::write_buffer(void)
00252 {
00253   int _nbytes=adptr_diff(bptr+1,buffer);
00254   if (_nbytes > 0)
00255   {
00256     unsigned int nbytes = (unsigned int)_nbytes;
00257 
00258     written_flag=1;
00259     // get the current file position
00260     off_t pos=lseek(fp,0L,SEEK_CUR);
00261 
00262     // write the size of the next record into the file
00263     ssize_t ret = ::write(fp, &nbytes, sizeof(unsigned int));
00264     assert(ret != -1);
00265 
00266     // write the record into the file
00267     ret = ::write(fp,buffer,nbytes);
00268     assert(ret != -1);
00269     if (ret < _nbytes)
00270     {
00271       cerr << "Error writing to file " << filename << endl;
00272       ad_exit(1);
00273     }
00274     // reset the pointer to the beginning of the buffer
00275     bptr=buffer;
00276 
00277     // now write the previous file position into the file so we can back up
00278     // when we want to.
00279     ret = ::write(fp,&pos,sizeof(off_t));
00280     assert(ret != -1);
00281 
00282     endof_file_ptr=lseek(fp,0L,SEEK_CUR);
00283 
00284     //cout << lseek(fp,0L,SEEK_CUR) << endl;
00285   }
00286 }
00287 
00292 void fixed_smartlist2::read_buffer(void)
00293 {
00294   if (!written_flag)
00295   {
00296     if (direction ==-1)
00297       eof_flag=-1;
00298     else
00299       eof_flag=1;
00300   }
00301   else
00302   {
00303     off_t pos = 0;
00304     if (direction ==-1) // we are going backwards
00305     {
00306       off_t ipos=lseek(fp,0L,SEEK_CUR);
00307       if (ipos ==0)
00308       {
00309         eof_flag=-1;
00310         return;
00311       }
00312       // offset of the begining of the record is at the end
00313       // of the record
00314       lseek(fp,-((off_t)sizeof(off_t)),SEEK_CUR);
00315       ssize_t ret = read(fp,&pos,sizeof(off_t));
00316       assert(ret != -1);
00317       // back up to the beginning of the record (plus record size)
00318       lseek(fp,pos,SEEK_SET);
00319       //*(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00320     }
00321     // get the record size
00322     int _nbytes = 0;
00323     ssize_t ret = ::read(fp,&_nbytes,sizeof(int));
00324     assert(ret != -1);
00325     if (_nbytes > 0)
00326     {
00327       const size_t nbytes = (size_t)_nbytes;
00328       if (nbytes > bufsize)
00329       {
00330         cerr << "Error -- record size in file seems to be larger than"
00331          " the buffer it was created from " << endl
00332           << " buffer size is " << bufsize << " record size is supposedly "
00333           << nbytes << endl;
00334         ad_exit(1);
00335       }
00336       // now read the record into the buffer
00337 #if defined(__MINGW64__) || (defined(_WIN64) && defined(_MSC_VER))
00338       ssize_t nr = ::read(fp,buffer,_nbytes);
00339 #else
00340       ssize_t nr = ::read(fp,buffer,nbytes);
00341 #endif
00342       assert(nr != -1);
00343       if (nr != _nbytes)
00344       {
00345         cerr << "Error: read only " << nr << " of " << nbytes << "bytes.\n";
00346         exit(1);
00347       }
00348       // reset the pointer to the beginning of the buffer
00349       bptr=buffer;
00350       size_t ns = nbytes / sizeof(int);
00351       recend=bptr+ns-1;
00352       //cout << "Number of bytes read " << nr
00353        //    << "  recend value = " << recend << endl;
00354       if (direction ==-1) // we are going backwards
00355       {
00356         // backup the file pointer again
00357         lseek(fp,pos,SEEK_SET);
00358         // *(off_t*)(bptr)=lseek(fp,pos,SEEK_SET);
00359       }
00360       else  // we are going forward
00361       {
00362         //\todo need test
00363         // skip over file postion entry in file
00364         lseek(fp,(off_t)sizeof(off_t),SEEK_CUR);
00365       }
00366     }
00367   }
00368 }
00369 
00374 void memcpy(const fixed_smartlist2 & _list,void * p, const size_t nsize)
00375 {
00376   ADUNCONST(fixed_smartlist2,list)
00377   if ( list.bptr+nsize-1 > list.buffend)
00378   {
00379     cerr << " Trying to write outside list buffer" << endl;
00380     exit(1);
00381   }
00382   memcpy(list.bptr,p,nsize);
00383   list.bptr+=nsize;
00384 }
00385 
00390 void memcpy(void * p,const fixed_smartlist2 & _list, const size_t nsize)
00391 {
00392   ADUNCONST(fixed_smartlist2,list)
00393   if ( list.bptr+nsize-1 > list.buffend)
00394   {
00395     cerr << " Trying to write outside list buffer" << endl;
00396     exit(1);
00397   }
00398   memcpy(p,list.bptr,nsize);
00399   list.bptr+=nsize;
00400 }
00401 
00406 void fixed_smartlist2::operator -= (int n)
00407 {
00408   if (bptr-n<buffer)
00409   {
00410     if (bptr != buffer)
00411     {
00412       cerr << " Sanity error in fixed_smartlist2::operator -= (int)" << endl;
00413       exit(1);
00414     }
00415     else
00416     {
00417       // get previous record from the file
00418       read_buffer();
00419       bptr=recend-n+1;
00420     }
00421   }
00422   else
00423   {
00424     bptr-=n;
00425   }
00426 }
00427 
00432 void fixed_smartlist2::operator -- (void)
00433 {
00434   if (bptr-1<buffer)
00435   {
00436     if (bptr != buffer)
00437     {
00438       cerr << " Sanity error in fixed_smartlist2::operator -= (int)" << endl;
00439       exit(1);
00440     }
00441     else
00442     {
00443       // get previous record from the file
00444       read_buffer();
00445       //bptr=recend+1;
00446       bptr=recend;
00447     }
00448   }
00449   else
00450   {
00451     bptr--;
00452   }
00453 }
00454 
00459 void fixed_smartlist2::operator += (int nsize)
00460 {
00461   if ( bptr+nsize-1 > buffend)
00462   {
00463     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00464     {
00465       read_buffer();
00466     }
00467     else
00468     {
00469       if ((unsigned int)nsize>bufsize)
00470       {
00471          cout << "Need to increase buffsize in list" << endl;
00472          exit(1);
00473       }
00474       write_buffer();
00475     }
00476   }
00477   else
00478   {
00479     bptr+=nsize;
00480   }
00481 }
00482 
00487 void fixed_smartlist2::operator ++ (void)
00488 {
00489   if ( bptr==buffend)
00490   {
00491     if (df1b2variable::get_passnumber()==2 && !noreadflag )
00492     {
00493       read_buffer();
00494     }
00495     else
00496     {
00497       write_buffer();
00498     }
00499   }
00500   else
00501   {
00502     bptr++;
00503   }
00504 }
00505 
00509 void fixed_smartlist2::read_file(void)
00510 {
00511   //rewind the file
00512   off_t pos=lseek(fp,0L,SEEK_SET);
00513   char buffer[50000];
00514   int offset=0;
00515   fixed_list_entry * b= (fixed_list_entry*) &(buffer[0]);
00516   cout << b << endl;
00517   ssize_t nw = 0;
00518   do
00519   {
00520     int nbytes = 0;
00521     nw = ::read(fp,&nbytes,sizeof(int));
00522     if (nw != -1)
00523     {
00524       nw = ::read(fp, buffer + offset, (size_t)nbytes);
00525       if (nw != -1)
00526       {
00527         offset+=nbytes;
00528         nw = ::read(fp,&pos,sizeof(off_t));
00529       }
00530     }
00531   }
00532   while(nw);
00533 }