/*******************************************************************/ /* XDMF */ /* eXtensible Data Model and Format */ /* */ /* Id : Id */ /* Date : $Date$ */ /* Version : $Revision$ */ /* */ /* Author:Kenji Takizawa (Team for Advanced Flow Simulation and Modeling) */ /* */ /* Copyright @ 2008 US Army Research Laboratory */ /* All Rights Reserved */ /* See Copyright.txt or http://www.arl.hpc.mil/ice for details */ /* */ /* This software is distributed WITHOUT ANY WARRANTY; without */ /* even the implied warranty of MERCHANTABILITY or FITNESS */ /* FOR A PARTICULAR PURPOSE. See the above copyright notice */ /* for more information. */ /* */ /*******************************************************************/ #include "XdmfValuesBinary.h" #include "XdmfDataStructure.h" #include "XdmfArray.h" //#include "XdmfHDF.h" #include "XdmfDOM.h" #include #include #ifdef XDMF_USE_GZIP #include "gzstream.h" #endif #ifdef XDMF_USE_BZIP2 #include "bz2stream.h" #endif namespace xdmf2 { //#include //#include //Internal Classes template struct ByteSwaper { static inline void swap(void*p){} static inline void swap(void*p,XdmfInt64 length){ char* data = static_cast(p); for(XdmfInt64 i=0;i::swap(data); } } }; template<> void ByteSwaper<2>::swap(void*p){ char one_byte; char* data = static_cast(p); one_byte = data[0]; data[0] = data[1]; data[1] = one_byte; }; template<> void ByteSwaper<4>::swap(void*p){ char one_byte; char* data = static_cast(p); one_byte = data[0]; data[0] = data[3]; data[3] = one_byte; one_byte = data[1]; data[1] = data[2]; data[2] = one_byte; }; template<> void ByteSwaper<8>::swap(void*p){ char one_byte; char* data = static_cast(p); one_byte = data[0]; data[0] = data[7]; data[7] = one_byte; one_byte = data[1]; data[1] = data[6]; data[6] = one_byte; one_byte = data[2]; data[2] = data[5]; data[5] = one_byte; one_byte = data[3]; data[3] = data[4]; data[4] = one_byte; }; void XdmfValuesBinary::byteSwap(XdmfArray * RetArray){ if(needByteSwap()){ switch(RetArray->GetElementSize()){ case 1: break; case 2: ByteSwaper<2>::swap(RetArray->GetDataPointer(),RetArray->GetNumberOfElements()); break; case 4: ByteSwaper<4>::swap(RetArray->GetDataPointer(),RetArray->GetNumberOfElements()); break; case 8: ByteSwaper<8>::swap(RetArray->GetDataPointer(),RetArray->GetNumberOfElements()); break; default: break; } } } class HyperSlabReader:public XdmfObject{// XdmfInt64 ncontiguous;//byte XdmfInt64 start[XDMF_MAX_DIMENSION];//byte XdmfInt64 stride[XDMF_MAX_DIMENSION];//byte XdmfInt64 last[XDMF_MAX_DIMENSION];//byte XdmfInt64 count[XDMF_MAX_DIMENSION];//size XdmfInt64 rank; void toTotal(const XdmfInt64 * dims, XdmfInt32 byte, XdmfInt64 * data){ data[this->rank-1] *= byte; for(XdmfInt32 i = 1; i< this->rank; ++i){ for(XdmfInt32 j=i; jrank; ++j){ data[i-1] *= dims[j]; } data[i-1] *= byte; } } void read(XdmfInt32 k, char *& pointer, istream &is){ is.seekg(this->start[k], std::ios::cur); //XdmfDebug("Skip: " << this->start[k]<<", "<count[k];istride[k] <<", " << k ); is.seekg(this->stride[k], std::ios::cur); is.read(pointer, ncontiguous); //XdmfDebug("Read: " << ncontiguous); pointer += ncontiguous; } }else{ read(k+1,pointer,is); for(XdmfInt64 i=1,l=this->count[k];istride[k], std::ios::cur); //XdmfDebug("Skip: " << this->stride[k] << ", "<< k); read(k+1,pointer,is); } } //XdmfDebug("Skip: " << this->last[k] << ", " << k); is.seekg(this->last[k], std::ios::cur); } public: HyperSlabReader(XdmfInt32 rank, XdmfInt32 byte, const XdmfInt64 * dims, const XdmfInt64 * start, const XdmfInt64 * lstride, const XdmfInt64 * lcount){ assert(rank>0 && rankrank = rank; XdmfInt64 d[XDMF_MAX_DIMENSION]; for(XdmfInt32 i =0;istart[i] = start[i]; this->stride[i] = lstride[i]-1; this->count[i] = lcount[i]; d[i] = dims[i]; } //reduce rank for(XdmfInt32 i =rank-1;i>0;--i){ if(this->start[i]==0 && this->stride[i]==0 && this->count[i]==dims[i]){ --this->rank; }else{ break; } } if(this->rank != rank){ XdmfDebug("Reduce Rank: " << rank << " to " << this->rank); for(XdmfInt32 i = this->rank;irank;++i){ this->last[i] = d[i] - (this->start[i] + (this->stride[i]+1)*(this->count[i]-1) + 1); } toTotal(d,byte, this->start); toTotal(d,byte, this->stride); toTotal(d,byte, this->last); ncontiguous=byte; if(this->stride[this->rank-1]==0){ ncontiguous *= this->count[this->rank-1]; this->count[this->rank-1] = 1; } XdmfDebug("Contiguous byte: " << ncontiguous); } ~HyperSlabReader(){ } void read(char * pointer, istream &is){ read(static_cast(0),pointer,is); } }; size_t XdmfValuesBinary::getSeek(){ if(this->Seek==NULL)return 0; return static_cast(strtoull(this->Seek, NULL, 0)); } enum XdmfValuesBinary::CompressionType XdmfValuesBinary::getCompressionType(){ if(this->Compression==NULL||XDMF_WORD_CMP(Compression, "Raw")){ return Raw; } if(XDMF_WORD_CMP(Compression, "Zlib")){ return Zlib; } if(XDMF_WORD_CMP(Compression, "BZip2")){ return BZip2; } return Raw; } XdmfValuesBinary::XdmfValuesBinary() { this->Endian = NULL; this->Seek = NULL; this->Compression = NULL; this->SetFormat(XDMF_FORMAT_BINARY); } XdmfValuesBinary::~XdmfValuesBinary() { } XdmfArray * XdmfValuesBinary::Read(XdmfArray *anArray){ if(!this->DataDesc){ XdmfErrorMessage("DataDesc has not been set"); return(NULL); } XdmfArray *RetArray = anArray; ostrstream FullFileName; // Allocate anArray if Necessary if(!RetArray){ RetArray = new XdmfArray(); RetArray->CopyType(this->DataDesc); RetArray->CopyShape(this->DataDesc); RetArray->CopySelection(this->DataDesc); RetArray->Allocate(); } XdmfDebug("Accessing Binary CDATA"); { XdmfConstString Value = this->Get("Endian"); if(Value){ this->SetEndian(Value); }else{ this->Endian = NULL; } } { XdmfConstString Value = this->Get("Seek"); if(Value){ this->SetSeek(Value); }else{ this->Seek = NULL; } } { XdmfConstString Value = this->Get("Compression"); if(Value){ this->SetCompression(Value); }else{ this->Compression = NULL; } } XdmfString DataSetName = 0; XDMF_STRING_DUPLICATE(DataSetName, this->Get("CDATA")); XDMF_WORD_TRIM(DataSetName); XdmfInt64 dims[XDMF_MAX_DIMENSION]; XdmfInt32 rank = this->DataDesc->GetShape(dims); XdmfInt64 total = 1; for(XdmfInt32 i=0;iGetCoreLength()); XdmfDebug(" Byte " << RetArray->GetElementSize()); //check // struct stat buf; // stat(DataSetName, &buf); // assert(buf.st_size == RetArray->GetCoreLength()); //ifstream fs(DataSetName,std::ios::binary); if( RetArray->GetDataPointer() == NULL ){ XdmfErrorMessage("Memory Object Array has no data storage"); return( NULL ); } istream * fs = NULL; if( ( strlen( this->DOM->GetWorkingDirectory() ) > 0 ) && ( DataSetName[0] != '/' ) ){ FullFileName << this->DOM->GetWorkingDirectory() << "/"; } FullFileName << DataSetName << ends; char * path = FullFileName.rdbuf()->str(); XdmfDebug("Opening Binary Data for Reading : " << FullFileName.str()); //char * path = new char [ strlen(this->DOM->GetWorkingDirectory())+strlen(DataSetName) + 1 ]; //strcpy(path, this->DOM->GetWorkingDirectory()); //strcpy(path+strlen(this->DOM->GetWorkingDirectory()), DataSetName); try{ size_t seek = this->getSeek(); switch(getCompressionType()){ case Zlib: XdmfDebug("Compression: Zlib"); #ifdef XDMF_USE_GZIP fs = new igzstream(path, std::ios::binary|std::ios::in); if(seek!=0){ XdmfDebug("Seek has not supported with Zlib."); } break; #else XdmfDebug("GZip Lib is needed."); #endif case BZip2: XdmfDebug("Compression: Bzip2"); #ifdef XDMF_USE_BZIP2 fs = new ibz2stream(path);//, std::ios::binary|std::ios::in); if(seek!=0){ XdmfDebug("Seek has not supported with Bzip2."); } break; #else XdmfDebug("BZIP2 LIBRARY IS NEEDED."); #endif default: fs = new ifstream(path, std::ios::binary); fs->seekg(seek); XdmfDebug("Seek: " << seek); break; } fs->exceptions( ios::failbit | ios::badbit ); if(!fs->good()){ XdmfErrorMessage("Can't Open File " << DataSetName); //return(NULL); } if( this->DataDesc->GetSelectionType() == XDMF_HYPERSLAB ){ XdmfDebug("Hyperslab data"); XdmfInt32 Rank; XdmfInt64 Start[ XDMF_MAX_DIMENSION ]; XdmfInt64 Stride[ XDMF_MAX_DIMENSION ]; XdmfInt64 Count[ XDMF_MAX_DIMENSION ]; Rank = this->DataDesc->GetHyperSlab( Start, Stride, Count ); HyperSlabReader wrapper(Rank,RetArray->GetElementSize(),dims,Start,Stride, Count); wrapper.read(reinterpret_cast(RetArray->GetDataPointer()), *fs); }else{ XdmfDebug("Regular data"); fs->read(reinterpret_cast(RetArray->GetDataPointer()), RetArray->GetCoreLength()); } } catch( std::exception& e){ XdmfErrorMessage(e.what()); delete fs; //delete path; return( NULL ); } //fs->close();? delete fs; //delete path; byteSwap(RetArray); return RetArray; } XdmfInt32 XdmfValuesBinary::Write(XdmfArray *anArray, XdmfConstString aHeavyDataSetName){ if(!aHeavyDataSetName) aHeavyDataSetName = this->GetHeavyDataSetName(); if(anArray->GetHeavyDataSetName()){ aHeavyDataSetName = (XdmfConstString)anArray->GetHeavyDataSetName(); }else{ return(XDMF_FAIL); } XdmfDebug("Writing Values to " << aHeavyDataSetName); if(!this->DataDesc ){ XdmfErrorMessage("DataDesc has not been set"); return(XDMF_FAIL); } if(!anArray){ XdmfErrorMessage("Array to Write is NULL"); return(XDMF_FAIL); } if( anArray->GetDataPointer() == NULL ){ XdmfErrorMessage("Memory Object Array has no data storage"); return(XDMF_FAIL); } char* hds; XDMF_STRING_DUPLICATE(hds, aHeavyDataSetName); XDMF_WORD_TRIM( hds ); this->Set("CDATA", hds); byteSwap(anArray); ostream * fs = NULL; char * path = new char [ strlen(this->DOM->GetWorkingDirectory())+strlen(aHeavyDataSetName) + 1 ]; strcpy(path, this->DOM->GetWorkingDirectory()); strcpy(path+strlen(this->DOM->GetWorkingDirectory()), aHeavyDataSetName); try{ //ofstream fs(aHeavyDataSetName,std::ios::binary); switch(getCompressionType()){ case Zlib: XdmfDebug("Compression: ZLIB"); #ifdef XDMF_USE_GZIP // fs = gzip(fs); fs = new ogzstream(path, std::ios::binary|std::ios::out); break; #else XdmfDebug("GZIP LIBRARY IS NEEDED."); #endif case BZip2: XdmfDebug("Compression: BZIP2"); #ifdef XDMF_USE_BZIP2 fs = new obz2stream(path);//, std::ios::binary|std::ios::out); break; #else XdmfDebug("BZIP2 LIBRARY IS NEEDED."); #endif default: fs = new ofstream(path, std::ios::binary); //fs->seekg(seek); //XdmfDebug("Seek: " << seek); break; } fs->exceptions( ios::failbit | ios::badbit ); if(!fs->good()){ XdmfErrorMessage("Can't Open File " << aHeavyDataSetName); } fs->write(reinterpret_cast(anArray->GetDataPointer()), anArray->GetCoreLength()); }catch( std::exception& ){ //fs.close(); byteSwap(anArray); delete fs; delete [] hds; delete [] path; return(XDMF_FAIL); } byteSwap(anArray); delete [] fs; delete [] hds; delete [] path; return(XDMF_SUCCESS); } #ifdef CMAKE_WORDS_BIGENDIAN bool XdmfValuesBinary::needByteSwap(){ return XDMF_WORD_CMP(Endian, "Little"); } #else bool XdmfValuesBinary::needByteSwap(){ return XDMF_WORD_CMP(Endian, "Big"); } #endif // vim: expandtab sw=4 : }