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