// Copyright Marek Kurdej 2010 - 2012. // Distributed under the UTC Heudiasyc Pacpus License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at // http://www.hds.utc.fr/~kurdejma/LICENSE_1_0.txt #ifndef DBITEFILE_H #define DBITEFILE_H #include #include #include #include "kernel/cstdint.h" #include "kernel/hdfile_header_t.h" #include "kernel/road_time.h" namespace pacpus { struct VariableDataSizeTag {}; extern VariableDataSizeTag VariableDataSize; struct ReadModeTag {}; extern ReadModeTag ReadMode; struct WriteModeTag {}; extern WriteModeTag WriteMode; struct DiagnoseModeTag {}; extern DiagnoseModeTag DiagnoseMode; class DbiteFile { public: enum ReadDirection { ReadForward , ReadBackward }; /// @throws nothing DbiteFile(); /// @throws nothing ~DbiteFile(); /// Opens the file in read mode. /// /// @throws DbiteException on I/O error (read: cannot open the file) /// @throws DbiteException on invalid file signature void open(const std::string & path, ReadModeTag); /// Opens the file in write mode using default settings. /// It is necessary to set data type and data size afterwards. /// /// @throws DbiteException on I/O error (write: cannot write the header) /// @see setRecordSize /// @see setType void open(const std::string & path, WriteModeTag); /// Opens the file in write mode using given data type and data size. /// /// @code /// DbiteFile dbt; /// dbt.open(path, WriteMode, type, dataSize); /// @endcode /// is equivalent to /// @code /// DbiteFile dbt; /// dbt.open(path, WriteMode) /// dbt.setRecordSize(dataSize); /// dbt.setType(type); /// @endcode /// /// @throws DbiteException on I/O error (write: cannot write the header) void open(const std::string & path, WriteModeTag, hdfile_header_t::DataTypeT type, hdfile_header_t::DataSizeT dataSize); /// Opens the file in write mode using given data type and variable data size. /// /// @code /// DbiteFile dbt; /// dbt.open(path, WriteMode, type, VariableDataSize); /// @endcode /// is equivalent to /// @code /// DbiteFile dbt; /// dbt.open(path, WriteMode) /// dbt.setRecordSize(VariableDataSize); /// dbt.setType(type); /// @endcode /// /// @throws DbiteException on I/O error (write: cannot write the header) void open(const std::string & path, WriteModeTag, hdfile_header_t::DataTypeT type, VariableDataSizeTag); /// Tries to diagnose and repair the file. /// @throws DbiteException on I/O error (write: cannot write the header) //void open(const std::string & path, DiagnoseModeTag); // TODO /// @throws nothing void close(); /// @throws nothing bool isOpen() const; /// @throws DbiteException when file is not open void goToFileBegin(); /// @throws DbiteException when file is not open void goToFileEnd(); /// @throws DbiteException when file is not open void goToDataBegin(); /// @throws nothing const std::string & getPath() const; /// @throws nothing std::string getSignature() const; /// @throws nothing hdfile_header_t::DataTypeT getType() const; /// @throws nothing hdfile_header_t::VersionT getVersion() const; /// @throws nothing hdfile_header_t::DataOffsetT getDataOffset() const; /// @throws nothing hdfile_header_t::DataSizeT getRecordSize() const; // FIXME: file size should be 64-bit long, have to change the hdfile_header_t structure as well /// @throws nothing hdfile_header_t::FileSizeT getFileSize() const; int64_t getRealFileSize(); /// @throws nothing road_time_t getTimeMin() const; /// @throws nothing road_time_t getTimeMax() const; /// @throws nothing hdfile_header_t::RecordCountT getRecordCount() const; /// @throws nothing void setType(hdfile_header_t::DataTypeT type); /// @throws nothing void setRecordSize(hdfile_header_t::DataSizeT recordSize); /// @throws nothing void setRecordSize(VariableDataSizeTag tag); /// @throws nothing void setTimeMin(road_time_t time); /// @throws nothing void setTimeMax(road_time_t time); /// @throws nothing void setRecordCount(hdfile_header_t::RecordCountT recourdCount); /// prints header /// @throws nothing operator std::string(); /// @throws nothing bool isVariableDataSize() const; /// @throws DbiteException on I/O error bool readRecord(size_t recordIndex, road_time_t & time, road_timerange_t & timeRange, char * data); /// @throws DbiteException on I/O error bool readRecord(size_t recordIndex, road_time_t & time, road_timerange_t & timeRange, char * data, size_t & dataSize); /// @throws DbiteException on I/O error bool readRecord(road_time_t & time, road_timerange_t & timeRange, char * data, const ReadDirection & direction = ReadForward); /// @throws DbiteException on I/O error bool readRecord(road_time_t & time, road_timerange_t & timeRange, char * data, size_t & dataSize, const ReadDirection & direction = ReadForward); /// Reads only time and time range and moves the file position to the beginning of the next record /// @throws DbiteException on I/O error bool readRecord(road_time_t & time, road_timerange_t & timeRange, const ReadDirection & direction = ReadForward); /// @throws DbiteException on I/O error bool writeRecord(const road_time_t & time, const road_timerange_t & timeRange, const char * data, const size_t dataSize); /// @throws DbiteException on I/O error template bool writeRecord(const road_time_t & time, const road_timerange_t & timeRange, const T* data); /// @throws nothing bool isEndOfFile(); private: /// @throws nothing void setPath(const std::string & path); /// @throws nothing void setVersion(hdfile_header_t::VersionT version); /// @throws nothing void setDataOffset(hdfile_header_t::DataOffsetT dataOffset); /// @throws nothing void setFileSize(hdfile_header_t::FileSizeT fileSize); void initializeHeader(); bool isSignatureCorrect() const; void setSignature(); const hdfile_header_t & getHeader() const; hdfile_header_t & header(); void writeHeader(); void openWriteMode(const std::string & path); void openWriteMode(const std::string & path, hdfile_header_t::DataTypeT type); void closeDbite(); void closeDbite(ReadModeTag); void closeDbite(WriteModeTag); void readHeader(); void verifyHeader(); /// @throws DbiteException when file is not open int64_t getReadPosition(); /// @throws DbiteException when file is not open int64_t getWritePosition(); /// @throws DbiteException when file is not open void setReadPosition(int64_t offset, std::ios_base::seekdir direction); /// @throws DbiteException when file is not open void setReadPosition(int64_t position); /// @throws DbiteException when file is not open void setWritePosition(int64_t offset, std::ios_base::seekdir direction); /// @throws DbiteException when file is not open void setWritePosition(int64_t position); /// @throws DbiteException on I/O error bool readRecordNoBufferCheck(road_time_t & time, road_timerange_t & timeRange, char * data, size_t & dataSize, const ReadDirection & direction); /// @throws DbiteException on I/O error bool readRecordForward(road_time_t & time, road_timerange_t & timeRange, char * data, size_t & dataSize); /// @throws DbiteException on I/O error bool readRecordBackward(road_time_t & time, road_timerange_t & timeRange, char * data, size_t & dataSize); /// @throws DbiteException on I/O error void read(std::fstream::char_type * s, std::streamsize n); /// @throws DbiteException on I/O error void write(const std::fstream::char_type * s, std::streamsize n); /// @throws DbiteException when file is not open void checkFileOpen(); private: std::fstream mFile; hdfile_header_t mHeader; bool mIsWriting; std::string mPath; bool mIsVariableRecordSize; }; template bool DbiteFile::writeRecord(const road_time_t & time, const road_timerange_t & timeRange, const T* data) { return writeRecord(time, timeRange, (const char*) data, sizeof(T)); } } // namespace pacpus #endif // DBITEFILE_H