diff options
Diffstat (limited to 'src/IEEEIO.hh')
-rw-r--r-- | src/IEEEIO.hh | 709 |
1 files changed, 709 insertions, 0 deletions
diff --git a/src/IEEEIO.hh b/src/IEEEIO.hh new file mode 100644 index 0000000..1b81dbb --- /dev/null +++ b/src/IEEEIO.hh @@ -0,0 +1,709 @@ +#ifndef __IEEEIO_HH_ +#define __IEEEIO_HH_ +#ifndef WIN32 +#include <stdio.h> +#include <unistd.h> +#include <sys/file.h> +#else +#include <io.h> +#endif + +#include "IEEEIOWinDllApi.h" + +#include "IO.hh" +#include "FlexArrayTmpl.H" +#include "Arch.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#if defined(WIN32) || defined(SOLARIS) +// I'm a WIN32 box and I ignore standards +// or I'm a Sun box and I hate BSD. +#define bcopy(src,dest,len) memcpy(dest,src,len) +#else +#include <strings.h> // available non-ANSI/Posix compliant +#endif + +#ifdef FFIO +#include <ffio.h> +#endif + +// Win32/Solaris lseek crap... +#if defined(WIN32) || defined(SOLARIS) || defined (HITACHI) || defined(sun) +#define L_INCR SEEK_CUR +#ifndef L_SET // for that wanky Solaris compiler +#define L_SET SEEK_SET +#endif +#define L_XTND SEEK_END +#endif +// T3E lseek crap... +#ifdef T3E // I'm a T3E and I ignore ANSI/Posix standards +#define L_INCR SEEK_CUR +#define L_SET SEEK_SET +#define L_XTND SEEK_END +#endif + +#define IEEE_NATIVE_MAGIC 0x01020304 +#define IEEE_REVERSE_MAGIC 0x04030201 +#define IEEE_ALTERNATING_MAGIC 0x02010403 + +#define IEEE_BIG_ENDIAN IEEE_NATIVE_MAGIC +#define IEEE_LITTLE_ENDIAN IEEE_REVERSE_MAGIC +#define IEEE_VAX_ENDIAN IEEE_ALTERNATING_MAGIC + +#define IEEE_MAJORVERSION 1 +#define IEEE_MINORVERSION 1 + +class IEEEIO_API IEEEIO : public IObase { +public: + enum RecordType {DataRecord=1,AnnotationRecord,AttributeRecord}; + union btorder { + char c[4]; // write as Int, read as Int + Int i; + }; +#define FileHdrSize (4+4+4+2+2) // T3E Kludge + struct FileHdr { + // do magic twice so we can figure out which byte-order + // the current machine is in addition (without hardcoding) in + // addition to which byte order the file is in + btorder magic; + btorder byteorder; + Long ndatasets; + // T3E will be stupid for this, but thats OK + short majorversion; + short minorversion; + // ** Inline these because they are + // ** actually kludges for the T3E + static int write(IEEEIO *ieeeio,FileHdr &rec){ + int r=0; +#ifdef T3E // data structures are not packed contiguously in memory + r+=ieeeio->write((rec.magic.c),4); + r+=ieeeio->write((rec.byteorder.c),4); + r+=ieeeio->write(&(rec.ndatasets),4); + // this may be incorrect, but it will work for now + // It assumes the low order bytes will be first to + // be written. + r+=ieeeio->write(&(rec.majorversion),2); + r+=ieeeio->write(&(rec.minorversion),2); +#else + // problem if this includes pointers to static methods + // will require an extra degree of inheritance. (inherit + // from a base structure. + r=ieeeio->write(&rec,FileHdrSize); +#endif + return r; + } + static int read(IEEEIO *ieeeio,FileHdr &rec){ + int r=0; +#ifdef T3E // data structures are not packed contiguously in memory + char buffer[FileHdrSize]; + r=ieeeio->read(buffer,FileHdrSize); // read full buffer in and then copy to struct + ::bcopy(buffer,(rec.magic.c),4); + ::bcopy(buffer+4,(rec.byteorder.c),4); + ::bcopy(buffer+8,&(rec.ndatasets),4); + // May be invalid if low order bytes are not the + // proper ones to load. (eg. may fail on big-endian systems) + ::bcopy(buffer+12,&(rec.majorversion),2); + ::bcopy(buffer+14,&(rec.minorversion),2); +#else + r=ieeeio->read(&rec,FileHdrSize); +#endif + return r; + } + static void byteswap(FileHdr &hdr){ + IEEEIO::byteswapBuffer(&(hdr.ndatasets),1,sizeof(hdr.ndatasets)); + // because the t3e doesn't have a 2-byte datatype, must do this manually + IEEEIO::byteswapBuffer(&(hdr.majorversion),1,2); + IEEEIO::byteswapBuffer(&(hdr.minorversion),1,2); + } + // May be a problem to have a nonstatic class member here because + // this will create a vtable entry. + void byteswap(){ + IEEEIO::byteswapBuffer(&ndatasets,1,sizeof(ndatasets)); + // because the t3e doesn't have a 2-byte datatype, must do this manually + IEEEIO::byteswapBuffer(&majorversion,1,2); + IEEEIO::byteswapBuffer(&minorversion,1,2); + } + }; +#define RecordHdrSize (4+4+4) // T3E Kludge + struct RecordHdr { + Int recordtype; + Long recordsize; + Int sequenceID; + // ** Inline these because they are + // ** actually kludges for the T3E + static int write(IEEEIO *ieeeio,RecordHdr &rec){ + int r=0; + // copy into buffer + if(ieeeio->swapbytes){ + char buffer[RecordHdrSize]; + IEEEIO::byteswapBuffer(&(rec.recordtype),buffer,1,4); + IEEEIO::byteswapBuffer(&(rec.recordsize),buffer+4,1,4); + IEEEIO::byteswapBuffer(&(rec.sequenceID),buffer+8,1,4); + r=ieeeio->write(buffer,RecordHdrSize); + } + else { +#ifdef T3E // data structures are not packed contiguously in memory + r+=ieeeio->write(&(rec.recordtype),4); + r+=ieeeio->write(&(rec.recordsize),4); + r+=ieeeio->write(&(rec.sequenceID),4); +#else + r=ieeeio->write(&rec,RecordHdrSize); + //printf("Wrote rechdr %u,%u,%u\n",rec.recordtype,rec.recordsize,rec.sequenceID); +#endif + } + return r; + } + static int read(IEEEIO *ieeeio,RecordHdr &rec){ + char buffer[RecordHdrSize]; + int r=ieeeio->read(buffer,RecordHdrSize); + if(ieeeio->swapbytes) + IEEEIO::byteswapBuffer(buffer,3,4);//3 elements of 4 bytes +#ifdef T3E // data structures are not packed contiguously in memory + // do it the stupid way first + // would be smarter to pack buffers really + ::bcopy(buffer,&(rec.recordtype),4); + ::bcopy(buffer+4,&(rec.recordsize),4); + ::bcopy(buffer+8,&(rec.sequenceID),4); +#else + ::bcopy(buffer,(char*)&rec,RecordHdrSize); +#endif + return r; + } + }; + +#define DataRecordHdrSize (4+4+4) // T3E Kludge + struct DataRecordHdr { + Long datasize; + Int numbertype; + Int rank; + // ** Inline these because they are + // ** actually kludges for the T3E + static int write(IEEEIO *ieeeio,DataRecordHdr &rec){ + int r=0; + // copy into buffer + if(ieeeio->swapbytes){ + char buffer[DataRecordHdrSize]; + IEEEIO::byteswapBuffer(&(rec.datasize),buffer,1,4); + IEEEIO::byteswapBuffer(&(rec.numbertype),buffer+4,1,4); + IEEEIO::byteswapBuffer(&(rec.rank),buffer+8,1,4); + r=ieeeio->write(buffer,DataRecordHdrSize); + } + else { +#ifdef T3E + r+=ieeeio->write(&(rec.datasize),4); + r+=ieeeio->write(&(rec.numbertype),4); + r+=ieeeio->write(&(rec.rank),4); +#else + r=ieeeio->write(&rec,DataRecordHdrSize); +#endif + } + return r; + } + static int read(IEEEIO *ieeeio,DataRecordHdr &rec){ + char buffer[DataRecordHdrSize]; + int r=ieeeio->read(buffer,DataRecordHdrSize); + if(ieeeio->swapbytes) + IEEEIO::byteswapBuffer(buffer,3,4);//3 elements of 4 bytes +#ifdef T3E + // do it the stupid way first + // would be smarter to pack buffers really + ::bcopy(buffer,&(rec.datasize),4); + ::bcopy(buffer+4,&(rec.numbertype),4); + ::bcopy(buffer+8,&(rec.rank),4); +#else + ::bcopy(buffer,(char*)&rec,DataRecordHdrSize); +#endif + return r; + } + }; +#define DataRecordHdr64Size (8+4+4) // T3E Kludge + struct DataRecordHdr64 { + Long8 datasize; + Int numbertype; + Int rank; + // ** Inline these because they are + // ** actually kludges for the T3E + static int write(IEEEIO *ieeeio,DataRecordHdr64 &rec){ + int r=0; + // copy into buffer + if(ieeeio->swapbytes){ + char buffer[DataRecordHdr64Size]; + IEEEIO::byteswapBuffer(&(rec.datasize),buffer,1,8); + IEEEIO::byteswapBuffer(&(rec.numbertype),buffer+8,1,4); + IEEEIO::byteswapBuffer(&(rec.rank),buffer+12,1,4); + r=ieeeio->write(buffer,DataRecordHdr64Size); + } + else { +#ifdef T3E + r+=ieeeio->write(&(rec.datasize),8); + r+=ieeeio->write(&(rec.numbertype),4); + r+=ieeeio->write(&(rec.rank),4); +#else + r=ieeeio->write(&rec,DataRecordHdr64Size); +#endif + } + return r; + } + static int read(IEEEIO *ieeeio,DataRecordHdr64 &rec){ + char buffer[DataRecordHdr64Size]; + int r=ieeeio->read(buffer,DataRecordHdr64Size); + if(ieeeio->swapbytes){ + IEEEIO::byteswapBuffer(buffer,1,8); + IEEEIO::byteswapBuffer(buffer+8,2,4);//2 elements of 4 bytes + } +#ifdef T3E + // do it the stupid way first + // would be smarter to pack buffers really + ::bcopy(buffer,&(rec.datasize),8); + ::bcopy(buffer+4,&(rec.numbertype),4); + ::bcopy(buffer+8,&(rec.rank),4); +#else + ::bcopy(buffer,(char*)&rec,DataRecordHdr64Size); +#endif + return r; + } + }; +#define AttributeRecordHdrSize (4+4+4) // T3E Kludge + struct AttributeRecordHdr { + Long datasize; + Int numbertype; + Int namesize; // attributes are named + // ** Inline these because they are + // ** actually kludges for the T3E + static int write(IEEEIO *ieeeio,AttributeRecordHdr &rec){ + int r=0; + // copy into buffer + if(ieeeio->swapbytes){ // pack a buffer + char buffer[AttributeRecordHdrSize]; + IEEEIO::byteswapBuffer(&(rec.datasize),buffer,1,4); + IEEEIO::byteswapBuffer(&(rec.numbertype),buffer+4,1,4); + IEEEIO::byteswapBuffer(&(rec.namesize),buffer+8,1,4); + r=ieeeio->write(buffer,RecordHdrSize); + } + else { +#ifdef T3E + r+=ieeeio->write(&(rec.datasize),4); + r+=ieeeio->write(&(rec.numbertype),4); + r+=ieeeio->write(&(rec.namesize),4); +#else + //printf("AttribRec::writing ds,nt,ns %d,%d,%d\n",rec.datasize,rec.numbertype,rec.namesize); + r = ieeeio->write(&rec,AttributeRecordHdrSize); + //printf("Wrote attribhdr %d,%d,%d\n",rec.datasize,rec.numbertype,rec.namesize); + //printf("\tr=%u\n",r); +#endif + } + return r; + } + static int read(IEEEIO *ieeeio,AttributeRecordHdr &rec){ + int r=0; + char buffer[AttributeRecordHdrSize]; + r=ieeeio->read(buffer,AttributeRecordHdrSize); + if(ieeeio->swapbytes) + IEEEIO::byteswapBuffer(buffer,3,4); +#ifdef T3E + ::bcopy(buffer,&(rec.datasize),4); + ::bcopy(buffer+4,&(rec.numbertype),4); + ::bcopy(buffer+8,&(rec.namesize),4); +#else + ::bcopy(buffer,(char*)&rec,AttributeRecordHdrSize); + //printf("AttribRec::reading ds,nt,ns %d,%d,%d\n",rec.datasize,rec.numbertype,rec.namesize); +#endif + return r; + } + }; +#define AttributeRecordHdr64Size (8+4+4) // T3E Kludge + struct AttributeRecordHdr64 { + Long8 datasize; + Int numbertype; + Int namesize; // attributes are named + // ** Inline these because they are + // ** actually kludges for the T3E + static int write(IEEEIO *ieeeio,AttributeRecordHdr64 &rec){ + int r=0; + // copy into buffer + if(ieeeio->swapbytes){ // pack a buffer + char buffer[AttributeRecordHdr64Size]; + IEEEIO::byteswapBuffer(&(rec.datasize),buffer,1,4); + IEEEIO::byteswapBuffer(&(rec.numbertype),buffer+4,1,4); + IEEEIO::byteswapBuffer(&(rec.namesize),buffer+8,1,4); + r=ieeeio->write(buffer,AttributeRecordHdr64Size); + } + else { +#ifdef T3E + r+=ieeeio->write(&(rec.datasize),4); + r+=ieeeio->write(&(rec.numbertype),4); + r+=ieeeio->write(&(rec.namesize),4); +#else + //printf("AttribRec::writing ds,nt,ns %d,%d,%d\n",rec.datasize,rec.numbertype,rec.namesize); + r = ieeeio->write(&rec,AttributeRecordHdr64Size); + //printf("Wrote attribhdr %d,%d,%d\n",rec.datasize,rec.numbertype,rec.namesize); + //printf("\tr=%u\n",r); +#endif + } + return r; + } + static int read(IEEEIO *ieeeio,AttributeRecordHdr64 &rec){ + int r=0; + char buffer[AttributeRecordHdr64Size]; + r=ieeeio->read(buffer,AttributeRecordHdr64Size); + if(ieeeio->swapbytes) + IEEEIO::byteswapBuffer(buffer,3,4); +#ifdef T3E + ::bcopy(buffer,&(rec.datasize),4); + ::bcopy(buffer+4,&(rec.numbertype),4); + ::bcopy(buffer+8,&(rec.namesize),4); +#else + ::bcopy(buffer,(char*)&rec,AttributeRecordHdr64Size); + //printf("AttribRec::reading ds,nt,ns %d,%d,%d\n",rec.datasize,rec.numbertype,rec.namesize); +#endif + return r; + } + }; + + struct RecRef { + RecordHdr rec; + Long8 offset; + // should have a cached flag to indicate if Attribs should be scanned for + //virtual ~RecRef(); + // ** Inline these because they are + // ** actually kludges for the T3E + }; + + struct AttribRef : public RecRef { + //FlexArray<char> name; + char name[64]; + AttribRef(); + AttribRef(AttribRef &src); + //virtual ~AttribRef(); + AttribRef &operator=(AttribRef &src); + // ** Inline these because they are + // ** actually kludges for the T3E + }; + + struct DataRef : public RecRef { + // should have a cached flag to indicate if Attribs should be scanned for + FlexArray<RecRef> annotations; + FlexArray<AttribRef> attributes; + Long8 end_offset; + DataRef(); + //virtual ~DataRef(); + DataRef(DataRef &src); + DataRef &operator=(DataRef &src); + }; +private: + friend class AttribRef; + friend class DataRef; + friend class FileHdr; + friend class RecordHdr; + friend class DataRecordHdr; + friend class AttributeRecordHdr; + friend class DataRecordHdr64; + friend class AttributeRecordHdr64; + // convenience utilities +#ifdef T3E + int ffioIsTrue(); +#endif + void initPosition(); + inline Long8 getPosition(){return this->lseek(0,L_INCR);} + void restart(); + int nextRecord(); + int nextDataRecord(); + inline Long8 getLength(){ return file_length; } + static void byteswapBuffer(void *buf,Long8 nelements,int elementsize); + static void byteswapBuffer(void *source,void *dest,Long8 nelements,int elementsize); + int writeFileHeader(); + int readFileHeader(); + void rebuildFileHeader(); + void appendRecordTable(); + void buildRecordTable(); + void clearChunk(int nbytes); + void openFile(CONST char *fname,IObase::AccessMode access,int swbytes); + // annotations don't need a header + // for c, size includes null terminator. + // must decrement size for f77 + //inline int write(int fid,void *data,int size); +protected: + FlexArray<DataRef> rec_table; + FlexArray<Int> chunkdims; + FileHdr file_header; + RecordHdr current_rec,current_data_rec; + DataRecordHdr current_dat; + Long8 current_rec_offset; // offset past the record header + Long8 stream_offset; // kludge to allow index cache to be turned off + Long8 current_dat_offset; // to datarec + int fid,datasetnumber,ndatasets,swapbytes,current_reserved_chunk; + int hasread,streaming,cur_type_size; + IEEEIO *masterfile; + int writebuffersize,writebuffercount; + char *writebuffer; + Long8 savedposition; + Long8 virtual_position,actual_position; + Long8 file_length; +protected: + inline int write(const void *data,size_t size); + inline void flush(); + inline Long8 lseek(Long8 len, int direction); + inline int read(void *data,size_t size); +public: + //------------------------core stuff..................... + enum ExtendedAccessMode {Read=0,Write=1,Create=1,Append=2,SharedRead=4}; + + IObase::AccessMode mode(ExtendedAccessMode amode) + { + switch(amode){ + case Read: + return IObase::Read; + case Write: + return IObase::Write; + case Append: + return IObase::Append; + default: + return IObase::Read; + } + } + // the IEEEIO:: commented out to satisfy Microsoft Compiler + IEEEIO(CONST char *fname, ExtendedAccessMode access,int swbytes=0); + IEEEIO(CONST char *fname, AccessMode access,int swbytes=0); + IEEEIO(IEEEIO *file); // read-only dup an existing open file + virtual ~IEEEIO(); + virtual int isValid(); + // could use overloading to differentiate type here... (but I'm going simple) + virtual int write(IObase::DataType typeID,int rank,CONST int *dims,void *data); + virtual int readInfo(IObase::DataType &typeID,int &rank,int *dims,int maxdims=3); + virtual int read(void *data); + //virtual int readChunk(int dims,int origin,int stride,void *data)=0; + virtual int seek(int dataset_index); + virtual int nDatasets(); + + virtual int writeAnnotation(CONST char *annotation); + virtual int readAnnotationInfo(int number,int &length); // returns length (-1 if none left) + virtual int readAnnotation(int number,char *annotation,int maxsize=128); + virtual int nAnnotations(); + + virtual int writeAttribute(CONST char *name,IObase::DataType typeID,Long length,void *data); + // returns number + virtual int readAttributeInfo(int number,char *name,IObase::DataType &typeID,Long &nelem,int maxnamelen=128); + virtual int readAttributeInfo(CONST char *name,IObase::DataType &typeID,Long &nelem); // returns number + virtual int readAttribute(int number,void *data); + // virtual Long readAttribute(CONST char *name,void *data); + virtual int nAttributes(); + + //-----------------Chunking Utilities.................. + virtual int reserveChunk(IObase::DataType typeID,int rank,CONST int *dims); + virtual int writeChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data); + virtual int readChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data); + // Streaming interface is for support of PANDA, Sockets etc.. + virtual int reserveStream(IObase::DataType typeID,int rank,CONST int *dims); + virtual int writeStream(void *data,int length); + virtual int readStream(void *data,int length); + virtual int pause(); + virtual int resume(); + void bufferOn(long size=-1); + void bufferOff(); + //---------------------MPIO Experimental Methods------------ + void getFilename(char *fn,int maxlen=256); + int reserveStream(IObase::DataType typeID,int rank,CONST int *dims,Long8 &offset); + int writeStream(void *data,int length,Long8 offset); +}; +/* +int bcopy(char *src,char *dst,int len){ + // copying bytes on the DEC Alpha processor can be costly due + // to the penalty of non-aligned memory accesses. This tries + // to align the copys. + + You can use the program copyperf to see how bcopy() improves performance + You must build copyperf separately using + gmake copyperf + + The following will test copy a 64meg buffer 1 time. + copyperf 64m + The following will test copy a 32k buffer 1000 times + copyperf 32k 1000 + The performance differences are 4-to-1 or greater in favor of bcopy(). +} +*/ +int IEEEIO::write(const void *data,size_t size){ + //puts("***********write()"); +#ifdef T3E + static int ffio_inline_true=0; + if(ffio_inline_true >= 0){ + // do this test only once on first write + // this just gives someone a clue that they've done the + // wrong thing when they compiled +#ifdef FFIO + if(!ffioIsTrue()){ + fprintf(stderr,"Error!!! Inconsistent FFIO flags on a T3E!\n"); + fprintf(stderr,"Your libraries have been compiled without -DFFIO, but your executable has been compled and linked with them with -DFFIO.\n"); + fprintf(stderr,"\t*****Please either rebuild the IEEEIO library with -DFFIO or *remove* -DFFIO from your own build.******\n"); + } +#else + if(ffioIsTrue()){ + fprintf(stderr,"Error!!! Inconsistent FFIO flags on a T3E!\n"); + fprintf(stderr,"Your libraries have been compiled with -DFFIO, but your executable has been compled and linked with them without -DFFIO\n"); + fprintf(stderr,"\t*****Please recompile with -DFFIO******\n"); + } +#endif + ffio_inline_true = -1; + } +#endif + if(!writebuffer){ + register Long8 r=0; +#ifdef FFIO + r = ::ffwrite(fid,data,size); +#else + r = ::write(fid,data,size); +#endif + if(r>0) actual_position += r; + virtual_position = actual_position; + // if(r>0) virtual_position = actual_position = (actual_position+r); + if(virtual_position>file_length) file_length = virtual_position; + return r; + } + // otherwise, do a buffered write + int retval=0; + char *datap = (char *)data; + if(writebuffercount>0){ + // copy as much as you can to the writebuffer + // should use bcopy... its a whole lot faster!!! + Long8 copysize = (size>(size_t)(writebuffersize-writebuffercount))?(writebuffersize-writebuffercount):size; + bcopy(datap,writebuffer+writebuffercount,copysize); + writebuffercount += copysize; + virtual_position += copysize; + retval += copysize; + if(writebuffercount>=writebuffersize) + this->flush(); // dump immediately (updates both virtual and actual pos) + size-=copysize; datap+=copysize; + if(size<=0) { + // virtual_position = actual_position + writebuffercount; + if(virtual_position>file_length) file_length=virtual_position; + return retval; + } + } + // at this point size>0 and writebuffercount=0 + if(size<=0 || writebuffercount!=0){ + printf("***Write Failed: size=%u writebuffercount=%u\n", + (unsigned int)size,writebuffercount); + } + if(size<(size_t)writebuffersize){// store to buffer (size>0 is implicit in loop) + bcopy(datap,writebuffer+writebuffercount,size); + writebuffercount += size; + virtual_position += size; + retval += size; + } + else { + register Long8 r=0; + // its larger than buffer, so bypass it and + // write it directly to the disk. +#ifdef FFIO + r = ::ffwrite(fid,datap,size); +#else + r = ::write(fid,datap,size); +#endif + actual_position += r; + virtual_position = actual_position; // essentially equiv to flush + if(r>0) retval+=r; + } + // double-check virtual position + // virtual_position = actual_position + writebuffercount; + if(virtual_position>file_length) file_length = virtual_position; + return retval; +} +void IEEEIO::flush(){ + register Long8 r=0; + if(writebuffercount){ +#ifdef FFIO + r = ::ffwrite(fid,writebuffer,writebuffercount); +#else + r = ::write(fid,writebuffer,writebuffercount); +#endif + } + writebuffercount=0; + if((r+actual_position)!=virtual_position){ + fprintf(stderr,"IEEEIO::flush() : inconsistent file positions! r=%ld v=%ld a=%ld\n", + r,virtual_position,actual_position); + } + actual_position = virtual_position; + if(virtual_position>file_length) file_length=virtual_position; +} +Long8 IEEEIO::lseek(Long8 len, int direction){ + // compute new pos + register Long8 npos=0; + // can seek beyond end of file + switch(direction){ + case L_XTND: /* should do special case for 0 len */ + npos = file_length + len; + break; + case L_SET: + npos = len; + break; + case L_INCR:; + npos = virtual_position + len; + break; + } + if(npos>file_length) + file_length = npos; + if(virtual_position != npos) { + if(writebuffer) + this->flush(); // must flush current buffer contents + // printf("Actually seeking from %ld to %ld\n",virtual_position,npos); + virtual_position = actual_position = npos; +#ifdef FFIO + // if(!writebuffer) + return ::ffseek(fid,npos,L_SET); +#else + // if(!writebuffer) +#ifdef SGI + return ::lseek64(fid,npos,L_SET); +#else + return ::lseek(fid,npos,L_SET); +#endif +#endif + } + return npos; // otherwise no change required +} +/* Will eventually want to buffer the reads as well... */ +int IEEEIO::read(void *data,size_t size){ + register int r=0; + if(writebuffercount>0) + flush(); +#ifdef FFIO + r = ::ffread(fid,data,size); +#else + r = ::read(fid,data,size); +#endif + if(r>0) virtual_position += r; + actual_position=virtual_position; + // can't read past end of file of course so no need to update file_length; + return r; +} + + +//==========F77 Interface============= +#define f_ieee_open F77NAME(ieee_open_,ieee_open,IEEE_OPEN) +#define f_ieee_openr F77NAME(ieee_openr_,ieee_openr,IEEE_OPENR) +#define f_ieee_openw F77NAME(ieee_openw_,ieee_openw,IEEE_OPENW) +#define f_ieee_opena F77NAME(ieee_opena_,ieee_opena,IEEE_OPENA) +#define f_ieee_bufon F77NAME(ieee_bufon_,ieee_bufon,IEEE_BUFON) +#define f_ieee_bufoff F77NAME(ieee_bufoff_,ieee_bufoff,IEEE_BUFOFF) +extern "C"{ +#ifdef CRAY // Note: This isn't really implemented yet... +#include <fortran.h> + Long8 f_ieee_open (_fcd fcfilename,_fcd fcaccessmode); + Long8 f_ieee_openr (_fcd fcfilename); + Long8 f_ieee_openw (_fcd fcfilename); + Long8 f_ieee_opena (_fcd fcfilename); +#else + Long8 f_ieee_open (char *filename,char *accessmode,int namelen,int accesslength); + Long8 f_ieee_openr (char *filename,int namelen); + Long8 f_ieee_openw (char *filename,int namelen); // actually IObase::Create + Long8 f_ieee_opena (char *filename,int namelen); +#endif + void f_ieee_bufon (Long8 *fileID,int *bufsize); + void f_ieee_bufoff (Long8 *fileID); + //=====================ANSI C interface +#include "IEEEIO.h" // ANSI C interface + } + +#endif |