diff --git a/src/config.hpp b/src/config.hpp index 014f013..28f8bcd 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -53,8 +53,8 @@ namespace CosmoTool Exception(const char *mess = 0) : msg(mess) {} - const char *getMessage() const { return msg; }; - virtual const char *what() const throw () { return msg; }; + const char *getMessage() const { return msg != 0 ? msg : "No message"; }; + virtual const char *what() const throw () { return msg != 0 ? msg : "What 'what' ?"; }; private: const char *msg; @@ -104,6 +104,13 @@ namespace CosmoTool EndOfFileException(const char *mess = 0) : Exception(mess) {} }; + + class FilesystemFullException: public Exception + { + public: + FilesystemFullException(const char *mess = 0) + : Exception(mess) {} + }; }; #endif diff --git a/src/fortran.cpp b/src/fortran.cpp index 285d100..4ca7254 100644 --- a/src/fortran.cpp +++ b/src/fortran.cpp @@ -155,3 +155,168 @@ int64_t UnformattedRead::readInt64() return a.i; } + +//// UnformattedWrite + +UnformattedWrite::UnformattedWrite(const string& fname) + throw(NoSuchFileException) +{ + f = new ofstream(fname.c_str()); + if (!*f) + throw NoSuchFileException(); + + swapOrdering = false; + cSize = Check_32bits; + checkPointRef = checkPointAccum = 0; +} + +UnformattedWrite::UnformattedWrite(const char *fname) + throw(NoSuchFileException) +{ + f = new ofstream(fname); + if (!*f) + throw NoSuchFileException(); + swapOrdering = false; + cSize = Check_32bits; + checkPointRef = checkPointAccum = 0; +} + + +UnformattedWrite::~UnformattedWrite() +{ + delete f; +} + +// Todo implement primitive description +void UnformattedWrite::setOrdering(Ordering o) +{ + if (o == LittleEndian) + { + } +} + +void UnformattedWrite::setCheckpointSize(CheckpointSize cs) +{ + cSize = cs; +} + +void UnformattedWrite::beginCheckpoint() + throw (InvalidUnformattedAccess,FilesystemFullException) +{ + if (checkPointAccum != 0) + throw InvalidUnformattedAccess(); + + checkPointRef = f->tellp(); + if (cSize == Check_32bits) + writeInt32(0); + else + writeInt64(0); + + checkPointAccum = 0; + + if (!*f) + throw FilesystemFullException(); +} + +void UnformattedWrite::endCheckpoint() + throw (InvalidUnformattedAccess,FilesystemFullException) +{ + if (checkPointAccum == 0) + throw InvalidUnformattedAccess(); + + ostream::streampos curPos = f->tellp(); + + int64_t deltaPos = curPos-checkPointRef; + + deltaPos -= (cSize == Check_32bits) ? 4 : 8; + // This is a sanity check. + if (checkPointAccum != deltaPos) + throw InvalidUnformattedAccess(); + + uint64_t saveAccum = checkPointAccum; + + f->seekp(checkPointRef); + if (cSize == Check_32bits) + writeInt32(saveAccum); + else + writeInt64(saveAccum); + + f->seekp(curPos); + if (cSize == Check_32bits) + writeInt32(saveAccum); + else + writeInt64(saveAccum); + + checkPointAccum = checkPointRef = 0; +} + +void UnformattedWrite::writeOrderedBuffer(void *buffer, int size) + throw (FilesystemFullException) +{ + f->write((char *)buffer, size); + + if (swapOrdering) + { + char *cb = (char *)buffer; + for (int i = 0; i < size/2; i++) + swap(cb[i], cb[size-i-1]); + } + checkPointAccum += size; + + if (!*f) + throw FilesystemFullException(); +} + +void UnformattedWrite::writeReal64(double d) + throw (FilesystemFullException) +{ + union + { + char b[8]; + double d; + } a; + + a.d = d; + + writeOrderedBuffer(&a, 8); +} + +void UnformattedWrite::writeReal32(float f) + throw (FilesystemFullException) +{ + union + { + char b[4]; + float f; + } a; + + a.f = f; + + writeOrderedBuffer(&a, 4); +} + +void UnformattedWrite::writeInt32(int32_t i) + throw (FilesystemFullException) +{ + union + { + char b[4]; + int32_t i; + } a; + + a.i = i; + writeOrderedBuffer(&a, 4); +} + +void UnformattedWrite::writeInt64(int64_t i) + throw (FilesystemFullException) +{ + union + { + char b[8]; + int64_t i; + } a; + + a.i = i; + writeOrderedBuffer(&a, 8); +} diff --git a/src/fortran.hpp b/src/fortran.hpp index 361978e..6c5a52e 100644 --- a/src/fortran.hpp +++ b/src/fortran.hpp @@ -13,7 +13,7 @@ namespace CosmoTool { }; - class UnformattedRead + class FortranTypes { public: enum Ordering { @@ -23,6 +23,11 @@ namespace CosmoTool enum CheckpointSize { Check_32bits, Check_64bits }; + }; + + class UnformattedRead: public FortranTypes + { + public: UnformattedRead(const std::string& fname) throw (NoSuchFileException); @@ -59,6 +64,45 @@ namespace CosmoTool throw (InvalidUnformattedAccess); }; + class UnformattedWrite: public FortranTypes + { + public: + + UnformattedWrite(const std::string& fname) + throw (NoSuchFileException); + UnformattedWrite(const char *fname) + throw (NoSuchFileException); + ~UnformattedWrite(); + + // Todo implement primitive description + void setOrdering(Ordering o); + void setCheckpointSize(CheckpointSize cs); + + void beginCheckpoint() + throw (FilesystemFullException,InvalidUnformattedAccess); + void endCheckpoint() + throw (FilesystemFullException,InvalidUnformattedAccess); + + void writeReal64(double d) + throw (FilesystemFullException); + void writeReal32(float f) + throw (FilesystemFullException); + void writeInt32(int32_t i) + throw (FilesystemFullException); + void writeInt64(int64_t i) + throw (FilesystemFullException); + + protected: + bool swapOrdering; + CheckpointSize cSize; + std::streamoff checkPointRef; + uint64_t checkPointAccum; + std::ofstream *f; + + void writeOrderedBuffer(void *buffer, int size) + throw(FilesystemFullException); + }; + }; #endif