#ifndef DATAONDEMAND_H #define DATAONDEMAND_H #include "IGBheader.h" #include #include #include #include #include "DataClass.h" #include "AsciiReader.hpp" using namespace std; static const size_t IGB_OFFSET = 1024; /** Class for reading data requested from the file on disk */ template class DataOnDemand: public DataClass { public: virtual T max(int t){return extremum(t,true);} //!< maximum data value at a time virtual T max(){assert(0);} //!< maximum data value at a time virtual T min(int t){return extremum(t,false);}//!< minimum data value at a time virtual T min(){assert(0);} //!< minimum data value at a time virtual T* slice(int); //!< pointer to time slice of data virtual void time_series( int, T* ); //!< time series for a point virtual void increment(int){} //!< time slice increment DataOnDemand(const char *fn, int); virtual ~DataOnDemand(){free(data);if(databuf)free(databuf);} private: IGBheader *hdr; AsciiReader *asciiRdr=NULL; char *databuf=NULL; const char *_scanstr; //!< format code to read ascii file const int bufsz=1024; char buf[1024]; //!< storage tor read ascii line T extremum(int,bool); using DataClass :: data; using DataClass :: maxtm; using DataClass :: last_tm; using DataClass :: slice_size; using DataClass :: filename; using DataClass :: _dt; using DataClass :: _t0; using DataClass :: _ftype; }; template DataOnDemand::DataOnDemand( const char *fn, int slsz ) { bool IGBdata; int j = 0; FILE *in; string scanner; map CGfiles; map::iterator CGp; #ifdef USE_HDF5 hid_t hin; struct ch5s_nodal_grid info; unsigned int index; #endif filename = fn; slice_size = slsz; _ftype = FileTypeFinder( fn ); if ( _ftype == FThdf5 ) { #ifdef USE_HDF5 if(ch5_open( fname.substr(0, filename.find_last_of(":")).c_str(), &hin ) ) throw(1); #endif } else { if ( (in=fopen(fn, "r")) == NULL ) throw( 1 ); } // ugly but I don't know what else to do besides specialization which is ugly if ( typeid(T) == typeid(double) ) _scanstr = "%lf"; else if ( typeid(T) == typeid(float) ) _scanstr = "%f"; else if ( typeid(T) == typeid(int) ) _scanstr = "%d"; else if ( typeid(T) == typeid(short) ) _scanstr = "%hd"; else if ( typeid(T) == typeid(long) ) _scanstr = "%ld"; else exit(1); // open file if ( _ftype == FTIGB ) { hdr = new IGBheader( in, true ); if ( hdr->slice_sz() != slice_size ) { maxtm = -1; throw PointMismatch(slice_size,hdr->slice_sz()); } maxtm = hdr->t(); _dt = hdr->inc_t(); _t0 = hdr->org_t(); databuf = (char *)malloc( slice_size*hdr->data_size() ); } else if ( _ftype == FTfileSeqCG ) { CG_file_list( CGfiles, fn ); CGp = CGfiles.begin(); scanner = "%*f %*f"; scanner += _scanstr; } else if( _ftype == FThdf5 ) { string gtype; #ifdef USE_HDF5 if( parse_HDF5_grid( fn, gtype, index ) || gtype!="nodal" ) throw(1); ch5s_nodal_grid_info( hin, index, &info ); _dt = info.time_delta; maxtm = 0; #endif _t0 = 0; } else if( _ftype == FTascii ) { asciiRdr = new AsciiReader; asciiRdr->read_file( filename ); if( asciiRdr->num_lines() < slice_size ){ maxtm = -1; throw PointMismatch(slice_size,asciiRdr->num_lines()); } maxtm = asciiRdr->num_lines()/slice_size - 1; } data = (T *)malloc( slice_size*sizeof(T) ); last_tm = 0; // get one slice switch( _ftype ) { case FTIGB: hdr->read_data( data, 1, databuf ); break; case FTascii: for( int i=0; iget_line( i, buf, bufsz ); if( sscanf(buf, _scanstr, data+i ) != 1 ) { maxtm = -1; throw( 1 ); } } break; #ifdef USE_HDF5 case FThdf5: assert(0); #endif default: assert(0); } } /** return an extremum * * \param tm frame number * \param max determine max?, min o.w. */ template T DataOnDemand::extremum( int tm, bool max ) { if ( tm>maxtm ) return 0; T* (*exfcn)(T*, T*); if( max ) exfcn = max_element; else exfcn = min_element; if( last_tm == tm ) return *exfcn( data, data+slice_size ); // analyze a temporary slice T* sdata = (T*)malloc(slice_size*sizeof(T)); if( _ftype == FTIGB ) { hdr->data_frame( tm ); hdr->read_data( sdata, 1, NULL ); } else if( _ftype == FTascii ) { for( int i=0; iget_line( i+slice_size*tm, buf, bufsz ); sscanf( buf, _scanstr, sdata+i ); } } else { assert(0); } T maxdat = *exfcn( sdata, sdata+slice_size ) ; free( sdata ); return maxdat; } template T* DataOnDemand::slice( int tm ) { if ( tm>maxtm ) return NULL; if( tm == last_tm ) return data; if( _ftype == FTIGB ) { hdr->data_frame( tm ); hdr->read_data( data, 1, databuf ); } else if( _ftype == FTascii ) { for( int i=0; iget_line( i+slice_size*tm, buf, bufsz ); sscanf( buf, _scanstr, data+i ); } } else assert(0); last_tm = tm; return data; } template void DataOnDemand::time_series( int offset, T* buffer ) { FILE *in = (FILE *)hdr->fileptr(); if( _ftype == FTIGB ) { size_t slsz = hdr->slice_sz()*hdr->data_size(); char datum[hdr->data_size()]; offset *=hdr->data_size(); for( size_t i=0; i<=maxtm; i++ ) { fseek( in, IGB_OFFSET+offset+i*slsz, SEEK_SET ); fread( datum, hdr->data_size(), 1, in ); if ( hdr->endian() != hdr->systeme() ) hdr->swab( datum, 1 ); buffer[i] = hdr->convert_buffer_datum( datum, 0 ); } } else if( _ftype == FTascii ) { for( int i=0; i<=maxtm; i ++ ) { asciiRdr->get_line( offset+slice_size, buf, bufsz ); sscanf( buf, _scanstr, buffer+i ); } } } #endif