/data3/calcul/jacquem/working_dir/Micromegas/micromegasFrameWork/lcio/sio/src/SIO_stream.cc

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------------
00002 // CVS $Id: SIO_stream.cc,v 1.9 2010/06/22 13:49:54 gaede Exp $
00003 // ----------------------------------------------------------------------------
00004 // => Controller for a single SIO stream.                          
00005 // ----------------------------------------------------------------------------
00006 //
00007 // General Description:
00008 //
00009 // SIO_stream manages operations of a single SIO stream.
00010 //
00011 // ----------------------------------------------------------------------------
00012 
00013 #ifdef _MSC_VER
00014 #   pragma warning(disable:4786)        // >255 characters in debug information
00015 #endif
00016 
00017 #include <iostream>
00018 #include <cstdlib>
00019 #include <cstring>
00020 
00021 #include "zlib.h"
00022 
00023 #include "SIO_block.h"
00024 #include "SIO_definitions.h"
00025 #include "SIO_functions.h"
00026 #include "SIO_record.h"
00027 #include "SIO_recordManager.h"
00028 #include "SIO_stream.h"
00029 
00030 
00031 
00032 static unsigned int
00033     SIO_align       = 0x00000003,
00034     SIO_mark_record = 0xabadcafe;
00035 
00036 // ----------------------------------------------------------------------------
00037 // Constructor (private function!)   
00038 // ----------------------------------------------------------------------------
00039 SIO_stream::SIO_stream
00040 (
00041     const char*      i_name,
00042     unsigned int     i_reserve,
00043     SIO_verbosity    i_verbosity
00044 )
00045 {
00046 
00047 bufloc    = NULL;
00048 buffer    = NULL;
00049 bufmax    = NULL;
00050 recmax    = NULL;
00051 blkmax    = NULL;
00052 
00053 cmploc    = NULL;
00054 cmpmax    = NULL;
00055 z_strm    = NULL;
00056 
00057 name      = i_name;
00058 handle    = NULL;
00059 
00060 mode      = SIO_MODE_UNDEFINED;
00061 reserve   = i_reserve;
00062 state     = SIO_STATE_CLOSED;
00063 verbosity = i_verbosity;
00064 
00065 compLevel = Z_DEFAULT_COMPRESSION ;
00066 }
00067 
00068 // ----------------------------------------------------------------------------
00069 // Destructor (private function!)
00070 // ----------------------------------------------------------------------------
00071 SIO_stream::~SIO_stream()
00072 {
00073 
00074 //
00075 // Always try to close the stream.
00076 //
00077 if( state != SIO_STATE_CLOSED )
00078     close();
00079 
00080 //
00081 // That's all folks!
00082 //
00083 return;
00084 }
00085 
00086 // ----------------------------------------------------------------------------
00087 // Flush the stream.
00088 // ----------------------------------------------------------------------------
00089 unsigned int SIO_stream::flush()
00090 {
00091 //
00092 // Can't close what ain't open!
00093 //
00094 if( state == SIO_STATE_CLOSED )
00095 {
00096     if( verbosity >= SIO_ERRORS )
00097     {
00098         std::cout << "SIO: ["  << name << "//] "
00099                   << "Not open"
00100                   << std::endl;
00101     }
00102     return( SIO_STREAM_NOTOPEN );
00103 }
00104 int rc = FFLUSH( handle );
00105 return (rc == 0) ? SIO_STREAM_SUCCESS : SIO_STREAM_BADWRITE;
00106 }
00107 
00108 // ----------------------------------------------------------------------------
00109 // Close the stream.
00110 // ----------------------------------------------------------------------------
00111 unsigned int SIO_stream::close()
00112 {
00113 
00114 //
00115 // Local variables.
00116 //
00117 int
00118     z_stat;
00119 
00120 unsigned int
00121     status;
00122 
00123 //
00124 // Can't close what ain't open!
00125 //
00126 if( state == SIO_STATE_CLOSED )
00127 {
00128     if( verbosity >= SIO_ERRORS )
00129     {
00130         std::cout << "SIO: ["  << name << "//] "
00131                   << "Not open"
00132                   << std::endl;
00133     }
00134     return( SIO_STREAM_NOTOPEN );
00135 }
00136 
00137 //
00138 // Assume all will go well.
00139 //
00140 status = SIO_STREAM_SUCCESS;
00141 
00142 //
00143 // Dispose of the pointer relocation tables.
00144 //
00145 delete pointedAt;
00146 delete pointerTo;
00147 
00148 //
00149 // Dispose of compression control structure.
00150 //
00151 if( z_strm != NULL )
00152 {
00153     z_stat = (mode == SIO_MODE_READ) ? inflateEnd( z_strm )
00154                                      : deflateEnd( z_strm );
00155 
00156     if( z_stat != Z_OK )
00157     {
00158         status = SIO_STREAM_BADCOMPRESS;
00159         if( verbosity >= SIO_ERRORS )
00160         {
00161             std::cout << "SIO: ["  << name << "//] "
00162                       << "ZLIB error number " << z_stat
00163                       << std::endl;
00164 
00165             std::cout << "SIO: ["  << name << "//] "
00166                       << "Compression de-initialization failed"
00167                       << std::endl;
00168         }
00169     }
00170     free( z_strm );
00171     z_strm = NULL;
00172 }
00173     
00174 //
00175 // Dispose of any compression/decompression buffer.
00176 //
00177 if( cmploc != NULL )
00178 {
00179     free( cmploc );
00180     cmploc = NULL;
00181     cmpmax = NULL;
00182 }
00183 
00184 //
00185 // Dispose of any associated raw data buffer.
00186 //
00187 if( bufloc != NULL )
00188 {
00189     free( bufloc );
00190     bufloc = NULL;
00191     buffer = NULL;
00192     bufmax = NULL;
00193     recmax = NULL;
00194     blkmax = NULL;
00195 }
00196 
00197 //
00198 // Close the stream and destroy associated information.
00199 //
00200 if( FCLOSE( handle ) == EOF )
00201 {
00202     status = SIO_STREAM_GOTEOF;
00203     if( verbosity >= SIO_ERRORS )
00204     {
00205         std::cout << "SIO: ["  << name << "//] "
00206                   << "EOF on close" 
00207                   << std::endl;
00208     }
00209 }
00210 else
00211 {
00212 }
00213 filename.erase( filename.begin(), filename.end() );
00214 handle = NULL;
00215 
00216 //
00217 // Miscellany.
00218 //
00219 mode   = SIO_MODE_UNDEFINED;
00220 state  = SIO_STATE_CLOSED;
00221 
00222 //
00223 // Summarize.
00224 //
00225 if( status == SIO_STREAM_SUCCESS )
00226 {
00227     if( verbosity >= SIO_ALL )
00228     {
00229         std::cout << "SIO: ["  << name << "//] "
00230                   << "Closed"
00231                   << std::endl;
00232     }
00233 }
00234 
00235 //
00236 // That's all folks!
00237 //
00238 return( status );
00239 }
00240 
00241 // ----------------------------------------------------------------------------
00242 // Dump the buffer.  
00243 // ----------------------------------------------------------------------------
00244 void SIO_stream::dump
00245 (
00246     unsigned int    offset,
00247     unsigned int    length
00248 )
00249 {
00250 
00251 //
00252 // Local variables.
00253 //
00254 unsigned int
00255     count;
00256 
00257 char
00258    *ascpnt,
00259    *hexpnt,
00260     outbuf[77];
00261 
00262 unsigned char
00263    *dmpbeg,
00264    *dmpend;
00265 
00266 static char
00267     hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
00268                 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
00269 
00270 //
00271 // Header.
00272 //
00273 printf( "\nDump buffer of stream %s\n\n", name.c_str() );
00274 
00275 if( buffer == NULL )
00276 {
00277     printf( "No buffer associated with stream %s\n", name.c_str() );
00278     return;
00279 }
00280 
00281 //
00282 // Offset must be in bounds.
00283 //
00284 dmpbeg = bufloc + offset;
00285 if( dmpbeg >= bufmax )
00286 {
00287     printf( "Offset beyond end of buffer\n");
00288     return;
00289 }
00290 
00291 //
00292 // Length must not run off end of buffer.
00293 //
00294 dmpend = dmpbeg + length;
00295 if( dmpend > bufmax )
00296     dmpend = bufmax;
00297 
00298 //
00299 // Buffer characteristics.
00300 //
00301 printf("   Start address: %8d  (0x%08x)\n", bufloc, bufloc );
00302 count = buffer - bufloc;
00303 printf(" Current address: %8d  (0x%08x)    Offset: %8d  (0x%08x)\n", 
00304         buffer, buffer, count, count );
00305 count = bufmax - bufloc;
00306 printf("     End address: %8d  (0x%08x)    Offset: %8d  (0x%08x)\n",
00307         bufmax, bufmax, count, count );
00308 
00309 //
00310 // Put out a header.
00311 //
00312 printf("\n --Offset:Address-");
00313 printf(  "    -Hex------------------------------");
00314 printf(  "    -ASCII----------\n");
00315 
00316 // dddddddd:xxxxxxxx    xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx    aaaaaaaaaaaaaaaa
00317 //-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456
00318 
00319 //
00320 // Scan down the buffer, printing a dump record every 16 bytes.
00321 //
00322 memset(  &outbuf[ 0], ' ', sizeof( outbuf ) );
00323 sprintf( &outbuf[ 1], "%8d",  offset );
00324 sprintf( &outbuf[10], "%08x", dmpbeg );
00325 outbuf[ 9] = ':';
00326 outbuf[18] = ' ';
00327 outbuf[76] = '\0';
00328 hexpnt     = &outbuf[22];
00329 ascpnt     = &outbuf[60];
00330 count      = 0;
00331 
00332 while( dmpbeg < dmpend )
00333 {
00334 
00335     *hexpnt++ = hex[ ((*dmpbeg >>   4) & 15) ]; 
00336     *hexpnt++ = hex[ ( *dmpbeg         & 15) ];
00337     if( (count & 0x3) == 3 ) hexpnt++;
00338 
00339     if( isprint( *dmpbeg ) ) *ascpnt++ = *dmpbeg;
00340     else                     *ascpnt++ = '.';
00341 
00342     count++;
00343     offset++;
00344     dmpbeg++;
00345 
00346     if( count == 16 )
00347     {
00348         printf( "%s\n", outbuf );
00349 
00350         memset(  &outbuf[ 0], ' ', sizeof( outbuf ) );
00351         sprintf( &outbuf[ 1], "%8d",  offset );
00352         sprintf( &outbuf[10], "%08x", dmpbeg );
00353         outbuf[ 9] = ':';
00354         outbuf[18] = ' ';
00355         outbuf[76] = '\0';
00356         hexpnt     = &outbuf[22];
00357         ascpnt     = &outbuf[60];
00358         count      = 0;
00359     }
00360 }
00361 
00362 if( count != 0 )
00363     printf( "%s\n", outbuf );
00364 
00365 //
00366 // That's all folks!
00367 //
00368 return;
00369 }
00370 
00371 // ----------------------------------------------------------------------------
00372 // Return pointer to stream name.
00373 // ----------------------------------------------------------------------------
00374 std::string* SIO_stream::getName()         { return( &name ); }
00375 
00376 // ----------------------------------------------------------------------------
00377 // Return pointer to filename.
00378 // ----------------------------------------------------------------------------
00379 std::string* SIO_stream::getFilename()     { return( &filename ); }
00380 
00381 // ----------------------------------------------------------------------------
00382 // Return mode.
00383 // ----------------------------------------------------------------------------
00384 SIO_stream_mode SIO_stream::getMode()      { return( mode ); }
00385 
00386 // ----------------------------------------------------------------------------
00387 // Return state.
00388 // ----------------------------------------------------------------------------
00389 SIO_stream_state SIO_stream::getState()    { return( state ); }
00390 
00391 // ----------------------------------------------------------------------------
00392 // Return verbosity.
00393 // ----------------------------------------------------------------------------
00394 SIO_verbosity SIO_stream::getVerbosity()   { return( verbosity ); }
00395 
00396 
00397 // ----------------------------------------------------------------------------
00398 // Set compresision level
00399 // ----------------------------------------------------------------------------
00400 void SIO_stream::setCompressionLevel(int level) { 
00401   
00402   // zlib knows comp levels:  -1/Z_DEFAULT_COMPRESSION, 1-9
00403   if( level < 0 ) 
00404 
00405     compLevel = Z_DEFAULT_COMPRESSION ;
00406 
00407   else if( level > 9 )
00408     
00409     compLevel = 9  ;
00410  
00411   else 
00412 
00413     compLevel = level ;
00414 
00415 }
00416 
00417 
00418 
00419 // ----------------------------------------------------------------------------
00420 // Associate a file name and a mode with this stream and open the file.
00421 // ----------------------------------------------------------------------------
00422 unsigned int SIO_stream::open
00423 (
00424     const char*      i_filename,
00425     SIO_stream_mode  i_mode
00426 )
00427 {
00428 
00429 //
00430 // Local variables.
00431 //
00432 int
00433     z_stat;
00434 
00435 static char
00436   SIO_filemode[4][3] = { "rb", "wb", "ab","r+" };
00437 
00438 //
00439 // Can't open what ain't closed!
00440 //
00441 if( state == SIO_STATE_OPEN || state == SIO_STATE_ERROR )
00442 {
00443     if( verbosity >= SIO_ERRORS )
00444     {
00445         std::cout << "SIO: ["  << name << "//] "
00446                   << "Already open"
00447                   << std::endl;
00448     }
00449     return( SIO_STREAM_ALREADYOPEN );
00450 }
00451 
00452 //
00453 // Can't open in mode undefined.
00454 //
00455  if( i_mode == SIO_MODE_UNDEFINED )
00456    {
00457      if( verbosity >= SIO_ERRORS )
00458        {
00459          std::cout << "SIO: ["  << name << "//] "
00460                    << "Cannot open in mode SIO_MODE_UNDEFINED"
00461                    << std::endl;
00462        }
00463      return( SIO_STREAM_BADMODE );
00464    }
00465  
00466 //
00467 // Open the file.
00468 //
00469 if( (handle = FOPEN( i_filename, SIO_filemode[i_mode] )) == NULL )
00470 {
00471     if( verbosity >= SIO_ERRORS )
00472     {
00473         std::cout << "SIO: ["  << name << "//] "
00474                   << "Cannot open file "
00475                   << i_filename
00476                   << std::endl;
00477     }
00478     return( SIO_STREAM_OPENFAIL );
00479 }
00480 
00481 //
00482 // Open succeeded.  Save the context.
00483 //
00484 filename = i_filename;
00485 mode     = i_mode;
00486 state    = SIO_STATE_OPEN;
00487 
00488 if( verbosity >= SIO_ALL )
00489 {
00490     std::cout << "SIO: ["  << name << "//] "
00491               << "Opened file " 
00492               << i_filename
00493               << std::endl;
00494 }
00495 
00496 //
00497 // Allocate a raw data buffer to go with the stream.
00498 //
00499 buffer = NULL;
00500 bufmax = NULL;
00501 bufloc = static_cast<unsigned char*>(malloc( reserve ));
00502 if( bufloc == NULL )
00503 {
00504     state = SIO_STATE_ERROR;
00505     if( verbosity >= SIO_ERRORS )
00506     {
00507         std::cout << "SIO: ["  << name << "//] "
00508                   << "Buffer allocation failed"
00509                   << std::endl;
00510     }
00511     return( SIO_STREAM_NOALLOC );
00512 }
00513 buffer = bufloc;
00514 bufmax = bufloc + reserve;
00515 
00516 //
00517 // Allocate a compression/decompression buffer and initialize it.
00518 //
00519 cmploc = NULL;
00520 cmpmax = NULL;
00521 cmploc = static_cast<unsigned char*>(malloc( reserve >> 2 ));
00522 if( cmploc == NULL )
00523 {
00524     state = SIO_STATE_ERROR;
00525     if( verbosity >= SIO_ERRORS )
00526     {
00527         std::cout << "SIO: ["  << name << "//] "
00528                   << "Compression buffer allocation failed"
00529                   << std::endl;
00530     }
00531     return( SIO_STREAM_BADCOMPRESS );
00532 }
00533 cmpmax = cmploc + (reserve >> 2);
00534 
00535 //
00536 // Allocate the z_stream structure and initialize it.
00537 //
00538 z_strm = static_cast<z_stream*>( malloc( sizeof( z_stream ) ));
00539 
00540 z_strm->zalloc = Z_NULL;
00541 z_strm->zfree  = Z_NULL;
00542 z_strm->opaque = 0;
00543 
00544 z_stat = (mode == SIO_MODE_READ) ? inflateInit( z_strm )
00545                                  : deflateInit( z_strm, compLevel );
00546 
00547 if( z_stat != Z_OK )
00548 {
00549     state = SIO_STATE_ERROR;
00550     if( verbosity >= SIO_ERRORS )
00551     {
00552         std::cout << "SIO: ["  << name << "//] "
00553                   << "ZLIB error number " << z_stat
00554                   << std::endl;
00555 
00556         std::cout << "SIO: ["  << name << "//] "
00557                   << "Compression initialization failed"
00558                   << std::endl;
00559     }
00560     return( SIO_STREAM_BADCOMPRESS );
00561 }
00562     
00563 //
00564 // Allocate the pointer relocation tables.
00565 //
00566 pointedAt = new pointedAtMap_c;
00567 pointerTo = new pointerToMap_c;
00568 
00569 //
00570 // That's all folks!
00571 //
00572 return( SIO_STREAM_SUCCESS );
00573 }
00574 
00575 
00576 //fg: need ftell for direct access 
00577 SIO_64BITINT SIO_stream::currentPosition() { 
00578 
00579   return  FTELL( handle ) ; 
00580 }
00581 
00582 //
00583 //fg: add method to position the file pointer
00584 //
00585 unsigned int SIO_stream::seek(SIO_64BITINT pos, int whence) {  
00586   
00587   unsigned int status;
00588   
00589   //fg:  also need the seek in 'append' mode ( delete old file record )
00590 //   //
00591 //   // This must be a readable stream!
00592 //   //
00593 //   if( mode != SIO_MODE_READ ) {
00594     
00595 //     //    if( verbosity >= SIO_ERRORS ) {
00596 //     if( true ) {
00597       
00598 //       std::cout << "SIO: ["  << name << "//] "
00599 //              << "Cannot seek (stream is write only)"
00600 //              << std::endl;
00601 //     }
00602 //     return( SIO_STREAM_WRITEONLY );
00603 //   }
00604 
00605   status = FSEEK( handle, pos , whence )  ;
00606   
00607   if( status != 0 ) {
00608     
00609     state = SIO_STATE_ERROR;
00610     
00611     if( verbosity >= SIO_ERRORS ) {
00612       
00613       std::cout << "SIO: ["  << name << "/] "
00614                 << "Failed seeking position" << pos
00615                 << std::endl;
00616     }
00617     return( SIO_STREAM_EOF );
00618   }
00619   
00620 //   //FIXME: debug...
00621 //   std::cout << " SIO_stream::seek( " << pos << ", " << whence << " ) - ftell : " << FTELL( handle ) 
00622 //          << " stream-state: " << state << std::endl ;
00623 
00624   return( SIO_STREAM_SUCCESS );
00625 }
00626 
00627 unsigned int SIO_stream::reset(SIO_64BITINT pos){
00628 
00629   unsigned int status;
00630 
00631   status = seek( pos ) ;
00632 
00633   if( status == SIO_STREAM_SUCCESS ){
00634 
00635     // if we can seek the file  the stream should be fine ...
00636     state = SIO_STATE_OPEN ;
00637   }
00638 
00639   return status ;
00640 }
00641 
00642 
00643 // ----------------------------------------------------------------------------
00644 // Read the next record.
00645 // ----------------------------------------------------------------------------
00646 unsigned int SIO_stream::read
00647 (
00648     SIO_record**    record
00649 )
00650 {
00651 
00652 int
00653     z_stat;
00654 
00655 unsigned int
00656     data_length,
00657     head_length,
00658     name_length,
00659     ucmp_length,
00660     buftyp,
00661     compress,
00662     padlen,
00663     options,
00664     status;
00665 
00666 char
00667    *tmploc;
00668 
00669 bool
00670     requested;
00671 
00672 //
00673 // Initialize the returned record pointer to something nasty.
00674 //
00675 *record = NULL;
00676 
00677  recPos = -1 ;  
00678  SIO_64BITINT  recStart = -1 ;
00679 
00680 //
00681 // The stream must be open!
00682 //
00683 if( state != SIO_STATE_OPEN )
00684 {
00685     if( verbosity >= SIO_ERRORS )
00686     {
00687         std::cout << "SIO: ["  << name << "//] "
00688                   << "Cannot read (stream is not open)"
00689                   << std::endl;
00690     }
00691     return( SIO_STREAM_NOTOPEN );
00692 }
00693 
00694 //
00695 // This must be a readable stream!
00696 //
00697 if( mode != SIO_MODE_READ )
00698 {
00699     if( verbosity >= SIO_ERRORS )
00700     {
00701         std::cout << "SIO: ["  << name << "//] "
00702                   << "Cannot read (stream is write only)"
00703                   << std::endl;
00704     }
00705     return( SIO_STREAM_WRITEONLY );
00706 }
00707 
00708 //
00709 // Loop over records until a requested one turns up.
00710 //
00711 requested = false;
00712 while( requested == false )
00713 {
00714 
00715   recStart = FTELL( handle ) ;
00716 
00717     //
00718     // Initialize the buffer and read the first eight bytes.  A read failure
00719     // at this point is treated as an end-of-file (even if there are a few
00720     // bytes dangling in the file).
00721     //
00722     buffer = bufloc;
00723     status = FREAD( buffer, SIO_LEN_SB, 8, handle );
00724     if( status < 8 )
00725         return( SIO_STREAM_EOF );
00726  
00727     //
00728     // Interpret: 1) The length of the record header.
00729     //            2) The record marker.
00730     //
00731     blkmax = bufloc + 8;
00732     SIO_DATA( this, &head_length,  1 );
00733     SIO_DATA( this, &buftyp,       1 );
00734     if( buftyp != SIO_mark_record )
00735     {
00736         state = SIO_STATE_ERROR;
00737         if( verbosity >= SIO_ERRORS )
00738         {
00739             std::cout << "SIO: ["  << name << "//] "
00740                       << "Expected record marker not found"
00741                       << std::endl;
00742         }
00743         return( SIO_STREAM_NORECMARKER );
00744     }
00745 
00746     //
00747     // Interpret: 3) The options word.
00748     //            4) The length of the record data (compressed).
00749     //            5) The length of the record name (uncompressed).
00750     //            6) The length of the record name.
00751     //            7) The record name.
00752     //
00753     status = FREAD( buffer, SIO_LEN_SB, (head_length - 8), handle );
00754     if( status < (head_length - 8) )
00755     {
00756         if( verbosity >= SIO_ERRORS )
00757         {
00758             std::cout << "SIO: ["  << name << "//] "
00759                       << "Unexpected EOF reading record header"
00760                       << std::endl;
00761         }
00762         return( SIO_STREAM_EOF );
00763     }
00764 
00765     blkmax = bufloc + head_length;
00766     SIO_DATA( this, &options,      1 );
00767     SIO_DATA( this, &data_length,  1 );
00768     SIO_DATA( this, &ucmp_length,  1 );
00769     SIO_DATA( this, &name_length,  1 );
00770 
00771     tmploc = static_cast<char*>(malloc( name_length + 1 ));
00772     if( tmploc == NULL )
00773     {
00774         if( verbosity >= SIO_ERRORS )
00775         {
00776             std::cout << "SIO: ["  << name << "//] "
00777                       << "Buffer allocation failed"
00778                       << std::endl;
00779         }
00780         return( SIO_STREAM_NOALLOC );
00781     }
00782 
00783     SIO_DATA( this, tmploc, name_length );
00784     tmploc[name_length]  = '\0';
00785     *record              = SIO_recordManager::get( tmploc );
00786     rec_name             = tmploc;
00787     free( tmploc );
00788 
00789     if( verbosity >= SIO_ALL )
00790     {
00791         std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
00792                   << "Record header read"
00793                   << std::endl;
00794     }
00795 
00796     //
00797     // Unpack this record?
00798     //
00799     if( *record == NULL )
00800     {
00801         if( verbosity >= SIO_ALL )
00802         {
00803             std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
00804                       << "Ignored (name not recognized)"
00805                       << std::endl;
00806         }
00807     }
00808 
00809     else if( !(*record)->getUnpack() )
00810     {
00811         if( verbosity >= SIO_ALL )
00812         {
00813             std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
00814                       << "Ignored (unpacking not requested)"
00815                       << std::endl;
00816         }
00817     }
00818 
00819     else
00820     {
00821         requested = true;
00822     }
00823 
00824     //
00825     // If the record's not interesting, move on.  Remember to skip over any
00826     // padding bytes inserted to make the next record header start on a
00827     // four byte boundary in the file.
00828     //
00829     if( requested == false )
00830     {
00831         data_length += (4 - (data_length & SIO_align)) & SIO_align;
00832         status = FSEEK( handle, data_length, 1 );
00833         if( status != 0 )
00834         {
00835             state = SIO_STATE_ERROR;
00836             if( verbosity >= SIO_ERRORS )
00837             {
00838                 std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
00839                           << "Failed skipping record"
00840                           << std::endl;
00841             }
00842             return( SIO_STREAM_EOF );
00843         }
00844         continue;
00845     }
00846 
00847     //
00848     // Ensure sufficient buffering for the uncompressed record.
00849     //
00850     if( (head_length + ucmp_length) >= (bufmax - bufloc) )
00851     {
00852         unsigned int
00853             newlen;
00854 
00855         unsigned char
00856            *newbuf;
00857 
00858         newlen = head_length + ucmp_length;
00859         newbuf = static_cast<unsigned char*>(malloc( newlen )); 
00860         if( newbuf == NULL )
00861         {
00862             if( verbosity >= SIO_ERRORS )
00863             {
00864                 std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
00865                           << "Uncompressed buffer allocation failed"
00866                           << std::endl;
00867             }
00868             return( SIO_STREAM_NOALLOC );
00869         }
00870 
00871         memcpy( newbuf, bufloc, head_length );
00872         free( bufloc );
00873         bufloc = newbuf;
00874         buffer = newbuf + head_length;
00875         bufmax = bufloc + newlen;
00876     }
00877 
00878     //
00879     // Extract the compression bit from the options word.
00880     //
00881     compress = options & SIO_OPT_COMPRESS;
00882 
00883     if( !compress )
00884     {
00885         //
00886         // Read the rest of the record data.  Note that uncompressed data is
00887         // -always- aligned to a four byte boundary in the file, so no pad
00888         // skipping is necessary,
00889         //
00890         status = FREAD( buffer, SIO_LEN_SB, data_length, handle );
00891         if( status < data_length )
00892         {
00893             state = SIO_STATE_ERROR;
00894             if( verbosity >= SIO_ERRORS )
00895             {
00896                 std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
00897                           << "Failed reading uncompressed record data"
00898                           << std::endl;
00899             }
00900             return( SIO_STREAM_EOF );
00901         }
00902     }
00903 
00904     else
00905     {
00906         //
00907         // Ensure sufficient buffering for the compressed record.
00908         //
00909         if( data_length >= (cmpmax - cmploc) )
00910         {
00911             unsigned char
00912                *newbuf;
00913 
00914             newbuf = static_cast<unsigned char*>(malloc( data_length )); 
00915             if( newbuf == NULL )
00916             {
00917                 if( verbosity >= SIO_ERRORS )
00918                 {
00919                     std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
00920                               << "Compressed buffer allocation failed"
00921                               << std::endl;
00922                 }
00923                 return( SIO_STREAM_NOALLOC );
00924             }
00925 
00926             free( cmploc );
00927             cmploc = newbuf;
00928             cmpmax = cmploc + data_length;
00929         }
00930 
00931         //
00932         // Read the compressed record data.
00933         //
00934         status = FREAD( cmploc, SIO_LEN_SB, data_length, handle );
00935         if( status < data_length )
00936         {
00937             state = SIO_STATE_ERROR;
00938             if( verbosity >= SIO_ERRORS )
00939             {
00940                 std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
00941                           << "Failed reading compressed record data"
00942                           << std::endl;
00943             }
00944             return( SIO_STREAM_EOF );
00945         }
00946 
00947         //
00948         // Skip the read pointer over any padding bytes that may have been
00949         // inserted to make the next record header start on a four byte
00950         // boundary in the file.
00951         //
00952         padlen = (4 - (data_length & SIO_align)) & SIO_align;
00953         if( padlen > 0 )
00954         {
00955             status = FSEEK( handle, padlen, 1 );
00956             if( status != 0 )
00957             {
00958                 state = SIO_STATE_ERROR;
00959                 if( verbosity >= SIO_ERRORS )
00960                 {
00961                     std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
00962                               << "Failed reading end-of-record pad data"
00963                               << std::endl;
00964                 }
00965                 return( SIO_STREAM_EOF );
00966             }
00967         }
00968 
00969         //
00970         // Set up for the decompression.
00971         //
00972         z_strm->next_in   = cmploc;
00973         z_strm->avail_in  = data_length;
00974         z_strm->total_in  = 0;
00975 
00976         z_strm->next_out  = buffer;
00977         z_strm->avail_out = bufmax-buffer;
00978         z_strm->total_out = 0;
00979 
00980         z_stat = inflate( z_strm, Z_FINISH );
00981         if( z_stat != Z_STREAM_END )
00982         {
00983             state = SIO_STATE_ERROR;
00984             if( verbosity >= SIO_ERRORS )
00985             {
00986                 std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
00987                           << "ZLIB error number " << z_stat
00988                           << std::endl;
00989 
00990                 std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
00991                           << "Decompression failed"
00992                           << std::endl;
00993             }
00994             return( SIO_STREAM_BADCOMPRESS );
00995         }
00996     
00997         z_stat = inflateReset( z_strm );
00998         if( z_stat != Z_OK )
00999         {
01000             state = SIO_STATE_ERROR;
01001             if( verbosity >= SIO_ERRORS )
01002             {
01003                 std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
01004                           << "ZLIB error number " << z_stat
01005                           << std::endl;
01006 
01007                 std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
01008                           << "Decompression de-initialization failed"
01009                           << std::endl;
01010             }
01011             return( SIO_STREAM_BADCOMPRESS );
01012         }
01013     
01014     }
01015 
01016     //
01017     // Let the record manager sort out reading all the blocks.
01018     //
01019     recmax = bufloc + head_length + ucmp_length;
01020     status = (*record)->read( this, options );
01021 
01022     //
01023     // Clear the maps that may have accumulated during record unpacking.
01024     // This must be done unconditionally (otherwise tables from a busted
01025     // record may persist into the next record).
01026     //
01027     pointerTo->erase( pointerTo->begin(), pointerTo->end() );
01028     pointedAt->erase( pointedAt->begin(), pointedAt->end() );
01029 
01030     if( !( status & 1 ) )
01031     {
01032         if( verbosity >= SIO_ERRORS )
01033         {
01034             std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
01035                       << "Unpacking error"
01036                       << std::endl;
01037         }
01038     } else {
01039       // save position of record start // can be queried with lastRecordStart()
01040       recPos = recStart ;
01041     }
01042 
01043 }
01044 
01045 //
01046 // That's all folks!
01047 //
01048 return( status );
01049 }
01050 
01051 // ----------------------------------------------------------------------------
01052 // Set the verbosity level.
01053 // ----------------------------------------------------------------------------
01054 SIO_verbosity SIO_stream::setVerbosity
01055 (
01056     SIO_verbosity   i_verb
01057 )
01058 { SIO_verbosity o_verb = verbosity; verbosity = i_verb; return( o_verb ); } 
01059 
01060 // ----------------------------------------------------------------------------
01061 // Write a record (by record name).
01062 // ----------------------------------------------------------------------------
01063 unsigned int SIO_stream::write
01064 (
01065     const char*     i_name
01066 )
01067 {
01068 
01069 //
01070 // Local variables.
01071 //
01072 SIO_record
01073    *record;
01074 
01075 //
01076 // Validate the record name.
01077 //
01078 record = SIO_recordManager::get( i_name );
01079 if( record == NULL )
01080 {
01081     if( verbosity >= SIO_ERRORS )
01082     {
01083         std::cout << "SIO: ["  << name << "/" << i_name << "//] "
01084                   << "Record name not recognized" 
01085                   << std::endl;
01086     }
01087     return( SIO_STREAM_NOSUCHRECORD );
01088 }
01089 
01090 //
01091 // Call the workhorse.
01092 //
01093 return( write( record, i_name ) );
01094 }
01095 
01096 // ----------------------------------------------------------------------------
01097 // Write a record (by record pointer).
01098 // ----------------------------------------------------------------------------
01099 unsigned int SIO_stream::write
01100 (
01101     SIO_record*     record
01102 )
01103 {
01104 
01105 //
01106 // Call the workhorse.
01107 //
01108 return( write( record, record->getName()->c_str() ) );
01109 }
01110 
01111 // ----------------------------------------------------------------------------
01112 // Write a record (workhorse)
01113 // ----------------------------------------------------------------------------
01114 unsigned int SIO_stream::write
01115 (
01116     SIO_record*     record,
01117     const char*     i_name
01118 )
01119 {
01120 
01121 //
01122 // Local variables.
01123 //
01124 int
01125     z_stat;
01126 
01127 unsigned int
01128     data_length,
01129     data_length_off,
01130     head_length,
01131     head_length_off,
01132     name_length,
01133     ucmp_length,
01134     ucmp_length_off,
01135     bufout,
01136     compress,
01137     newlen,
01138     oldlen,
01139     options,
01140     status;
01141 
01142 unsigned char
01143    *newbuf;
01144 
01145 static unsigned char
01146     pad[4] = { 0, 0, 0, 0 };
01147  
01148 //
01149 // The stream must be open!
01150 //
01151 if( state != SIO_STATE_OPEN )
01152 {
01153     if( verbosity >= SIO_ERRORS )
01154     {
01155         std::cout << "SIO: ["  << name << "//] "
01156                   << "Cannot write (stream is not open)"
01157                   << std::endl;
01158     }
01159     return( SIO_STREAM_NOTOPEN );
01160 }
01161 
01162 //
01163 // This must be a writeable stream!
01164 //
01165 if( mode == SIO_MODE_READ )
01166 {
01167     if( verbosity >= SIO_ERRORS )
01168     {
01169         std::cout << "SIO: ["  << name << "//] "
01170                   << "Cannot write (stream is read only)"
01171                   << std::endl;
01172     }
01173     return( SIO_STREAM_READONLY );
01174 }
01175 
01176 //
01177 // Capture the record name for error reporting.
01178 //
01179 rec_name = i_name;
01180 
01181 //
01182 // Initialize the buffer.
01183 //
01184 buffer = bufloc;
01185 
01186 //
01187 // Save begin of record (current file end) 
01188 //
01189 recPos = FTELL( handle ) ;
01190 
01191 //
01192 // Output: 1) A placeholder for the record header length.
01193 //         2) A 'framing' marker (to help in debugging).
01194 //         3) An options word.
01195 //         4) A placeholder for the record data length (compressed).
01196 //         5) A placeholder for the record data length (uncompressed).
01197 //         6) The length of the record name.
01198 //         7) The record name.
01199 //
01200 compress = record->getCompress();
01201 options  = record->getOptions();
01202 
01203 head_length_off = buffer - bufloc;
01204 SIO_DATA( this, &SIO_mark_record,            1           );
01205 SIO_DATA( this, &SIO_mark_record,            1           );
01206 SIO_DATA( this, &options,                    1           );
01207 
01208 data_length_off = buffer - bufloc;
01209 SIO_DATA( this, &SIO_mark_record,            1           );
01210 
01211 ucmp_length_off = buffer - bufloc;
01212 SIO_DATA( this, &SIO_mark_record,            1           );
01213 
01214 name_length = strlen( i_name );
01215 SIO_DATA( this, &name_length,                1           );
01216 SIO_DATA( this,  const_cast<char *>(i_name), name_length );
01217 
01218 //
01219 // Back fill the length of the record header.
01220 //
01221 head_length = buffer - bufloc;
01222 SIO_functions::copy( UCHR_CAST(&head_length), (bufloc + head_length_off),
01223                      SIO_LEN_QB,              1                        );
01224 
01225 //
01226 // Ask the record object to fill the buffer with blocks. If an error is
01227 // reported, just print a complaint and skip writing this buffer.
01228 //
01229 status = record->write( this );
01230 if( !(status & 1) )
01231 {
01232     if( verbosity >= SIO_ERRORS )
01233     {
01234         std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
01235                   << "Packing error"
01236                   << std::endl;
01237     }
01238     return( status );
01239 }
01240 
01241 //
01242 // Fill in the uncompressed record length.
01243 //
01244 ucmp_length = (buffer - bufloc) - head_length;
01245 SIO_functions::copy( UCHR_CAST(&ucmp_length), (bufloc + ucmp_length_off),
01246                      SIO_LEN_QB,              1                        );
01247 
01248 // //debug
01249 // std::cout << "*************** SIO: ["  << name << "/" << rec_name << "/] "
01250 // << "writing record -  compressed : "  << compress 
01251 // << std::endl;
01252 
01253 
01254 //
01255 // Write out the complete record.
01256 //
01257 if( !compress )
01258 {
01259     //
01260     // Fill in the written length of the record data (identical with the
01261     // uncompressed length when no compression is being performed).
01262     //
01263     data_length = ucmp_length;
01264     SIO_functions::copy( UCHR_CAST(&data_length), (bufloc + data_length_off),
01265                          SIO_LEN_QB,              1                        );
01266 
01267     //
01268     // When not compressing, both the record header and the record data
01269     // can be written in one swell foop.  Note that uncompressed data always
01270     // satisfies the requirement that it ends on a four byte boundary, so
01271     // no padding is required.
01272     //
01273     data_length += head_length;
01274     bufout = FWRITE( bufloc, sizeof(char), data_length, handle );
01275     if( bufout != data_length && ! FFLUSH( handle ) ) // fg 20030514 - flush the record
01276     {
01277         state = SIO_STATE_ERROR;
01278         if( verbosity >= SIO_ERRORS )
01279         {
01280             std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
01281                       << "File error writing record" 
01282                       << std::endl;
01283         }
01284         return( SIO_STREAM_BADWRITE );
01285     }
01286 }
01287 else
01288 {
01289     //
01290     // Set up for the compression.
01291     //
01292     z_strm->next_in   = bufloc + head_length;
01293     z_strm->avail_in  = ucmp_length;
01294     z_strm->total_in  = 0;
01295 
01296     z_strm->next_out  = cmploc;
01297     z_strm->avail_out = cmpmax - cmploc;
01298     z_strm->total_out = 0;
01299 
01300     //
01301     // Loop the compression in case the compression buffer is not big enough.
01302     //
01303     for(;;)
01304     {
01305         z_stat = deflate( z_strm, Z_FINISH );
01306         if( z_strm->avail_out > 0 )
01307             break;
01308 
01309         newlen = (cmpmax - cmploc) << 1;
01310         newbuf = static_cast<unsigned char*>(malloc( newlen ));
01311         if( newbuf == NULL )
01312         {
01313             if( verbosity >= SIO_ERRORS )
01314             {
01315                 std::cout << "SIO: ["  
01316                           << name     << "/"
01317                           << rec_name << "//] "
01318                           << "Compression buffer allocation failed"
01319                           << std::endl;
01320             }
01321         
01322             state = SIO_STATE_ERROR;
01323             return( SIO_STREAM_NOALLOC );
01324         }
01325 
01326         oldlen = z_strm->next_out - cmploc;
01327         memcpy( newbuf, cmploc, oldlen );
01328         free( cmploc );
01329         cmploc = newbuf;
01330         cmpmax = cmploc + newlen;
01331 
01332         z_strm->next_out  = cmploc + oldlen;
01333         z_strm->avail_out = cmpmax - z_strm->next_out;
01334 
01335         if( verbosity >= SIO_ALL )
01336         {
01337             std::cout << "SIO: ["  
01338                       << name     << "/"
01339                       << rec_name << "//] "
01340                       << "Allocated a "
01341                       << newlen
01342                       << "(0x" << std::hex << newlen << std::dec << ")"
01343                       << " byte compression buffer"
01344                       << std::endl;
01345         }
01346     }
01347 
01348     z_stat = deflateReset( z_strm );
01349     if( z_stat != Z_OK )
01350     {
01351         state = SIO_STATE_ERROR;
01352         if( verbosity >= SIO_ERRORS )
01353         {
01354             std::cout << "SIO: ["  << name << "//] "
01355                       << "ZLIB error number " << z_stat
01356                       << std::endl;
01357 
01358             std::cout << "SIO: ["  << name << "//] "
01359                       << "Compression de-initialization failed"
01360                       << std::endl;
01361         }
01362         return( SIO_STREAM_BADCOMPRESS );
01363     }
01364 
01365     //
01366     // Fill in the length of the compressed buffer.
01367     //
01368     data_length = z_strm->next_out - cmploc;
01369     SIO_functions::copy( UCHR_CAST(&data_length), (bufloc + data_length_off),
01370                          SIO_LEN_QB,              1                        );
01371 
01372     //
01373     // Write the record header.
01374     //
01375     bufout = FWRITE( bufloc, sizeof(char), head_length, handle );
01376     if( bufout != head_length )
01377     {
01378         state = SIO_STATE_ERROR;
01379         if( verbosity >= SIO_ERRORS )
01380         {
01381             std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
01382                       << "File error writing record header" 
01383                       << std::endl;
01384         }
01385         return( SIO_STREAM_BADWRITE );
01386     }
01387     
01388     //
01389     // Write the compressed record data.
01390     //
01391     bufout = FWRITE( cmploc, sizeof(char), data_length, handle );
01392     if( bufout != data_length && ! FFLUSH(handle) ) // fg 20030514 - flush the record
01393     {
01394         state = SIO_STATE_ERROR;
01395         if( verbosity >= SIO_ERRORS )
01396         {
01397             std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
01398                       << "File error writing record content" 
01399                       << std::endl;
01400         }
01401         return( SIO_STREAM_BADWRITE );
01402     }
01403 
01404     //
01405     // Insert any necessary padding to make the next record header start
01406     // on a four byte boundary in the file (to make it directly accessible
01407     // for xdr read).
01408     //
01409     newlen = (4 - (data_length & SIO_align)) & SIO_align;
01410     if( newlen > 0 )
01411     {
01412         bufout = FWRITE( pad, sizeof(char), newlen, handle );
01413         if( bufout != newlen && ! FFLUSH(handle))// fg 20030514 - flush the record
01414         {
01415             state = SIO_STATE_ERROR;
01416             if( verbosity >= SIO_ERRORS )
01417             {
01418                 std::cout << "SIO: ["  << name << "/" << rec_name << "/] "
01419                           << "File error writing end-of-record pad" 
01420                           << std::endl;
01421             }
01422             return( SIO_STREAM_BADWRITE );
01423         }
01424     }
01425 }
01426 
01427 //
01428 // Clear the maps that may have accumulated during record writing.
01429 //
01430 pointerTo->erase( pointerTo->begin(), pointerTo->end() );
01431 pointedAt->erase( pointedAt->begin(), pointedAt->end() );
01432 
01433 //
01434 // That's all folks!
01435 //
01436 return( SIO_STREAM_SUCCESS );
01437 }
01438 

Generated on Mon Jan 7 13:15:21 2013 for MicromegasFramework by  doxygen 1.4.7