From 55fa6a9ca0177c110dd46bf2ca411ac10a5547a8 Mon Sep 17 00:00:00 2001 From: ihedvall <92839244+ihedvall@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:09:35 +0100 Subject: [PATCH] Changed the C file interface to C++ generic stream buffer interface. Note that this is a major change. --- CMakeLists.txt | 2 +- include/mdf/ichannel.h | 2 +- include/mdf/idatagroup.h | 2 +- include/mdf/itimestamp.h | 3 +- include/mdf/mdffactory.h | 4 +- include/mdf/mdffile.h | 10 +- include/mdf/mdfreader.h | 43 +++- include/mdf/mdfwriter.h | 6 +- include/mdf/zlibutil.h | 8 +- mdflib/src/at4block.cpp | 88 +++---- mdflib/src/at4block.h | 6 +- mdflib/src/ca4block.cpp | 100 ++++---- mdflib/src/ca4block.h | 10 +- mdflib/src/cc3block.cpp | 84 +++--- mdflib/src/cc3block.h | 4 +- mdflib/src/cc4block.cpp | 80 +++--- mdflib/src/cc4block.h | 4 +- mdflib/src/cd3block.cpp | 17 +- mdflib/src/cd3block.h | 2 +- mdflib/src/ce3block.cpp | 22 +- mdflib/src/ce3block.h | 2 +- mdflib/src/cg3block.cpp | 96 +++---- mdflib/src/cg3block.h | 14 +- mdflib/src/cg4block.cpp | 156 ++++++------ mdflib/src/cg4block.h | 22 +- mdflib/src/ch4block.cpp | 36 +-- mdflib/src/ch4block.h | 4 +- mdflib/src/channelobserver.cpp | 20 +- mdflib/src/channelobserver.h | 20 +- mdflib/src/cn3block.cpp | 100 ++++---- mdflib/src/cn3block.h | 4 +- mdflib/src/cn4block.cpp | 194 +++++++------- mdflib/src/cn4block.h | 14 +- mdflib/src/datablock.cpp | 55 ++-- mdflib/src/datablock.h | 10 +- mdflib/src/datalistblock.cpp | 77 +++--- mdflib/src/datalistblock.h | 12 +- mdflib/src/dbchelper.cpp | 4 +- mdflib/src/dg3block.cpp | 104 ++++---- mdflib/src/dg3block.h | 12 +- mdflib/src/dg4block.cpp | 133 +++++----- mdflib/src/dg4block.h | 22 +- mdflib/src/di4block.cpp | 8 +- mdflib/src/di4block.h | 4 +- mdflib/src/dl4block.cpp | 42 +-- mdflib/src/dl4block.h | 4 +- mdflib/src/dt3block.cpp | 14 +- mdflib/src/dt3block.h | 6 +- mdflib/src/dt4block.cpp | 20 +- mdflib/src/dt4block.h | 8 +- mdflib/src/dv4block.cpp | 8 +- mdflib/src/dv4block.h | 4 +- mdflib/src/dz4block.cpp | 93 ++++--- mdflib/src/dz4block.h | 16 +- mdflib/src/ev4block.cpp | 71 +++--- mdflib/src/ev4block.h | 4 +- mdflib/src/fh4block.cpp | 28 +- mdflib/src/fh4block.h | 4 +- mdflib/src/hd3block.cpp | 97 +++---- mdflib/src/hd3block.h | 10 +- mdflib/src/hd4block.cpp | 82 +++--- mdflib/src/hd4block.h | 14 +- mdflib/src/hl4block.cpp | 28 +- mdflib/src/hl4block.h | 4 +- mdflib/src/ichannel.cpp | 26 +- mdflib/src/ichannelarray.cpp | 6 +- mdflib/src/idatagroup.cpp | 2 +- mdflib/src/idblock.cpp | 68 +++-- mdflib/src/idblock.h | 6 +- mdflib/src/ld4block.cpp | 20 +- mdflib/src/ld4block.h | 2 +- mdflib/src/mdf3file.cpp | 39 ++- mdflib/src/mdf3file.h | 10 +- mdflib/src/mdf3timestamp.cpp | 6 +- mdflib/src/mdf3timestamp.h | 4 +- mdflib/src/mdf3writer.cpp | 12 +- mdflib/src/mdf3writer.h | 2 +- mdflib/src/mdf4file.cpp | 53 ++-- mdflib/src/mdf4file.h | 14 +- mdflib/src/mdf4timestamp.cpp | 26 +- mdflib/src/mdf4timestamp.h | 4 +- mdflib/src/mdf4writer.cpp | 45 ++-- mdflib/src/mdf4writer.h | 6 +- mdflib/src/mdfblock.cpp | 352 ++++++++++++++++++++++++-- mdflib/src/mdfblock.h | 251 ++++++++++++++---- mdflib/src/mdfconverter.cpp | 26 +- mdflib/src/mdfconverter.h | 4 +- mdflib/src/mdfreader.cpp | 161 ++++++++---- mdflib/src/mdfwriter.cpp | 52 ++-- mdflib/src/pr3block.cpp | 33 +-- mdflib/src/pr3block.h | 7 +- mdflib/src/rd4block.cpp | 8 +- mdflib/src/rd4block.h | 4 +- mdflib/src/readcache.cpp | 43 ++-- mdflib/src/readcache.h | 6 +- mdflib/src/ri4block.cpp | 8 +- mdflib/src/ri4block.h | 4 +- mdflib/src/rv4block.cpp | 9 +- mdflib/src/rv4block.h | 4 +- mdflib/src/sd4block.cpp | 14 +- mdflib/src/sd4block.h | 6 +- mdflib/src/si4block.cpp | 41 +-- mdflib/src/si4block.h | 4 +- mdflib/src/sr3block.cpp | 36 ++- mdflib/src/sr3block.h | 6 +- mdflib/src/sr4block.cpp | 33 ++- mdflib/src/sr4block.h | 6 +- mdflib/src/tr3block.cpp | 31 +-- mdflib/src/tr3block.h | 4 +- mdflib/src/tx3block.cpp | 38 +-- mdflib/src/tx3block.h | 8 +- mdflib/src/tx4block.cpp | 36 ++- mdflib/src/tx4block.h | 6 +- mdflib/src/zlibutil.cpp | 85 +++---- mdflib_test/CMakeLists.txt | 4 +- mdflib_test/src/testiostream.cpp | 117 +++++++++ mdflib_test/src/testmdfblock.cpp | 115 +++++++++ mdflib_test/src/testmdffile.cpp | 7 +- mdflib_test/src/testread.cpp | 72 ++++++ mdflib_test/src/testzlib.cpp | 39 +-- mdflibrary/src/MdfFile.cpp | 4 +- mdflibrary/src/mdflibrary.cpp | 4 +- mdflibrary_test_net/MdfLibraryTest.cs | 4 + script/boost.cmake | 7 +- vcpkg.json | 1 + 125 files changed, 2546 insertions(+), 1682 deletions(-) create mode 100644 mdflib_test/src/testiostream.cpp create mode 100644 mdflib_test/src/testmdfblock.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ab0a337..71efc09d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,7 +87,7 @@ if((CMAKE_BUILD_TYPE MATCHES "^[Rr]elease") AND MDF_BUILD_DOC) set(DOXYGEN_RECURSIVE NO) set(DOXYGEN_REPEAT_BRIEF NO) set(DOXYGEN_PROJECT_NAME "MDF Lib") - set(DOXYGEN_PROJECT_NUMBER "2.2") + set(DOXYGEN_PROJECT_NUMBER "2.3") set(DOXYGEN_HTML_EXTRA_STYLESHEET doxygen/utillib.css) set(DOXYGEN_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/docs/manual) doxygen_add_docs( diff --git a/include/mdf/ichannel.h b/include/mdf/ichannel.h index 094ee4c0..dd4c9ab6 100644 --- a/include/mdf/ichannel.h +++ b/include/mdf/ichannel.h @@ -480,7 +480,7 @@ class IChannel : public IBlock { static bool GetVirtualSample(uint64_t sample, V& value) { // No need for array index here. Array is weird usage for virtual channels // as the channel value = sample. - value = static_cast(sample); + value = static_cast( static_cast(sample) ); return true; } diff --git a/include/mdf/idatagroup.h b/include/mdf/idatagroup.h index 199a14bb..f408a906 100644 --- a/include/mdf/idatagroup.h +++ b/include/mdf/idatagroup.h @@ -82,7 +82,7 @@ class IDataGroup : public IBlock { /** \brief Detaches all observers from the measurement. */ void DetachAllSampleObservers() const; /** \brief Notifies the observer that a new sample record have been read.*/ - bool NotifySampleObservers(size_t sample, uint64_t record_id, + bool NotifySampleObservers(uint64_t sample, uint64_t record_id, const std::vector& record) const; /** \brief Clear all temporary sample and data buffers. diff --git a/include/mdf/itimestamp.h b/include/mdf/itimestamp.h index 82f0c15d..db0046d5 100644 --- a/include/mdf/itimestamp.h +++ b/include/mdf/itimestamp.h @@ -79,8 +79,7 @@ class LocalTimestamp : public ITimestamp { [[nodiscard]] uint64_t GetUtcTimeNs() const override; private: - uint64_t local_timestamp_; ///< The local timestamp in nanoseconds, with - ///< timezone and DST offset. + uint64_t local_timestamp_; ///< The local timestamp in nanoseconds, with timezone and DST offset. int16_t timezone_offset_min_ = 0; ///< The timezone offset in minutes. int16_t dst_offset_min_ = 0; ///< The daylight saving time offset in minutes. }; diff --git a/include/mdf/mdffactory.h b/include/mdf/mdffactory.h index 5d01a95c..a0019a16 100644 --- a/include/mdf/mdffactory.h +++ b/include/mdf/mdffactory.h @@ -51,12 +51,12 @@ class MdfFactory { public: /** \brief Creates an MDF writer object. */ static std::unique_ptr CreateMdfWriter(MdfWriterType type); - /** \brief Create an MDF reader object.*/ + /** \brief Create an MDF file object.*/ static std::unique_ptr CreateMdfFile(MdfFileType type); /** \brief Creates an MDF writer object. */ static MdfWriter* CreateMdfWriterEx(MdfWriterType type); - /** \brief Create an MDF reader object.*/ + /** \brief Create an MDF file object.*/ static MdfFile* CreateMdfFileEx(MdfFileType type); /** \brief Sets the log function. */ diff --git a/include/mdf/mdffile.h b/include/mdf/mdffile.h index d82e4056..701227e8 100644 --- a/include/mdf/mdffile.h +++ b/include/mdf/mdffile.h @@ -143,7 +143,7 @@ class MdfFile { * read in any other information as measurement information. * @param file Pointer to an opened file. */ - virtual void ReadHeader(std::FILE* file) = 0; + virtual void ReadHeader(std::streambuf& buffer) = 0; /** \brief Reads the measurement information about the file. * @@ -154,7 +154,7 @@ class MdfFile { * * @param file Pointer to an opened file. */ - virtual void ReadMeasurementInfo(std::FILE* file) = 0; + virtual void ReadMeasurementInfo(std::streambuf& buffer) = 0; /** \brief Reads in all expect raw data from the file. * @@ -167,7 +167,7 @@ class MdfFile { * @param file Pointer to an opened file. */ virtual void - ReadEverythingButData(std::FILE* file) = 0; + ReadEverythingButData(std::streambuf& buffer) = 0; /** \brief Saves all blocks onto the file. * @@ -178,7 +178,7 @@ class MdfFile { * @param file Pointer to an open file. * @return True on success. */ - virtual bool Write(std::FILE* file) = 0; + virtual bool Write(std::streambuf& buffer) = 0; /** \brief Display name of the file. * @@ -211,7 +211,7 @@ class MdfFile { void FileName(const std::string& filename); /** \brief Sets the finalize state for the file. */ - virtual void IsFinalized(bool finalized, std::FILE* file, + virtual void IsFinalized(bool finalized, std::streambuf& buffer, uint16_t standard_flags, uint16_t custom_flags) = 0; /** \brief Returns true if the file is finalized. */ [[nodiscard]] virtual bool IsFinalized(uint16_t& standard_flags, diff --git a/include/mdf/mdfreader.h b/include/mdf/mdfreader.h index 8aea5635..467f1eb2 100644 --- a/include/mdf/mdfreader.h +++ b/include/mdf/mdfreader.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "mdf/ichannelobserver.h" #include "mdf/mdffile.h" @@ -67,9 +68,18 @@ void CreateChannelObserverForDataGroup(const IDataGroup& data_group, */ class MdfReader { public: - explicit MdfReader( - const std::string& filename); ///< Constructor that opens the file and - ///< read ID and HD block. + /** \brief Constructor for readers using an external file. + * + * This constructor is used when reading from an external file. The other + * way of reading from a C++ stream buffer. The latter is more complicated + * but more generic as it support environment without a file block + * storage. + * + * @param filename Full file path to the input file. + */ + explicit MdfReader(std::string filename); + + explicit MdfReader(std::shared_ptr& buffer); virtual ~MdfReader(); ///< Destructor that close any open file and destructs. MdfReader() = delete; @@ -118,14 +128,21 @@ class MdfReader { [[nodiscard]] std::string ShortName() const; ///< Returns the file name without paths. - bool Open(); ///< Opens the file stream for reading. + /** \brief Opens the internal stream buffer. + * + * Normally the stream buffer is an ordinary file but the use may also + * attach a generic C++ stream + * @return True if the stream was opened. + */ + [[nodiscard]] bool Open(); + [[nodiscard]] bool IsOpen() const; void Close(); ///< Closes the file stream. bool ReadHeader(); ///< Reads the ID and the HD block. bool ReadMeasurementInfo(); ///< Reads everything but not CG and raw data. bool ReadEverythingButData(); ///< Reads all blocks but not raw data. - /** \brief Export the attachment data to a detination file. */ + /** \brief Export the attachment data to a destination file. */ bool ExportAttachmentData(const IAttachment& attachment, const std::string& dest_file); @@ -184,7 +201,7 @@ class MdfReader { * bytes typical a video stream. These files tends to be huge so the * application runs out of memory. * - * This function reads in VLSD stored data in smaller batcher. The + * This function reads in VLSD stored data in smaller batches. The * application first reads in all offsets to the raw data. Using these offsets * the application can read in typically one sample (offset) at a time. This * tactic saves primary memory. @@ -203,11 +220,23 @@ class MdfReader { private: - std::FILE* file_ = nullptr; ///< Pointer to the file stream. + /** \brief Internal pointer to the active stream buffer. + * + * Shared pointer to the C++ stream buffer. This buffer is either + * created by this class (file streams) or outside the + */ + std::shared_ptr file_; + std::string filename_; ///< The file name with full path. std::unique_ptr instance_; ///< Pointer to the MDF file object. int64_t index_ = 0; ///< Unique (database) file index that can be used to ///< identify a file instead of its path. + + /** \brief Reads in the + * + */ + void VerifyMdfFile(); + }; } // namespace mdf diff --git a/include/mdf/mdfwriter.h b/include/mdf/mdfwriter.h index 5402b8b5..aeee6dc5 100644 --- a/include/mdf/mdfwriter.h +++ b/include/mdf/mdfwriter.h @@ -309,8 +309,8 @@ class MdfWriter { virtual void CreateMdfFile() = 0; ///< Creates an MDF file virtual bool PrepareForWriting() = 0; ///< Prepare for writing. - virtual void SetDataPosition(std::FILE* file); ///< Set the data position. - virtual bool WriteSignalData(std::FILE* file); ///< Write an SD block. + virtual void SetDataPosition(std::streambuf& file); ///< Set the data position. + virtual bool WriteSignalData(std::streambuf& file); ///< Write an SD block. void StopWorkThread(); ///< Stops the worker thread void WorkThread(); ///< Worker thread function @@ -323,7 +323,7 @@ class MdfWriter { /** \brief Increment the sample counter. */ void IncrementNofSamples(uint64_t record_id) const; /** \brief Set the last file position. */ - virtual void SetLastPosition(std::FILE* file) = 0; + virtual void SetLastPosition(std::streambuf& buffer) = 0; private: diff --git a/include/mdf/zlibutil.h b/include/mdf/zlibutil.h index 8d35082b..6438fa0a 100644 --- a/include/mdf/zlibutil.h +++ b/include/mdf/zlibutil.h @@ -23,7 +23,7 @@ using ByteArray = std::vector; ///< Defines a dynamic byte array * @param out Pointer to the output file stream. * @return True on success. */ -bool Deflate(std::FILE* in, std::FILE* out); ///< Compress file to file. +bool Deflate(std::streambuf& in, std::streambuf& out); ///< Compress file to file. /** * Compress a byte array directly to another array. @@ -55,13 +55,13 @@ bool Deflate(const ByteArray& buf_in, bool Deflate(const std::string& filename, ByteArray& buf_out); ///< Compress array to array. -bool Inflate(std::FILE* in, std::FILE* out); ///< Decompress file to file. -bool Inflate(std::FILE* in, std::FILE* out, +bool Inflate(std::streambuf& in, std::streambuf& out); ///< Decompress file to file. +bool Inflate(std::streambuf& in, std::streambuf& out, uint64_t nof_bytes); ///< Decompress part of file to file bool Inflate(const ByteArray& in, ByteArray& out); ///< Decompress array to array. bool Inflate(const ByteArray& in, - std::FILE* out); ///< Decompress array to file. + std::streambuf& out); ///< Decompress array to file. void Transpose(ByteArray& data, size_t record_size); ///< Transpose of an array. diff --git a/mdflib/src/at4block.cpp b/mdflib/src/at4block.cpp index 1e91f67b..e7dd97ba 100644 --- a/mdflib/src/at4block.cpp +++ b/mdflib/src/at4block.cpp @@ -6,6 +6,7 @@ #include #include +#include #include "mdf/cryptoutil.h" #include "mdf/mdfhelper.h" @@ -46,15 +47,11 @@ std::string MakeFlagString(uint16_t flag) { return s.str(); } -bool CopyBytes(std::FILE* source, std::FILE* dest, uint64_t nof_bytes) { +bool CopyBytes(std::streambuf& source, std::streambuf& dest, uint64_t nof_bytes) { uint8_t temp = 0; for (uint64_t ii = 0; ii < nof_bytes; ++ii) { - if (fread(&temp, 1, 1, source) != 1) { - return false; - } - if (fwrite(&temp, 1, 1, dest) != 1) { - return false; - } + temp = source.sbumpc(); + dest.sputc(static_cast(temp)); } return true; } @@ -144,27 +141,27 @@ void At4Block::GetBlockProperty(BlockPropertyList& dest) const { } } -size_t At4Block::Read(std::FILE* file) { - size_t bytes = ReadHeader4(file); - bytes += ReadNumber(file, flags_); - bytes += ReadNumber(file, creator_index_); +uint64_t At4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadNumber(buffer, flags_); + bytes += ReadNumber(buffer, creator_index_); std::vector reserved; - bytes += ReadByte(file, reserved, 4); - bytes += ReadByte(file, md5_, 16); - bytes += ReadNumber(file, original_size_); - bytes += ReadNumber(file, nof_bytes_); + bytes += ReadByte(buffer, reserved, 4); + bytes += ReadByte(buffer, md5_, 16); + bytes += ReadNumber(buffer, original_size_); + bytes += ReadNumber(buffer, nof_bytes_); // Do not read in the data BLOB at this point but store the file position for // that data, so it is fast to get the data later - data_position_ = GetFilePosition(file); + data_position_ = GetFilePosition(buffer); - filename_ = ReadTx4(file, kIndexFilename); - file_type_ = ReadTx4(file, kIndexType); - ReadMdComment(file, kIndexMd); + filename_ = ReadTx4(buffer, kIndexFilename); + file_type_ = ReadTx4(buffer, kIndexType); + ReadMdComment(buffer, kIndexMd); return bytes; } -size_t At4Block::Write(std::FILE* file) { +uint64_t At4Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; if (update) { return block_size_; @@ -190,8 +187,8 @@ size_t At4Block::Write(std::FILE* file) { return 0; } } else if (IsEmbedded()) { - const auto buffer = FileToBuffer(filename_, data_buffer); - if (!buffer) { + const auto read = FileToBuffer(filename_, data_buffer); + if (!read) { MDF_ERROR() << "File to buffer failure. File: " << filename; return 0; } @@ -209,44 +206,47 @@ size_t At4Block::Write(std::FILE* file) { block_length_ = 24 + (4 * 8) + 2 + 2 + 4 + 16 + 8 + 8 + nof_bytes_; link_list_.resize(4, 0); - WriteTx4(file, kIndexFilename, filename_); - WriteTx4(file, kIndexType, file_type_); - WriteMdComment(file, kIndexMd); + WriteTx4(buffer, kIndexFilename, filename_); + WriteTx4(buffer, kIndexType, file_type_); + WriteMdComment(buffer, kIndexMd); - auto bytes = MdfBlock::Write(file); - bytes += WriteNumber(file, flags_); - bytes += WriteNumber(file, creator_index_); - bytes += WriteBytes(file, 4); + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteNumber(buffer, flags_); + bytes += WriteNumber(buffer, creator_index_); + bytes += WriteBytes(buffer, 4); if (md5_.size() == 16) { - bytes += WriteByte(file, md5_); + bytes += WriteByte(buffer, md5_); } else { - bytes += WriteBytes(file, 16); + bytes += WriteBytes(buffer, 16); } - bytes += WriteNumber(file, original_size_); - bytes += WriteNumber(file, nof_bytes_); + bytes += WriteNumber(buffer, original_size_); + bytes += WriteNumber(buffer, nof_bytes_); data_position_ = FilePosition(); if (nof_bytes_ > 0) { - bytes += WriteByte(file, data_buffer); + bytes += WriteByte(buffer, data_buffer); } - UpdateBlockSize(file, bytes); + UpdateBlockSize(buffer, bytes); return bytes; } -void At4Block::ReadData(std::FILE* file, const std::string& dest_file) const { - if (file == nullptr || data_position_ <= 0) { +void At4Block::ReadData(std::streambuf& buffer, + const std::string& dest_file) const { + if (data_position_ <= 0) { throw std::invalid_argument("File is not opened or data position not read"); } - SetFilePosition(file, data_position_); + SetFilePosition(buffer, data_position_); if (IsEmbedded()) { - FILE* dest = nullptr; - Platform::fileopen(&dest, dest_file.c_str(), "wb"); - if (dest == nullptr) { + std::filebuf dest; + dest.open( dest_file, + std::ios_base::out | std::ios_base::trunc | std::ios_base::binary); + if (!dest.is_open()) { throw std::ios_base::failure("Failed to open the destination file"); } - const bool error = IsCompressed() ? !Inflate(file, dest, nof_bytes_) - : !CopyBytes(file, dest, nof_bytes_); - if (const int close = fclose(dest); error || close != 0) { + const bool error = IsCompressed() ? !Inflate(buffer, dest, nof_bytes_) + : !CopyBytes(buffer, dest, nof_bytes_); + dest.close(); + if ( error ) { throw std::ios_base::failure("Failed to copy correct number of bytes"); } } else { diff --git a/mdflib/src/at4block.h b/mdflib/src/at4block.h index c4c13a12..d9721260 100644 --- a/mdflib/src/at4block.h +++ b/mdflib/src/at4block.h @@ -51,11 +51,11 @@ class At4Block : public MdfBlock, public IAttachment { [[nodiscard]] bool IsCompressed() const override; void GetBlockProperty(BlockPropertyList& dest) const override; - size_t Read(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; - void ReadData(std::FILE* file, const std::string& dest_file) const; + void ReadData(std::streambuf& buffer, const std::string& dest_file) const; - size_t Write(std::FILE* file) override; + uint64_t Write(std::streambuf& buffer) override; [[nodiscard]] std::optional Md5() const override; private: diff --git a/mdflib/src/ca4block.cpp b/mdflib/src/ca4block.cpp index 48f16ef5..7962cfab 100644 --- a/mdflib/src/ca4block.cpp +++ b/mdflib/src/ca4block.cpp @@ -269,17 +269,17 @@ void Ca4Block::GetBlockProperty(BlockPropertyList &dest) const { } } -size_t Ca4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); // This function also read in all links - bytes += ReadNumber(file, type_); - bytes += ReadNumber(file, storage_); - bytes += ReadNumber(file, dimensions_); - bytes += ReadNumber(file, flags_); - bytes += ReadNumber(file, byte_offset_base_); - bytes += ReadNumber(file, invalid_bit_pos_base_); +uint64_t Ca4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); // This function also read in all links + bytes += ReadNumber(buffer, type_); + bytes += ReadNumber(buffer, storage_); + bytes += ReadNumber(buffer, dimensions_); + bytes += ReadNumber(buffer, flags_); + bytes += ReadNumber(buffer, byte_offset_base_); + bytes += ReadNumber(buffer, invalid_bit_pos_base_); dim_size_list_.resize(dimensions_, 0); // Resize number values/dimension for (uint64_t& dim_size : dim_size_list_ ) { - bytes += ReadNumber(file, dim_size); + bytes += ReadNumber(buffer, dim_size); } const auto sum_dim = SumOfArray(); const auto prod_dim = ProductOfArray(); @@ -287,7 +287,7 @@ size_t Ca4Block::Read(std::FILE *file) { if ((flags_ & CaFlag::FixedAxis) != 0) { axis_value_list_.resize(static_cast(sum_dim), 0.0); for (double& axis_value : axis_value_list_) { - bytes += ReadNumber(file, axis_value); + bytes += ReadNumber(buffer, axis_value); } } @@ -297,7 +297,7 @@ size_t Ca4Block::Read(std::FILE *file) { cycle_count_list_.resize(static_cast(prod_dim), 0); for (uint64_t& cycle : cycle_count_list_) { if (bytes + 8 <= max_bytes) { - bytes += ReadNumber(file, cycle); + bytes += ReadNumber(buffer, cycle); } } break; @@ -309,23 +309,23 @@ size_t Ca4Block::Read(std::FILE *file) { // Need to read all composition blocks if they exist if (Link(kIndexComposition) > 0) { - SetFilePosition(file, Link(kIndexComposition)); - const auto block_type = ReadBlockType(file); + SetFilePosition(buffer, Link(kIndexComposition)); + const auto block_type = ReadBlockType(buffer); if (composition_list_.empty() && (Link(kIndexComposition) > 0)) { for (auto link = Link(kIndexComposition); link > 0; /* No ++ here*/) { if (block_type == "CA") { auto ca_block = std::make_unique(); ca_block->Init(*this); - SetFilePosition(file, link); - ca_block->Read(file); + SetFilePosition(buffer, link); + ca_block->Read(buffer); link = ca_block->Link(0); composition_list_.emplace_back(std::move(ca_block)); } else if (block_type == "CN") { auto cn_block = std::make_unique(); cn_block->Init(*this); - SetFilePosition(file, link); - cn_block->Read(file); + SetFilePosition(buffer, link); + cn_block->Read(buffer); link = cn_block->Link(0); composition_list_.emplace_back(std::move(cn_block)); } @@ -334,11 +334,11 @@ size_t Ca4Block::Read(std::FILE *file) { } // Finds all objects. Note that is function is called after all blocks are // read. For now, it sizes the lists. - FindAllReferences(file); + FindAllReferences(buffer); return bytes; } -void Ca4Block::FindAllReferences(std::FILE* file) { +void Ca4Block::FindAllReferences(std::streambuf& buffer) { const uint64_t prod_dim = ProductOfArray(); size_t link_index = 1; if (Storage() == ArrayStorage::DgTemplate) { @@ -403,7 +403,7 @@ void Ca4Block::FindAllReferences(std::FILE* file) { } } -size_t Ca4Block::Write(std::FILE *file) { +uint64_t Ca4Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // True if already written to file if (update) { return static_cast(block_length_); @@ -465,31 +465,31 @@ size_t Ca4Block::Write(std::FILE *file) { } link_list_.resize(nof_links, 0); - WriteLink4List(file, composition_list_, kIndexComposition, + WriteLink4List(buffer, composition_list_, kIndexComposition, UpdateOption::DoNotUpdateWrittenBlock); size_t link_index = kIndexArray; if (Storage() == ArrayStorage::DgTemplate) { for (size_t index = 0; index < ProductOfArray(); ++index) { const int64_t data_position = index < data_links_.size() ? data_links_[index] : 0; - UpdateLink(file, link_index, data_position); + UpdateLink(buffer, link_index, data_position); ++link_index; } } if ((Flags() & CaFlag::DynamicSize) != 0) { - link_index += WriteReferences(file, dynamic_size_list_, + link_index += WriteReferences(buffer, dynamic_size_list_, Dimensions(), link_index); } if ((Flags() & CaFlag::InputQuantity) != 0) { - link_index += WriteReferences(file, input_quantity_list_, + link_index += WriteReferences(buffer, input_quantity_list_, Dimensions(), link_index); } if ((Flags() & CaFlag::OutputQuantity) != 0) { - WriteReference(file, output_quantity_, link_index); + WriteReference(buffer, output_quantity_, link_index); link_index += 3; } if ((Flags() & CaFlag::ComparisonQuantity) != 0) { - WriteReference(file, comparison_quantity_, link_index); + WriteReference(buffer, comparison_quantity_, link_index); link_index += 3; } if ((Flags() & CaFlag::Axis) != 0) { @@ -497,36 +497,36 @@ size_t Ca4Block::Write(std::FILE *file) { if (index < axis_conversion_list_.size()) { const auto* cc_block = axis_conversion_list_[index]; const int64_t axis_position = cc_block != nullptr ? cc_block->Index() : 0; - UpdateLink(file,link_index,axis_position); + UpdateLink(buffer,link_index,axis_position); } else { - UpdateLink(file,link_index,0); + UpdateLink(buffer,link_index,0); } ++link_index; } } if ((Flags() & CaFlag::Axis) != 0 && (Flags() & CaFlag::FixedAxis) == 0) { - link_index += WriteReferences(file, axis_list_, + link_index += WriteReferences(buffer, axis_list_, Dimensions(), link_index); } - auto bytes = MdfBlock::Write(file); - bytes += WriteNumber(file, type_); - bytes += WriteNumber(file, storage_); - bytes += WriteNumber(file, dimensions_); - bytes += WriteNumber(file, flags_); - bytes += WriteNumber(file, byte_offset_base_); - bytes += WriteNumber(file, invalid_bit_pos_base_); + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteNumber(buffer, type_); + bytes += WriteNumber(buffer, storage_); + bytes += WriteNumber(buffer, dimensions_); + bytes += WriteNumber(buffer, flags_); + bytes += WriteNumber(buffer, byte_offset_base_); + bytes += WriteNumber(buffer, invalid_bit_pos_base_); for (size_t dimension = 0; dimension < Dimensions(); ++dimension) { const uint64_t dim_size = dimension < dim_size_list_.size() ? dim_size_list_[dimension] : 0; - bytes += WriteNumber(file, dim_size); + bytes += WriteNumber(buffer, dim_size); } if ((Flags() & CaFlag::FixedAxis) != 0) { for (size_t axis = 0; axis < SumOfArray(); ++axis) { const double axis_value = axis < axis_value_list_.size() ? axis_value_list_[axis] : 0.0; - bytes += WriteNumber(file, axis_value); + bytes += WriteNumber(buffer, axis_value); } } @@ -536,7 +536,7 @@ size_t Ca4Block::Write(std::FILE *file) { for (size_t cycle = 0; cycle < ProductOfArray(); ++cycle) { const uint64_t count = cycle < cycle_count_list_.size() ? cycle_count_list_[cycle] : 0; - bytes += WriteNumber(file, count); + bytes += WriteNumber(buffer, count); } break; } @@ -544,7 +544,7 @@ size_t Ca4Block::Write(std::FILE *file) { default: break; } - UpdateBlockSize(file, bytes); + UpdateBlockSize(buffer, bytes); return bytes; } @@ -701,18 +701,18 @@ CaTripleReference Ca4Block::ReadReference(size_t index) const { return ref; } -void Ca4Block::WriteReference(std::FILE* file, +void Ca4Block::WriteReference(std::streambuf& buffer, const CaTripleReference& ref, size_t start_index) { - UpdateLink(file, start_index, + UpdateLink(buffer, start_index, ref.DataGroup != nullptr ? ref.DataGroup->Index() : 0 ); - UpdateLink(file, start_index + 1, + UpdateLink(buffer, start_index + 1, ref.ChannelGroup != nullptr ? ref.ChannelGroup->Index() : 0 ); - UpdateLink(file, start_index + 2, + UpdateLink(buffer, start_index + 2, ref.Channel != nullptr ? ref.Channel->Index() : 0 ); } -size_t Ca4Block::WriteReferences(std::FILE* file, +size_t Ca4Block::WriteReferences(std::streambuf& buffer, const std::vector& list, size_t max_fill, size_t start_index) { @@ -720,13 +720,13 @@ size_t Ca4Block::WriteReferences(std::FILE* file, for (size_t index = 0; index < max_fill; ++index) { if (index < list.size()) { const auto& ref = list[index]; - WriteReference(file, ref, start_index + nof_links); - UpdateLink(file, start_index + nof_links, + WriteReference(buffer, ref, start_index + nof_links); + UpdateLink(buffer, start_index + nof_links, ref.DataGroup != nullptr ? ref.DataGroup->Index() : 0 ); } else { - UpdateLink(file, start_index + nof_links,0 ); - UpdateLink(file, start_index + nof_links + 1, 0 ); - UpdateLink(file, start_index + nof_links + 2, 0 ); + UpdateLink(buffer, start_index + nof_links,0 ); + UpdateLink(buffer, start_index + nof_links + 1, 0 ); + UpdateLink(buffer, start_index + nof_links + 2, 0 ); } nof_links += 3; } diff --git a/mdflib/src/ca4block.h b/mdflib/src/ca4block.h index 9fc7f142..c9a68644 100644 --- a/mdflib/src/ca4block.h +++ b/mdflib/src/ca4block.h @@ -62,10 +62,10 @@ class Ca4Block : public MdfBlock, public IChannelArray { [[nodiscard]] MdfBlock *Find(int64_t index) const override; [[nodiscard]] const Cx4List& Cx4() const { return composition_list_; } - size_t Read(std::FILE* file) override; - void FindAllReferences(std::FILE* file); + uint64_t Read(std::streambuf& buffer) override; + void FindAllReferences(std::streambuf& buffer); - size_t Write(std::FILE* file) override; + uint64_t Write(std::streambuf& buffer) override; void SetParentChannel(const Cn4Block* parent); void PrepareForWriting(); @@ -89,9 +89,9 @@ class Ca4Block : public MdfBlock, public IChannelArray { [[nodiscard]] CaTripleReference ReadReference(size_t index) const; - void WriteReference(std::FILE* file, + void WriteReference(std::streambuf& buffer, const CaTripleReference& ref, size_t start_index); - size_t WriteReferences(std::FILE* file, + size_t WriteReferences(std::streambuf& buffer, const std::vector& list, size_t max_fill, size_t start_index); diff --git a/mdflib/src/cc3block.cpp b/mdflib/src/cc3block.cpp index ec9b392f..bb1e3b74 100644 --- a/mdflib/src/cc3block.cpp +++ b/mdflib/src/cc3block.cpp @@ -185,15 +185,15 @@ void Cc3Block::GetBlockProperty(BlockPropertyList &dest) const { } } -size_t Cc3Block::Read(std::FILE *file) { - size_t bytes = ReadHeader3(file); - bytes += ReadBool(file, range_valid_); - bytes += ReadNumber(file, min_); - bytes += ReadNumber(file, max_); - bytes += ReadStr(file, unit_, 20); - bytes += ReadNumber(file, conversion_type_); +uint64_t Cc3Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader3(buffer); + bytes += ReadBool(buffer, range_valid_); + bytes += ReadNumber(buffer, min_); + bytes += ReadNumber(buffer, max_); + bytes += ReadStr(buffer, unit_, 20); + bytes += ReadNumber(buffer, conversion_type_); if (bytes < block_size_) { - bytes += ReadNumber(file, nof_values_); + bytes += ReadNumber(buffer, nof_values_); } value_list_.clear(); @@ -209,7 +209,7 @@ size_t Cc3Block::Read(std::FILE *file) { case 9: // Rational for (uint16_t par = 0; par < nof_values_; ++par) { double temp = 0; - bytes += ReadNumber(file, temp); + bytes += ReadNumber(buffer, temp); value_list_.emplace_back(temp); } break; @@ -218,23 +218,23 @@ size_t Cc3Block::Read(std::FILE *file) { case 2: // Tabular for (uint16_t par = 0; par < nof_values_; ++par) { double temp1 = 0; - bytes += ReadNumber(file, temp1); + bytes += ReadNumber(buffer, temp1); value_list_.emplace_back(temp1); double temp2 = 0; - bytes += ReadNumber(file, temp2); + bytes += ReadNumber(buffer, temp2); value_list_.emplace_back(temp2); } break; case 10: // Text formula - bytes += ReadStr(file, formula_, nof_values_); + bytes += ReadStr(buffer, formula_, nof_values_); break; case 11: // Text Table for (uint16_t par = 0; par < nof_values_; ++par) { TextConversion cc; - bytes += ReadNumber(file, cc.value); - bytes += ReadStr(file, cc.text, 32); + bytes += ReadNumber(buffer, cc.value); + bytes += ReadStr(buffer, cc.text, 32); text_conversion_list_.emplace_back(cc); } break; @@ -242,9 +242,9 @@ size_t Cc3Block::Read(std::FILE *file) { case 12: // Text Range Table for (uint16_t par = 0; par < nof_values_; ++par) { TextRangeConversion cc; - bytes += ReadNumber(file, cc.lower); - bytes += ReadNumber(file, cc.upper); - bytes += ReadNumber(file, cc.link_text); + bytes += ReadNumber(buffer, cc.lower); + bytes += ReadNumber(buffer, cc.upper); + bytes += ReadNumber(buffer, cc.link_text); text_range_conversion_list_.emplace_back(cc); } break; @@ -260,15 +260,15 @@ size_t Cc3Block::Read(std::FILE *file) { if (conv.link_text > 0) { Tx3Block temp; temp.Init(*this); - SetFilePosition(file, conv.link_text); - temp.Read(file); + SetFilePosition(buffer, conv.link_text); + temp.Read(buffer); conv.text = temp.Text(); } } return bytes; } -size_t Cc3Block::Write(std::FILE *file) { +uint64_t Cc3Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // Write or update the values inside the block if (update) { @@ -281,7 +281,7 @@ size_t Cc3Block::Write(std::FILE *file) { if (!range.text.empty()) { Tx3Block temp; temp.Init(*this); - temp.Write(file); + temp.Write(buffer); link = static_cast(temp.FilePosition()); } range.link_text = link; @@ -291,12 +291,12 @@ size_t Cc3Block::Write(std::FILE *file) { 2; // Will be updated at the end of the block write link_list_.clear(); - size_t bytes = MdfBlock::Write(file); - bytes += WriteBool(file, range_valid_); - bytes += WriteNumber(file, min_); - bytes += WriteNumber(file, max_); - bytes += WriteStr(file, unit_, 20); - bytes += WriteNumber(file, conversion_type_); + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteBool(buffer, range_valid_); + bytes += WriteNumber(buffer, min_); + bytes += WriteNumber(buffer, max_); + bytes += WriteStr(buffer, unit_, 20); + bytes += WriteNumber(buffer, conversion_type_); switch (conversion_type_) { case 0: // Parametric @@ -305,43 +305,43 @@ size_t Cc3Block::Write(std::FILE *file) { case 8: // Logarithmic case 9: // Rational nof_values_ = static_cast(value_list_.size()); - bytes += WriteNumber(file, nof_values_); + bytes += WriteNumber(buffer, nof_values_); for (auto par : value_list_) { - bytes += WriteNumber(file, par); + bytes += WriteNumber(buffer, par); } break; case 1: // Tabular interpolation case 2: // Tabular nof_values_ = static_cast(value_list_.size() / 2); - bytes += WriteNumber(file, nof_values_); + bytes += WriteNumber(buffer, nof_values_); for (auto par : value_list_) { - bytes += WriteNumber(file, par); + bytes += WriteNumber(buffer, par); } break; case 10: // Text formula nof_values_ = static_cast(formula_.size()); - bytes += WriteNumber(file, nof_values_); - WriteStr(file, formula_, formula_.size()); + bytes += WriteNumber(buffer, nof_values_); + WriteStr(buffer, formula_, formula_.size()); break; case 11: // Text Table nof_values_ = static_cast(text_conversion_list_.size()); - bytes += WriteNumber(file, nof_values_); + bytes += WriteNumber(buffer, nof_values_); for (const auto &conv : text_conversion_list_) { - bytes += WriteNumber(file, conv.value); - bytes += WriteStr(file, conv.text, 32); + bytes += WriteNumber(buffer, conv.value); + bytes += WriteStr(buffer, conv.text, 32); } break; case 12: // Text Range Table nof_values_ = static_cast(text_range_conversion_list_.size()); - bytes += WriteNumber(file, nof_values_); + bytes += WriteNumber(buffer, nof_values_); for (const auto &conv : text_range_conversion_list_) { - bytes += WriteNumber(file, conv.lower); - bytes += WriteNumber(file, conv.upper); - bytes += WriteNumber(file, conv.link_text); + bytes += WriteNumber(buffer, conv.lower); + bytes += WriteNumber(buffer, conv.upper); + bytes += WriteNumber(buffer, conv.link_text); } break; @@ -350,10 +350,10 @@ size_t Cc3Block::Write(std::FILE *file) { case 65535: // 1:1 conversion (used to set unit to a CN block) default: nof_values_ = 0; - bytes += WriteNumber(file, nof_values_); + bytes += WriteNumber(buffer, nof_values_); break; } - UpdateBlockSize(file, bytes); + UpdateBlockSize(buffer, bytes); return bytes; } diff --git a/mdflib/src/cc3block.h b/mdflib/src/cc3block.h index 320fcc8e..8a479a01 100644 --- a/mdflib/src/cc3block.h +++ b/mdflib/src/cc3block.h @@ -32,8 +32,8 @@ class Cc3Block : public MdfBlock, public IChannelConversion { [[nodiscard]] uint8_t Decimals() const override; void GetBlockProperty(BlockPropertyList& dest) const override; - size_t Read(std::FILE* file) override; - size_t Write(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; protected: bool ConvertValueToText(double channel_value, diff --git a/mdflib/src/cc4block.cpp b/mdflib/src/cc4block.cpp index 70fa1140..a4104cca 100644 --- a/mdflib/src/cc4block.cpp +++ b/mdflib/src/cc4block.cpp @@ -203,43 +203,43 @@ void Cc4Block::GetBlockProperty(BlockPropertyList& dest) const { } } -size_t Cc4Block::Read(std::FILE* file) { // NOLINT - size_t bytes = ReadHeader4(file); - bytes += ReadNumber(file, type_); - bytes += ReadNumber(file, precision_); - bytes += ReadNumber(file, flags_); - bytes += ReadNumber(file, nof_references_); - bytes += ReadNumber(file, nof_values_); - bytes += ReadNumber(file, range_min_); - bytes += ReadNumber(file, range_max_); +uint64_t Cc4Block::Read(std::streambuf& buffer) { // NOLINT + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadNumber(buffer, type_); + bytes += ReadNumber(buffer, precision_); + bytes += ReadNumber(buffer, flags_); + bytes += ReadNumber(buffer, nof_references_); + bytes += ReadNumber(buffer, nof_values_); + bytes += ReadNumber(buffer, range_min_); + bytes += ReadNumber(buffer, range_max_); value_list_.clear(); for (uint16_t ii = 0; ii < nof_values_; ++ii) { if (Type() == ConversionType::BitfieldToText) { uint64_t temp = 0; - bytes += ReadNumber(file, temp); + bytes += ReadNumber(buffer, temp); value_list_.emplace_back(temp); } else { double temp = 0; - bytes += ReadNumber(file, temp); + bytes += ReadNumber(buffer, temp); value_list_.emplace_back(temp); } } - name_ = ReadTx4(file, kIndexName); + name_ = ReadTx4(buffer, kIndexName); if (Link(kIndexUnit) > 0) { - SetFilePosition(file, Link(kIndexUnit)); + SetFilePosition(buffer, Link(kIndexUnit)); unit_ = std::make_unique(); unit_->Init(*this); - unit_->Read(file); + unit_->Read(buffer); } - ReadMdComment(file, kIndexMd); + ReadMdComment(buffer, kIndexMd); if (Link(kIndexInverse) > 0) { - SetFilePosition(file, Link(kIndexInverse)); + SetFilePosition(buffer, Link(kIndexInverse)); cc_block_ = std::make_unique(); cc_block_->Init(*this); - cc_block_->Read(file); + cc_block_->Read(buffer); } if (ref_list_.empty() && nof_references_ > 0) { for (uint16_t ii = 0; ii < nof_references_; ++ii) { @@ -247,20 +247,20 @@ size_t Cc4Block::Read(std::FILE* file) { // NOLINT ref_list_.emplace_back(std::unique_ptr()); continue; } - SetFilePosition(file, Link(kIndexRef + ii)); - const std::string block_type = ReadBlockType(file); + SetFilePosition(buffer, Link(kIndexRef + ii)); + const std::string block_type = ReadBlockType(buffer); - SetFilePosition(file, Link(kIndexRef + ii)); + SetFilePosition(buffer, Link(kIndexRef + ii)); if (block_type == "TX") { auto tx = std::make_unique(); tx->Init(*this); - tx->Read(file); + tx->Read(buffer); ref_list_.emplace_back(std::move(tx)); } else if (block_type == "CC") { auto cc = std::make_unique(); cc->Init(*this); cc->ChannelDataType(channel_data_type_); - cc->Read(file); + cc->Read(buffer); ref_list_.emplace_back(std::move(cc)); } else { ref_list_.emplace_back(std::unique_ptr()); @@ -270,7 +270,7 @@ size_t Cc4Block::Read(std::FILE* file) { // NOLINT return bytes; } -size_t Cc4Block::Write(std::FILE* file) { // NOLINT +uint64_t Cc4Block::Write(std::streambuf& buffer) { // NOLINT const bool update = FilePosition() > 0; // True if already written to file if (update) { return static_cast(block_length_); @@ -283,35 +283,35 @@ size_t Cc4Block::Write(std::FILE* file) { // NOLINT block_length_ = 24 + (4 * 8) + (nof_references_ * 8) + 1 + 1 + 2 + 2 + 2 + 8 + 8 + (8 * nof_values_); link_list_.resize(4 + nof_references_, 0); - WriteTx4(file, kIndexName, name_); - WriteBlock4(file, unit_, kIndexUnit); - WriteMdComment(file, kIndexMd); - WriteBlock4(file, cc_block_, kIndexInverse); + WriteTx4(buffer, kIndexName, name_); + WriteBlock4(buffer, unit_, kIndexUnit); + WriteMdComment(buffer, kIndexMd); + WriteBlock4(buffer, cc_block_, kIndexInverse); for (uint16_t index_m = 0; index_m < nof_references_; ++index_m) { const auto index = kIndexRef + index_m; auto& block = ref_list_[index_m]; - WriteBlock4(file, block, index); + WriteBlock4(buffer, block, index); } - auto bytes = MdfBlock::Write(file); - bytes += WriteNumber(file, type_); - bytes += WriteNumber(file, precision_); - bytes += WriteNumber(file, flags_); - bytes += WriteNumber(file, nof_references_); - bytes += WriteNumber(file, nof_values_); - bytes += WriteNumber(file, range_min_); - bytes += WriteNumber(file, range_max_); + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteNumber(buffer, type_); + bytes += WriteNumber(buffer, precision_); + bytes += WriteNumber(buffer, flags_); + bytes += WriteNumber(buffer, nof_references_); + bytes += WriteNumber(buffer, nof_values_); + bytes += WriteNumber(buffer, range_min_); + bytes += WriteNumber(buffer, range_max_); for (uint16_t index_n = 0; index_n < nof_values_; ++index_n) { const auto& val = value_list_[index_n]; if (std::holds_alternative(val)) { - bytes += WriteNumber(file, std::get(val)); + bytes += WriteNumber(buffer, std::get(val)); } else if (std::holds_alternative(val)) { - bytes += WriteNumber(file, std::get(val)); + bytes += WriteNumber(buffer, std::get(val)); } else { - bytes += WriteNumber(file, 0.0); + bytes += WriteNumber(buffer, 0.0); } } - UpdateBlockSize(file, bytes); + UpdateBlockSize(buffer, bytes); return bytes; } diff --git a/mdflib/src/cc4block.h b/mdflib/src/cc4block.h index 02b7231e..5b2f5a96 100644 --- a/mdflib/src/cc4block.h +++ b/mdflib/src/cc4block.h @@ -71,8 +71,8 @@ class Cc4Block : public MdfBlock, public IChannelConversion { [[nodiscard]] MdfBlock* Find(int64_t index) const override; void GetBlockProperty(BlockPropertyList& dest) const override; - size_t Read(std::FILE* file) override; - size_t Write(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; void Formula( const std::string& formula) override; [[nodiscard]] const std::string& Formula() const override; diff --git a/mdflib/src/cd3block.cpp b/mdflib/src/cd3block.cpp index 124cd0d8..8f7d148b 100644 --- a/mdflib/src/cd3block.cpp +++ b/mdflib/src/cd3block.cpp @@ -4,10 +4,11 @@ */ #include "cd3block.h" namespace mdf::detail { -size_t Cd3Block::Read(std::FILE *file) { - size_t bytes = ReadHeader3(file); - bytes += ReadNumber(file, dependency_type_); - bytes += ReadNumber(file, nof_dependencies_); + +uint64_t Cd3Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader3(buffer); + bytes += ReadNumber(buffer, dependency_type_); + bytes += ReadNumber(buffer, nof_dependencies_); dependency_list_.clear(); dimension_list_.clear(); switch (dependency_type_) { @@ -17,16 +18,16 @@ size_t Cd3Block::Read(std::FILE *file) { case 2: for (uint16_t dep = 0; dep < nof_dependencies_; ++dep) { Dependency d; - bytes += ReadNumber(file, d.link_dg); - bytes += ReadNumber(file, d.link_cg); - bytes += ReadNumber(file, d.link_cn); + bytes += ReadNumber(buffer, d.link_dg); + bytes += ReadNumber(buffer, d.link_cg); + bytes += ReadNumber(buffer, d.link_cn); dependency_list_.emplace_back(d); } break; default: for (uint16_t dim = 256; dim < nof_dependencies_; ++dim) { uint16_t temp = 0; - bytes += ReadNumber(file, temp); + bytes += ReadNumber(buffer, temp); dimension_list_.emplace_back(temp); } break; diff --git a/mdflib/src/cd3block.h b/mdflib/src/cd3block.h index d23c5997..55e2a0bb 100644 --- a/mdflib/src/cd3block.h +++ b/mdflib/src/cd3block.h @@ -16,7 +16,7 @@ struct Dependency { class Cd3Block : public MdfBlock { public: - size_t Read(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; private: uint16_t dependency_type_ = 0; diff --git a/mdflib/src/ce3block.cpp b/mdflib/src/ce3block.cpp index 74806933..dd7c0102 100644 --- a/mdflib/src/ce3block.cpp +++ b/mdflib/src/ce3block.cpp @@ -5,22 +5,22 @@ #include "ce3block.h" namespace mdf::detail { -size_t Ce3Block::Read(std::FILE *file) { - size_t bytes = ReadHeader3(file); - bytes += ReadNumber(file, type_); +uint64_t Ce3Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader3(buffer); + bytes += ReadNumber(buffer, type_); switch (type_) { case 2: - bytes += ReadNumber(file, nof_module_); - bytes += ReadNumber(file, address_); - bytes += ReadStr(file, description_, 80); - bytes += ReadStr(file, ecu_, 32); + bytes += ReadNumber(buffer, nof_module_); + bytes += ReadNumber(buffer, address_); + bytes += ReadStr(buffer, description_, 80); + bytes += ReadStr(buffer, ecu_, 32); break; case 19: - bytes += ReadNumber(file, message_id_); - bytes += ReadNumber(file, index_); - bytes += ReadStr(file, message_, 36); - bytes += ReadStr(file, sender_, 36); + bytes += ReadNumber(buffer, message_id_); + bytes += ReadNumber(buffer, index_); + bytes += ReadStr(buffer, message_, 36); + bytes += ReadStr(buffer, sender_, 36); break; default: diff --git a/mdflib/src/ce3block.h b/mdflib/src/ce3block.h index 36ac8e0d..4a8357f9 100644 --- a/mdflib/src/ce3block.h +++ b/mdflib/src/ce3block.h @@ -12,7 +12,7 @@ namespace mdf::detail { class Ce3Block : public MdfBlock { public: - size_t Read(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; private: uint16_t type_ = 0; diff --git a/mdflib/src/cg3block.cpp b/mdflib/src/cg3block.cpp index a07e6735..a354d1d4 100644 --- a/mdflib/src/cg3block.cpp +++ b/mdflib/src/cg3block.cpp @@ -84,24 +84,24 @@ void Cg3Block::GetBlockProperty(BlockPropertyList &dest) const { dest.emplace_back("Comment", comment_); } -size_t Cg3Block::Read(std::FILE *file) { - size_t bytes = ReadHeader3(file); - bytes += ReadLinks3(file, 3); - - bytes += ReadNumber(file, record_id_); - bytes += ReadNumber(file, nof_channels_); - bytes += ReadNumber(file, size_of_data_record_); - bytes += ReadNumber(file, nof_records_); +uint64_t Cg3Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader3(buffer); + bytes += ReadLinks3(buffer, 3); + + bytes += ReadNumber(buffer, record_id_); + bytes += ReadNumber(buffer, nof_channels_); + bytes += ReadNumber(buffer, size_of_data_record_); + bytes += ReadNumber(buffer, nof_records_); if (bytes + 4 < block_size_) { uint32_t link = 0; - bytes += ReadNumber(file, link); + bytes += ReadNumber(buffer, link); link_list_.emplace_back(link); } - comment_ = ReadTx3(file, kIndexTx); + comment_ = ReadTx3(buffer, kIndexTx); return bytes; } -size_t Cg3Block::Write(std::FILE *file) { +uint64_t Cg3Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // Write or update the values inside the block nof_channels_ = static_cast(cn_list_.size()); @@ -120,35 +120,35 @@ size_t Cg3Block::Write(std::FILE *file) { if (!sr3 || sr3->FilePosition() > 0) { continue; } - sr3->Write(file); + sr3->Write(buffer); if (sr_index == 0) { sr_link = sr3->FilePosition(); } else { auto &prev = sr_list_[sr_index - 1]; if (prev) { - prev->UpdateLink(file, kIndexNext, sr3->FilePosition()); + prev->UpdateLink(buffer, kIndexNext, sr3->FilePosition()); } } } - auto bytes = update ? MdfBlock::Update(file) : MdfBlock::Write(file); + uint64_t bytes = update ? MdfBlock::Update(buffer) : MdfBlock::Write(buffer); if (!update) { - bytes += WriteNumber(file, record_id_); - bytes += WriteNumber(file, nof_channels_); - bytes += WriteNumber(file, size_of_data_record_); - bytes += WriteNumber(file, nof_records_); - bytes += WriteNumber(file, static_cast(sr_link)); + bytes += WriteNumber(buffer, record_id_); + bytes += WriteNumber(buffer, nof_channels_); + bytes += WriteNumber(buffer, size_of_data_record_); + bytes += WriteNumber(buffer, nof_records_); + bytes += WriteNumber(buffer, static_cast(sr_link)); } else { // Only nof_records and SR blocks may be added - bytes += StepFilePosition(file, sizeof(record_id_) + sizeof(nof_channels_) + + bytes += StepFilePosition(buffer, sizeof(record_id_) + sizeof(nof_channels_) + sizeof(size_of_data_record_)); - bytes += WriteNumber(file, nof_records_); + bytes += WriteNumber(buffer, nof_records_); // Check if any SR blocks been added. This typical happens after a // measurement. if (sr_link > 0) { - bytes += WriteNumber(file, static_cast(sr_link)); + bytes += WriteNumber(buffer, static_cast(sr_link)); } else { - bytes += StepFilePosition(file, sizeof(uint32_t)); + bytes += StepFilePosition(buffer, sizeof(uint32_t)); } } @@ -157,13 +157,13 @@ size_t Cg3Block::Write(std::FILE *file) { if (!cn3 || cn3->FilePosition() > 0) { continue; } - cn3->Write(file); + cn3->Write(buffer); if (cn_index == 0) { - UpdateLink(file, kIndexCn, cn3->FilePosition()); + UpdateLink(buffer, kIndexCn, cn3->FilePosition()); } else { auto &prev = cn_list_[cn_index - 1]; if (prev) { - prev->UpdateLink(file, kIndexNext, cn3->FilePosition()); + prev->UpdateLink(buffer, kIndexNext, cn3->FilePosition()); } } } @@ -171,32 +171,32 @@ size_t Cg3Block::Write(std::FILE *file) { if (!comment_.empty() && Link(kIndexTx) <= 0) { Tx3Block tx(comment_); tx.Init(*this); - tx.Write(file); - UpdateLink(file, kIndexTx, tx.FilePosition()); + tx.Write(buffer); + UpdateLink(buffer, kIndexTx, tx.FilePosition()); } return bytes; } -void Cg3Block::ReadCnList(std::FILE *file) { +void Cg3Block::ReadCnList(std::streambuf& buffer) { if (cn_list_.empty() && Link(kIndexCn) > 0) { for (auto link = Link(kIndexCn); link > 0; /* No ++ here*/) { auto cn = std::make_unique(); cn->Init(*this); - SetFilePosition(file, link); - cn->Read(file); + SetFilePosition(buffer, link); + cn->Read(buffer); link = cn->Link(kIndexNext); cn_list_.push_back(std::move(cn)); } } } -void Cg3Block::ReadSrList(std::FILE *file) { +void Cg3Block::ReadSrList(std::streambuf& buffer) { if (sr_list_.empty() && Link(kIndexSr) > 0) { for (auto link = Link(kIndexSr); link > 0; /* No ++ here*/) { auto sr = std::make_unique(); sr->Init(*this); - SetFilePosition(file, link); - sr->Read(file); + SetFilePosition(buffer, link); + sr->Read(buffer); link = sr->Link(kIndexNext); sr_list_.push_back(std::move(sr)); } @@ -233,15 +233,16 @@ void Cg3Block::PrepareForWriting() { sample_buffer_.resize(size_of_data_record_); } -size_t Cg3Block::ReadDataRecord(std::FILE *file, +uint64_t Cg3Block::ReadDataRecord(std::streambuf& buffer, const IDataGroup ¬ifier) const { - size_t count; + uint64_t count; // Normal fixed length records - size_t record_size = size_of_data_record_; + std::size_t record_size = size_of_data_record_; std::vector record(record_size, 0); - count = std::fread(record.data(), 1, record.size(), file); - size_t sample = Sample(); + count = buffer.sgetn( + reinterpret_cast(record.data()), record.size()); + uint64_t sample = Sample(); if (sample < NofSamples()) { const bool continue_reading = notifier.NotifySampleObservers(sample, RecordId(), record); IncrementSample(); @@ -253,12 +254,12 @@ size_t Cg3Block::ReadDataRecord(std::FILE *file, return count; } -size_t Cg3Block::ReadRangeDataRecord(std::FILE *file, +uint64_t Cg3Block::ReadRangeDataRecord(std::streambuf& buffer, const IDataGroup ¬ifier, DgRange& range) const { - size_t count; - const size_t sample = Sample(); - const size_t next_sample = sample + 1; + uint64_t count; + const uint64_t sample = Sample(); + const uint64_t next_sample = sample + 1; const size_t record_size = size_of_data_record_; CgRange* cg_range = range.GetCgRange(RecordId()); if (cg_range == nullptr) { @@ -268,7 +269,7 @@ size_t Cg3Block::ReadRangeDataRecord(std::FILE *file, if (!cg_range->IsUsed() || next_sample < range.MinSample() || next_sample > range.MaxSample()) { - count = StepFilePosition(file, record_size); + count = StepFilePosition(buffer, record_size); if (sample < NofSamples()) { IncrementSample(); @@ -281,7 +282,8 @@ size_t Cg3Block::ReadRangeDataRecord(std::FILE *file, std::vector record(record_size, 0); - count = std::fread(record.data(), 1, record.size(), file); + count = buffer.sgetn( + reinterpret_cast(record.data()), record.size()); if (sample < NofSamples()) { const bool continue_reading = @@ -302,10 +304,10 @@ IChannel *Cg3Block::CreateChannel() { return cn_list_.empty() ? nullptr : cn_list_.back().get(); } -void Cg3Block::ReadData(std::FILE *file) const { +void Cg3Block::ReadData(std::streambuf& buffer) const { for (const auto& sr3 : Sr3()) { if (!sr3) { continue;} - sr3->ReadData(file); + sr3->ReadData(buffer); } } diff --git a/mdflib/src/cg3block.h b/mdflib/src/cg3block.h index f07dcc91..36637c1e 100644 --- a/mdflib/src/cg3block.h +++ b/mdflib/src/cg3block.h @@ -42,13 +42,13 @@ class Cg3Block : public MdfBlock, public IChannelGroup { [[nodiscard]] std::string Comment() const override; MdfBlock* Find(int64_t index) const override; void GetBlockProperty(BlockPropertyList& dest) const override; - size_t Read(std::FILE* file) override; - size_t Write(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; - void ReadCnList(std::FILE* file); - void ReadSrList(std::FILE* file); + void ReadCnList(std::streambuf& buffer); + void ReadSrList(std::streambuf& buffer); - void ReadData(std::FILE* file) const; + void ReadData(std::streambuf& buffer) const; uint16_t RecordSize() const { return size_of_data_record_; } @@ -61,8 +61,8 @@ class Cg3Block : public MdfBlock, public IChannelGroup { [[nodiscard]] std::vector& SampleBuffer() const { return sample_buffer_; } - size_t ReadDataRecord(std::FILE* file, const IDataGroup& notifier) const; - size_t ReadRangeDataRecord(std::FILE* file, const IDataGroup& notifier, + uint64_t ReadDataRecord(std::streambuf& buffer, const IDataGroup& notifier) const; + uint64_t ReadRangeDataRecord(std::streambuf& buffer, const IDataGroup& notifier, DgRange& range) const; void PrepareForWriting(); diff --git a/mdflib/src/cg4block.cpp b/mdflib/src/cg4block.cpp index fca9986d..d42ec462 100644 --- a/mdflib/src/cg4block.cpp +++ b/mdflib/src/cg4block.cpp @@ -156,29 +156,29 @@ void Cg4Block::GetBlockProperty(BlockPropertyList &dest) const { } } -size_t Cg4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - bytes += ReadNumber(file, record_id_); - bytes += ReadNumber(file, nof_samples_); - bytes += ReadNumber(file, flags_); - bytes += ReadNumber(file, path_separator_); +uint64_t Cg4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadNumber(buffer, record_id_); + bytes += ReadNumber(buffer, nof_samples_); + bytes += ReadNumber(buffer, flags_); + bytes += ReadNumber(buffer, path_separator_); std::vector reserved; - bytes += ReadByte(file, reserved, 4); - bytes += ReadNumber(file, nof_data_bytes_); - bytes += ReadNumber(file, nof_invalid_bytes_); + bytes += ReadByte(buffer, reserved, 4); + bytes += ReadNumber(buffer, nof_data_bytes_); + bytes += ReadNumber(buffer, nof_invalid_bytes_); - acquisition_name_ = ReadTx4(file, kIndexName); + acquisition_name_ = ReadTx4(buffer, kIndexName); if (Link(kIndexSi) > 0) { - SetFilePosition(file, Link(kIndexSi)); + SetFilePosition(buffer, Link(kIndexSi)); si_block_ = std::make_unique(); si_block_->Init(*this); - si_block_->Read(file); + si_block_->Read(buffer); } - ReadMdComment(file, kIndexMd); + ReadMdComment(buffer, kIndexMd); return bytes; } -size_t Cg4Block::Write(std::FILE *file) { +uint64_t Cg4Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // True if already written to file const auto master = (flags_ & CgFlag::RemoteMaster) != 0; const auto vlsd = (flags_ & CgFlag::VlsdChannel) != 0; @@ -192,52 +192,52 @@ size_t Cg4Block::Write(std::FILE *file) { } - WriteLink4List(file, cn_list_, kIndexCn, + WriteLink4List(buffer, cn_list_, kIndexCn, UpdateOption::DoNotUpdateWrittenBlock); - WriteTx4(file, kIndexName, acquisition_name_); - WriteBlock4(file, si_block_, kIndexSi); - WriteLink4List(file, sr_list_, kIndexSr, + WriteTx4(buffer, kIndexName, acquisition_name_); + WriteBlock4(buffer, si_block_, kIndexSi); + WriteLink4List(buffer, sr_list_, kIndexSr, UpdateOption::DoNotUpdateWrittenBlock); - WriteMdComment(file, kIndexMd); + WriteMdComment(buffer, kIndexMd); // ToDo: Remote master handling - uint64_t bytes = update ? MdfBlock::Update(file) : MdfBlock::Write(file); + uint64_t bytes = update ? MdfBlock::Update(buffer) : MdfBlock::Write(buffer); if (update) { // Update number of samples if (nof_samples_position_ > 0) { - SetFilePosition(file, nof_samples_position_); - WriteNumber(file, nof_samples_); + SetFilePosition(buffer, nof_samples_position_); + WriteNumber(buffer, nof_samples_); } // Update VLSD size (which is a 64-bit value, low 32-bit) if (nof_data_position_ > 0) { - SetFilePosition(file, nof_data_position_); - WriteNumber(file, nof_data_bytes_); + SetFilePosition(buffer, nof_data_position_); + WriteNumber(buffer, nof_data_bytes_); } // Update VLSD size (which is a 64-bit value, high 32-bit) if (nof_invalid_position_ > 0) { - SetFilePosition(file, nof_invalid_position_); - WriteNumber(file, nof_invalid_bytes_); + SetFilePosition(buffer, nof_invalid_position_); + WriteNumber(buffer, nof_invalid_bytes_); } bytes = block_length_; } else { - bytes += WriteNumber(file, record_id_); - nof_samples_position_ = GetFilePosition(file); - bytes += WriteNumber(file, nof_samples_); - bytes += WriteNumber(file, flags_); - bytes += WriteNumber(file, path_separator_); - bytes += WriteBytes(file, 4); + bytes += WriteNumber(buffer, record_id_); + nof_samples_position_ = GetFilePosition(buffer); + bytes += WriteNumber(buffer, nof_samples_); + bytes += WriteNumber(buffer, flags_); + bytes += WriteNumber(buffer, path_separator_); + bytes += WriteBytes(buffer, 4); // Save the nof data and invalid bytes in case of a VLSD group. // Number data bytes is the lower 32-bit and number invalid bytes is the // 32-bit higher value. if (vlsd) { - nof_data_position_ = GetFilePosition(file); + nof_data_position_ = GetFilePosition(buffer); } - bytes += WriteNumber(file, nof_data_bytes_); + bytes += WriteNumber(buffer, nof_data_bytes_); if (vlsd) { - nof_invalid_position_ = GetFilePosition(file); + nof_invalid_position_ = GetFilePosition(buffer); } - bytes += WriteNumber(file, nof_invalid_bytes_); - UpdateBlockSize(file, bytes); + bytes += WriteNumber(buffer, nof_invalid_bytes_); + UpdateBlockSize(buffer, bytes); // Must scan through the channels and detect if any MLSD channel exist // and update its signal index. First need to find the length channel @@ -248,7 +248,7 @@ size_t Cg4Block::Write(std::FILE *file) { const auto block_position = data_length->Index(); for (auto* channel : cn_list) { if (channel != nullptr && channel->Type() == ChannelType::MaxLength) { - dynamic_cast(channel)->UpdateDataLink(file, block_position); + dynamic_cast(channel)->UpdateDataLink(buffer, block_position); } } } @@ -257,12 +257,12 @@ size_t Cg4Block::Write(std::FILE *file) { return bytes; } -void Cg4Block::ReadCnList(std::FILE *file) { - ReadLink4List(file, cn_list_, kIndexCn); +void Cg4Block::ReadCnList(std::streambuf& buffer) { + ReadLink4List(buffer, cn_list_, kIndexCn); } -void Cg4Block::ReadSrList(std::FILE *file) { - ReadLink4List(file, sr_list_, kIndexSr); +void Cg4Block::ReadSrList(std::streambuf& buffer) { + ReadLink4List(buffer, sr_list_, kIndexSr); } MdfBlock *Cg4Block::Find(int64_t index) const { @@ -295,18 +295,20 @@ MdfBlock *Cg4Block::Find(int64_t index) const { return MdfBlock::Find(index); } -size_t Cg4Block::ReadDataRecord(std::FILE *file, +uint64_t Cg4Block::ReadDataRecord(std::streambuf& buffer, const IDataGroup ¬ifier) const { - size_t count = 0; + uint64_t count = 0; if (flags_ & CgFlag::VlsdChannel) { // This is normally used for string and the CG block only include one signal uint32_t length = 0; - count += ReadNumber(file, length); + count += ReadNumber(buffer, length); std::vector record(length, 0); if (length > 0) { - count += std::fread(record.data(), 1, length, file); + count += buffer.sgetn( + reinterpret_cast(record.data()), + length); } - const size_t sample = Sample(); + const uint64_t sample = Sample(); if (sample < NofSamples()) { const bool continue_reading = notifier.NotifySampleObservers(sample, RecordId(), record); @@ -319,15 +321,16 @@ size_t Cg4Block::ReadDataRecord(std::FILE *file, // Normal fixed length records const size_t record_size = nof_data_bytes_ + nof_invalid_bytes_; std::vector record(record_size, 0); - count = std::fread(record.data(), 1, record.size(), file); - const size_t sample = Sample(); + count = buffer.sgetn( + reinterpret_cast(record.data()), + static_cast(record.size()) ); + const uint64_t sample = Sample(); if (sample < NofSamples()) { const bool continue_reading = notifier.NotifySampleObservers(sample, RecordId(), record); IncrementSample(); if (!continue_reading) { return 0; } - } } return count; @@ -395,9 +398,9 @@ void Cg4Block::UpdateVlsdSize(uint64_t nof_data_bytes) { } } -size_t Cg4Block::StepRecord(std::FILE *file) const { +uint64_t Cg4Block::StepRecord(std::streambuf& buffer) const { const size_t record_size = nof_data_bytes_ + nof_invalid_bytes_; - return StepFilePosition(file, record_size); + return StepFilePosition(buffer, record_size); } IChannel *Cg4Block::CreateChannel() { @@ -422,8 +425,8 @@ void Cg4Block::PrepareForWriting() { // Calculates number of data bytes. Note that some channels may // be a so-called array channel. Little bit complicated but the // referenced channel have a channel array (CA) block. - size_t byte_offset = 0; - size_t invalid_bit_offset = 0; + uint64_t byte_offset = 0; + uint64_t invalid_bit_offset = 0; for (const auto &channel : cn_list_) { if (!channel) { continue; @@ -466,8 +469,8 @@ void Cg4Block::PrepareForWriting() { } } -void Cg4Block::WriteSample(FILE *file, uint8_t record_id_size, - const std::vector &buffer) { +void Cg4Block::WriteSample(std::streambuf& buffer, uint8_t record_id_size, + const std::vector &source) { switch (record_id_size) { case 0: // No Record ID to store @@ -475,34 +478,35 @@ void Cg4Block::WriteSample(FILE *file, uint8_t record_id_size, case 1: { const auto id = static_cast(RecordId()); - WriteNumber(file, id); + WriteNumber(buffer, id); break; } case 2: { const auto id = static_cast(RecordId()); - WriteNumber(file, id); + WriteNumber(buffer, id); break; } case 4: { const auto id = static_cast(RecordId()); - WriteNumber(file, id); + WriteNumber(buffer, id); break; } default: { const auto id = RecordId(); - WriteNumber(file, id); + WriteNumber(buffer, id); break; } } - const size_t bytes = fwrite(buffer.data(), 1, - buffer.size(), file); - if (bytes != buffer.size()) { + const uint64_t bytes = buffer.sputn( + reinterpret_cast(source.data()), + static_cast(source.size())); + if (bytes != source.size()) { MDF_ERROR() << "Failed to write a sample data. Written : " - << bytes << "(" << buffer.size() << ")"; + << bytes << "(" << source.size() << ")"; } IncrementSample(); // Increment internal sample counter NofSamples(Sample()); @@ -551,8 +555,8 @@ void Cg4Block::WriteCompressedSample(std::vector& dest, NofSamples(Sample()); } -uint64_t Cg4Block::WriteVlsdSample(FILE *file, uint8_t record_id_size, - const std::vector &buffer) { +uint64_t Cg4Block::WriteVlsdSample(std::streambuf& buffer, uint8_t record_id_size, + const std::vector &source) { const uint64_t vlsd_index = vlsd_index_; // Temporary store the old index uint64_t total_count = nof_invalid_bytes_; total_count <<= 32; @@ -565,36 +569,38 @@ uint64_t Cg4Block::WriteVlsdSample(FILE *file, uint8_t record_id_size, case 1: { const auto id = static_cast(RecordId()); - WriteNumber(file, id); + WriteNumber(buffer, id); break; } case 2: { const auto id = static_cast(RecordId()); - WriteNumber(file, id); + WriteNumber(buffer, id); break; } case 4: { const auto id = static_cast(RecordId()); - WriteNumber(file, id); + WriteNumber(buffer, id); break; } default: { const auto id = RecordId(); - WriteNumber(file, id); + WriteNumber(buffer, id); break; } } - const auto length = static_cast(buffer.size()); + const auto length = static_cast(source.size()); const LittleBuffer buff(length); - const auto length_count = fwrite(buff.data(), - 1, sizeof(length), file); + const auto length_count = buffer.sputn( + reinterpret_cast(buff.data()), + sizeof(length) ); // total_count += length_count; - const auto buffer_count = fwrite(buffer.data(), - 1, buffer.size(), file); + const auto buffer_count = buffer.sputn( + reinterpret_cast(source.data()), + static_cast(source.size()) ); total_count += buffer_count; IncrementSample(); // Increment internal sample counter NofSamples(Sample()); diff --git a/mdflib/src/cg4block.h b/mdflib/src/cg4block.h index 007226ca..f405674c 100644 --- a/mdflib/src/cg4block.h +++ b/mdflib/src/cg4block.h @@ -64,20 +64,20 @@ class Cg4Block : public MdfBlock, public IChannelGroup { const Si4Block* Source() const { return si_block_.get(); } - size_t Read(std::FILE* file) override; - void ReadCnList(std::FILE* file); - void ReadSrList(std::FILE* file); + uint64_t Read(std::streambuf& buffer) override; + void ReadCnList(std::streambuf& buffer); + void ReadSrList(std::streambuf& buffer); - size_t ReadDataRecord(std::FILE* file, const IDataGroup& notifier) const; + uint64_t ReadDataRecord(std::streambuf& buffer, const IDataGroup& notifier) const; std::vector& SampleBuffer() const { return sample_buffer_; } - size_t Write(std::FILE* file) override; + uint64_t Write(std::streambuf& buffer) override; ISourceInformation* CreateSourceInformation() override; ISourceInformation* SourceInformation() const override; void UpdateCycleCounter(uint64_t nof_samples); void UpdateVlsdSize(uint64_t nof_data_bytes); - size_t StepRecord(std::FILE *file) const; + uint64_t StepRecord(std::streambuf& buffer) const; [[nodiscard]] IMetaData* CreateMetaData() override { return MdfBlock::CreateMetaData(); @@ -93,13 +93,15 @@ class Cg4Block : public MdfBlock, public IChannelGroup { uint32_t NofInvalidBytes() const { return nof_invalid_bytes_; } - void WriteSample(FILE* file, uint8_t record_id_size, - const std::vector& buffer); + void WriteSample(std::streambuf& buffer, uint8_t record_id_size, + const std::vector& source); + void WriteCompressedSample(std::vector& dest, uint8_t record_id_size, const std::vector& buffer); - [[nodiscard]] uint64_t WriteVlsdSample(FILE* file, uint8_t record_id_size, - const std::vector& buffer); + [[nodiscard]] uint64_t WriteVlsdSample(std::streambuf& buffer, uint8_t record_id_size, + const std::vector& source); + [[nodiscard]] uint64_t WriteCompressedVlsdSample(std::vector& dest, uint8_t record_id_size, const std::vector& buffer); diff --git a/mdflib/src/ch4block.cpp b/mdflib/src/ch4block.cpp index 30280aee..c44ee8e5 100644 --- a/mdflib/src/ch4block.cpp +++ b/mdflib/src/ch4block.cpp @@ -50,24 +50,24 @@ void Ch4Block::GetBlockProperty(BlockPropertyList &dest) const { } } -size_t Ch4Block::Read(std::FILE *file) { // NOLINT - size_t bytes = ReadHeader4(file); - bytes += ReadNumber(file, nof_elements_); - bytes += ReadNumber(file, type_); +uint64_t Ch4Block::Read(std::streambuf& buffer) { // NOLINT + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadNumber(buffer, nof_elements_); + bytes += ReadNumber(buffer, type_); std::vector reserved; - bytes += ReadByte(file, reserved, 3); + bytes += ReadByte(buffer, reserved, 3); - name_ = ReadTx4(file, kIndexTx); - ReadMdComment(file, kIndexMd); - ReadLink4List(file, ch_list_, kIndexCh); + name_ = ReadTx4(buffer, kIndexTx); + ReadMdComment(buffer, kIndexMd); + ReadLink4List(buffer, ch_list_, kIndexCh); return bytes; } -size_t Ch4Block::Write(std::FILE *file) { // NOLINT +uint64_t Ch4Block::Write(std::streambuf& buffer) { // NOLINT const auto update = FilePosition() > 0; if (update) { - WriteLink4List(file, ch_list_, kIndexCh, + WriteLink4List(buffer, ch_list_, kIndexCh, UpdateOption::DoNotUpdateWrittenBlock); return block_length_; } @@ -86,16 +86,16 @@ size_t Ch4Block::Write(std::FILE *file) { // NOLINT link_list_[index + 2] = element.channel != nullptr ? element.channel->Index() : 0; } - WriteTx4(file, kIndexTx, name_); - WriteMdComment(file, kIndexMd); - WriteLink4List(file, ch_list_, kIndexCh, + WriteTx4(buffer, kIndexTx, name_); + WriteMdComment(buffer, kIndexMd); + WriteLink4List(buffer, ch_list_, kIndexCh, UpdateOption::DoNotUpdateWrittenBlock); - size_t bytes = MdfBlock::Write(file); - bytes += WriteNumber(file, nof_elements_); - bytes += WriteNumber(file, type_); - bytes += WriteBytes(file, 3); - UpdateBlockSize(file, bytes); + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteNumber(buffer, nof_elements_); + bytes += WriteNumber(buffer, type_); + bytes += WriteBytes(buffer, 3); + UpdateBlockSize(buffer, bytes); return bytes; } diff --git a/mdflib/src/ch4block.h b/mdflib/src/ch4block.h index 137d386b..a9a3f58a 100644 --- a/mdflib/src/ch4block.h +++ b/mdflib/src/ch4block.h @@ -42,8 +42,8 @@ class Ch4Block : public MdfBlock, public IChannelHierarchy { [[nodiscard]] MdfBlock *Find(int64_t index) const override; void GetBlockProperty(BlockPropertyList &dest) const override; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; void FindReferencedBlocks(const Hd4Block &hd4); [[nodiscard]] IChannelHierarchy *CreateChannelHierarchy() override; diff --git a/mdflib/src/channelobserver.cpp b/mdflib/src/channelobserver.cpp index 1415340b..56cbb9ae 100644 --- a/mdflib/src/channelobserver.cpp +++ b/mdflib/src/channelobserver.cpp @@ -11,7 +11,7 @@ bool ChannelObserver>::GetSampleUnsigned( uint64_t sample, uint64_t &value, uint64_t array_index) const { const auto* channel_array = channel_.ChannelArray(); const auto array_size = channel_array != nullptr ? channel_array->NofArrayValues() : 1; - const auto sample_index = (sample * array_size) + array_index; + const auto sample_index = static_cast( (sample * array_size) + array_index ); value = 0; // value_list is a byte array return sample_index < valid_list_.size() && valid_list_[sample_index]; } @@ -22,7 +22,7 @@ bool ChannelObserver::GetSampleUnsigned(uint64_t sample, uint64_t array_index) const { const auto* channel_array = channel_.ChannelArray(); const auto array_size = channel_array != nullptr ? channel_array->NofArrayValues() : 1; - const auto sample_index = (sample * array_size) + array_index; + const auto sample_index = static_cast( (sample * array_size) + array_index ); // Convert the string to an unsigned value value = sample_index < value_list_.size() ? std::stoull(value_list_[sample_index]) : 0; return sample_index < valid_list_.size() && valid_list_[sample_index]; @@ -33,7 +33,7 @@ bool ChannelObserver>::GetSampleSigned( uint64_t sample, int64_t &value, uint64_t array_index) const { const auto* channel_array = channel_.ChannelArray(); const auto array_size = channel_array != nullptr ? channel_array->NofArrayValues() : 1; - const auto sample_index = (sample * array_size) + array_index; + const auto sample_index = static_cast( (sample * array_size) + array_index ); value = 0; // value_list is a byte array return sample_index < valid_list_.size() && valid_list_[sample_index]; } @@ -44,7 +44,7 @@ bool ChannelObserver::GetSampleSigned(uint64_t sample, uint64_t array_index) const { const auto* channel_array = channel_.ChannelArray(); const auto array_size = channel_array != nullptr ? channel_array->NofArrayValues() : 1; - const auto sample_index = (sample * array_size) + array_index; + const auto sample_index = static_cast( (sample * array_size) + array_index ); value = sample_index < value_list_.size() ? std::stoll(value_list_[sample_index]) : 0; return sample_index < valid_list_.size() && valid_list_[sample_index]; } @@ -54,7 +54,7 @@ bool ChannelObserver>::GetSampleFloat( uint64_t sample, double &value, uint64_t array_index) const { const auto* channel_array = channel_.ChannelArray(); const auto array_size = channel_array != nullptr ? channel_array->NofArrayValues() : 1; - const auto sample_index = (sample * array_size) + array_index; + const auto sample_index = static_cast((sample * array_size) + array_index); value = 0.0; // value_list is a byte array return sample_index < valid_list_.size() && valid_list_[sample_index]; } @@ -65,9 +65,9 @@ bool ChannelObserver::GetSampleFloat(uint64_t sample, uint64_t array_index) const { const auto* channel_array = channel_.ChannelArray(); const auto array_size = channel_array != nullptr ? channel_array->NofArrayValues() : 1; - const auto sample_index = (sample * array_size) + array_index; + const auto sample_index = static_cast( (sample * array_size) + array_index ); value = sample_index < value_list_.size() ? std::stod(value_list_[sample_index]) : 0; - return sample < valid_list_.size() && valid_list_[sample]; + return sample_index < valid_list_.size() && valid_list_[sample_index]; } template <> @@ -75,7 +75,7 @@ bool ChannelObserver>::GetSampleText( uint64_t sample, std::string &value, uint64_t array_index) const { const auto* channel_array = channel_.ChannelArray(); const auto array_size = channel_array != nullptr ? channel_array->NofArrayValues() : 1; - const auto sample_index = (sample * array_size) + array_index; + const auto sample_index = static_cast( (sample * array_size) + array_index ); // The value_list consist of byte arrays. Convert o std::ostringstream s; if (sample_index < value_list_.size()) { @@ -93,9 +93,9 @@ template <> bool ChannelObserver>::GetSampleByteArray( uint64_t sample, std::vector &value) const { if (sample < value_list_.size()) { - value = value_list_[sample]; + value = value_list_[static_cast(sample)]; } - return sample < valid_list_.size() && valid_list_[sample]; + return sample < valid_list_.size() && valid_list_[static_cast(sample)]; } } // namespace mdf::detail diff --git a/mdflib/src/channelobserver.h b/mdflib/src/channelobserver.h index af5f1e49..5212cb6b 100644 --- a/mdflib/src/channelobserver.h +++ b/mdflib/src/channelobserver.h @@ -44,11 +44,11 @@ class ChannelObserver : public IChannelObserver { const auto* channel_array = channel_.ChannelArray(); const auto array_size = channel_array != nullptr ? channel_array->NofArrayValues() : 1; - valid_list_.resize(group_.NofSamples() * array_size, false); - value_list_.resize(group.NofSamples() * array_size, T{}); + valid_list_.resize(static_cast(group_.NofSamples() * array_size), false); + value_list_.resize(static_cast(group.NofSamples() * array_size), T{}); if (channel_.Type() == ChannelType::VariableLength) { - offset_list_.resize(group.NofSamples() * array_size, 0); + offset_list_.resize(static_cast(group.NofSamples() * array_size), 0); } ChannelObserver::AttachObserver(); } @@ -89,7 +89,7 @@ class ChannelObserver : public IChannelObserver { case ChannelType::VirtualData: if (record_id_ == record_id) { for ( uint64_t array_index = 0; array_index < array_size; ++array_index) { - const auto sample_index = (sample * array_size) + array_index; + const auto sample_index = static_cast((sample * array_size) + array_index); valid = channel_.GetVirtualSample(sample, value); if (sample_index < value_list_.size()) { value_list_[sample_index] = value; @@ -175,7 +175,7 @@ bool ChannelObserver::GetSampleUnsigned(uint64_t sample, uint64_t array_index) const { const auto* channel_array = channel_.ChannelArray(); const auto array_size = channel_array != nullptr ? channel_array->NofArrayValues() : 1; - const auto sample_index = (sample * array_size) + array_index; + const auto sample_index = static_cast((sample * array_size) + array_index); value = sample_index < value_list_.size() ? static_cast(value_list_[sample_index]) : static_cast(T{}); return sample_index < valid_list_.size() && valid_list_[sample_index]; @@ -198,7 +198,7 @@ bool ChannelObserver::GetSampleSigned(uint64_t sample, uint64_t array_index) const { const auto* channel_array = channel_.ChannelArray(); const auto array_size = channel_array != nullptr ? channel_array->NofArrayValues() : 1; - const auto sample_index = (sample * array_size) + array_index; + const auto sample_index = static_cast((sample * array_size) + array_index); value = sample_index < value_list_.size() ? static_cast(value_list_[sample_index]) : 0; return sample_index < valid_list_.size() && valid_list_[sample_index]; } @@ -217,7 +217,7 @@ bool ChannelObserver::GetSampleFloat(uint64_t sample, double& value, uint64_t array_index) const { const auto* channel_array = channel_.ChannelArray(); const auto array_size = channel_array != nullptr ? channel_array->NofArrayValues() : 1; - const auto sample_index = (sample * array_size) + array_index; + const auto sample_index = static_cast( (sample * array_size) + array_index); value = sample_index < value_list_.size() ? static_cast(value_list_[sample_index]) : 0; return sample_index < valid_list_.size() && valid_list_[sample_index]; } @@ -238,7 +238,7 @@ bool ChannelObserver::GetSampleText(uint64_t sample, uint64_t array_index) const { const auto* channel_array = channel_.ChannelArray(); const auto array_size = channel_array != nullptr ? channel_array->NofArrayValues() : 1; - const auto sample_index = (sample * array_size) + array_index; + const auto sample_index = static_cast( (sample * array_size) + array_index ); try { std::ostringstream temp; if (sample_index < value_list_.size()) { @@ -246,7 +246,7 @@ bool ChannelObserver::GetSampleText(uint64_t sample, } value = temp.str(); - return sample_index < valid_list_.size() && valid_list_[sample]; + return sample_index < valid_list_.size() && valid_list_[sample_index]; } catch (const std::exception& ) {} return false; } @@ -261,7 +261,7 @@ template bool ChannelObserver::GetSampleByteArray(uint64_t sample, std::vector& value) const { value = {}; - return sample < valid_list_.size() && valid_list_[sample]; + return sample < valid_list_.size() && valid_list_[static_cast(sample)]; } // This specialized function is actually doing the work with byte arrays diff --git a/mdflib/src/cn3block.cpp b/mdflib/src/cn3block.cpp index 18f415dd..c93c1628 100644 --- a/mdflib/src/cn3block.cpp +++ b/mdflib/src/cn3block.cpp @@ -187,71 +187,71 @@ void Cn3Block::GetBlockProperty(BlockPropertyList &dest) const { dest.emplace_back("Byte Offset", std::to_string(byte_offset_)); } -size_t Cn3Block::Read(std::FILE *file) { - size_t bytes = ReadHeader3(file); - bytes += ReadLinks3(file, 5); - bytes += ReadNumber(file, channel_type_); - bytes += ReadStr(file, short_name_, 32); - bytes += ReadStr(file, description_, 128); - bytes += ReadNumber(file, start_offset_); - bytes += ReadNumber(file, nof_bits_); - bytes += ReadNumber(file, signal_type_); - bytes += ReadBool(file, range_valid_); - bytes += ReadNumber(file, min_); - bytes += ReadNumber(file, max_); - bytes += ReadNumber(file, sample_rate_); +uint64_t Cn3Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader3(buffer); + bytes += ReadLinks3(buffer, 5); + bytes += ReadNumber(buffer, channel_type_); + bytes += ReadStr(buffer, short_name_, 32); + bytes += ReadStr(buffer, description_, 128); + bytes += ReadNumber(buffer, start_offset_); + bytes += ReadNumber(buffer, nof_bits_); + bytes += ReadNumber(buffer, signal_type_); + bytes += ReadBool(buffer, range_valid_); + bytes += ReadNumber(buffer, min_); + bytes += ReadNumber(buffer, max_); + bytes += ReadNumber(buffer, sample_rate_); // The for loop handle earlier version of the MDF file for (int ii = 0; bytes < block_size_; ++ii) { switch (ii) { case 1: case 0: { uint32_t link = 0; - bytes += ReadNumber(file, link); + bytes += ReadNumber(buffer, link); link_list_.emplace_back(link); break; } case 2: - bytes += ReadNumber(file, byte_offset_); + bytes += ReadNumber(buffer, byte_offset_); break; default: { uint8_t temp = 0; - bytes += ReadNumber(file, temp); + bytes += ReadNumber(buffer, temp); break; } } } if (Link(kIndexCc) > 0) { - SetFilePosition(file, Link(kIndexCc)); + SetFilePosition(buffer, Link(kIndexCc)); cc_block_ = std::make_unique(); cc_block_->Init(*this); - cc_block_->Read(file); + cc_block_->Read(buffer); } if (Link(kIndexCe) > 0) { - SetFilePosition(file, Link(kIndexCe)); + SetFilePosition(buffer, Link(kIndexCe)); ce_block_ = std::make_unique(); ce_block_->Init(*this); - ce_block_->Read(file); + ce_block_->Read(buffer); } if (Link(kIndexCd) > 0) { - SetFilePosition(file, Link(kIndexCd)); + SetFilePosition(buffer, Link(kIndexCd)); cd_block_ = std::make_unique(); cd_block_->Init(*this); - cd_block_->Read(file); + cd_block_->Read(buffer); } - comment_ = ReadTx3(file, kIndexTx); - long_name_ = ReadTx3(file, kIndexTxLong); - display_name_ = ReadTx3(file, kIndexTxDisplay); + comment_ = ReadTx3(buffer, kIndexTx); + long_name_ = ReadTx3(buffer, kIndexTxLong); + display_name_ = ReadTx3(buffer, kIndexTxDisplay); return bytes; } -size_t Cn3Block::Write(std::FILE *file) { +uint64_t Cn3Block::Write(std::streambuf& buffer) { int64_t long_name_link = 0; int64_t display_name_link = 0; @@ -266,55 +266,55 @@ size_t Cn3Block::Write(std::FILE *file) { if (!long_name_.empty()) { Tx3Block tx(long_name_); tx.Init(*this); - tx.Write(file); + tx.Write(buffer); long_name_link = tx.FilePosition(); } if (!display_name_.empty()) { Tx3Block tx(display_name_); tx.Init(*this); - tx.Write(file); + tx.Write(buffer); display_name_link = tx.FilePosition(); } } - size_t bytes = update ? block_size_ : MdfBlock::Write(file); + uint64_t bytes = update ? block_size_ : MdfBlock::Write(buffer); if (!update) { - bytes += WriteNumber(file, channel_type_); - bytes += WriteStr(file, short_name_, 32); - bytes += WriteStr(file, description_, 128); - bytes += WriteNumber(file, start_offset_); - bytes += WriteNumber(file, nof_bits_); - bytes += WriteNumber(file, signal_type_); - bytes += WriteBool(file, range_valid_); - bytes += WriteNumber(file, min_); - bytes += WriteNumber(file, max_); - bytes += WriteNumber(file, sample_rate_); - bytes += WriteNumber(file, static_cast(long_name_link)); - bytes += WriteNumber(file, static_cast(display_name_link)); - bytes += WriteNumber(file, byte_offset_); + bytes += WriteNumber(buffer, channel_type_); + bytes += WriteStr(buffer, short_name_, 32); + bytes += WriteStr(buffer, description_, 128); + bytes += WriteNumber(buffer, start_offset_); + bytes += WriteNumber(buffer, nof_bits_); + bytes += WriteNumber(buffer, signal_type_); + bytes += WriteBool(buffer, range_valid_); + bytes += WriteNumber(buffer, min_); + bytes += WriteNumber(buffer, max_); + bytes += WriteNumber(buffer, sample_rate_); + bytes += WriteNumber(buffer, static_cast(long_name_link)); + bytes += WriteNumber(buffer, static_cast(display_name_link)); + bytes += WriteNumber(buffer, byte_offset_); } if (cc_block_ && Link(kIndexCc) <= 0) { - cc_block_->Write(file); - UpdateLink(file, kIndexCc, cc_block_->FilePosition()); + cc_block_->Write(buffer); + UpdateLink(buffer, kIndexCc, cc_block_->FilePosition()); } if (ce_block_ && Link(kIndexCe) <= 0) { - ce_block_->Write(file); - UpdateLink(file, kIndexCe, ce_block_->FilePosition()); + ce_block_->Write(buffer); + UpdateLink(buffer, kIndexCe, ce_block_->FilePosition()); } if (cd_block_ && Link(kIndexCd) <= 0) { - cd_block_->Write(file); - UpdateLink(file, kIndexCd, cd_block_->FilePosition()); + cd_block_->Write(buffer); + UpdateLink(buffer, kIndexCd, cd_block_->FilePosition()); } if (!comment_.empty() && Link(kIndexTx) <= 0) { Tx3Block tx(comment_); tx.Init(*this); - tx.Write(file); - UpdateLink(file, kIndexTx, tx.FilePosition()); + tx.Write(buffer); + UpdateLink(buffer, kIndexTx, tx.FilePosition()); } return bytes; diff --git a/mdflib/src/cn3block.h b/mdflib/src/cn3block.h index 8a8fea62..4f6fe298 100644 --- a/mdflib/src/cn3block.h +++ b/mdflib/src/cn3block.h @@ -57,8 +57,8 @@ class Cn3Block : public DataListBlock, public IChannel { [[nodiscard]] MdfBlock* Find(int64_t index) const override; void GetBlockProperty(BlockPropertyList& dest) const override; void Init(const MdfBlock& id_block) override; - size_t Read(std::FILE* file) override; - size_t Write(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; void AddCc3(std::unique_ptr& cc3); diff --git a/mdflib/src/cn4block.cpp b/mdflib/src/cn4block.cpp index 7c2a392b..4d220cbb 100644 --- a/mdflib/src/cn4block.cpp +++ b/mdflib/src/cn4block.cpp @@ -162,12 +162,12 @@ std::string MakeFlagString(uint32_t flag) { ///< Helper function that recursively copies all data bytes to a /// destination buffer. -size_t CopyDataToBuffer(const mdf::detail::MdfBlock *data, std::FILE *from_file, - std::vector &buffer, size_t &buffer_index) { +uint64_t CopyDataToBuffer(const mdf::detail::MdfBlock *data, std::streambuf& from_file, + std::vector &buffer, uint64_t &buffer_index) { if (data == nullptr) { return 0; } - size_t count = 0; + uint64_t count = 0; const auto *db = dynamic_cast(data); const auto *dl = dynamic_cast(data); if (db != nullptr) { @@ -186,8 +186,8 @@ namespace mdf::detail { Cn4Block::Cn4Block() { block_type_ = "##CN"; } -void Cn4Block::UpdateDataLink(std::FILE *file, int64_t position) { - UpdateLink(file, kIndexData, position); +void Cn4Block::UpdateDataLink(std::streambuf& buffer, int64_t position) { + UpdateLink(buffer, kIndexData, position); } int64_t Cn4Block::DataLink() const { return Link(kIndexData); } @@ -387,47 +387,47 @@ void Cn4Block::GetBlockProperty(BlockPropertyList &dest) const { } } -size_t Cn4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - bytes += ReadNumber(file, type_); - bytes += ReadNumber(file, sync_type_); - bytes += ReadNumber(file, data_type_); - bytes += ReadNumber(file, bit_offset_); - bytes += ReadNumber(file, byte_offset_); - bytes += ReadNumber(file, bit_count_); - bytes += ReadNumber(file, flags_); - bytes += ReadNumber(file, invalid_bit_pos_); - bytes += ReadNumber(file, precision_); +uint64_t Cn4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadNumber(buffer, type_); + bytes += ReadNumber(buffer, sync_type_); + bytes += ReadNumber(buffer, data_type_); + bytes += ReadNumber(buffer, bit_offset_); + bytes += ReadNumber(buffer, byte_offset_); + bytes += ReadNumber(buffer, bit_count_); + bytes += ReadNumber(buffer, flags_); + bytes += ReadNumber(buffer, invalid_bit_pos_); + bytes += ReadNumber(buffer, precision_); std::vector reserved; - bytes += ReadByte(file, reserved, 1); - bytes += ReadNumber(file, nof_attachments_); - bytes += ReadNumber(file, range_min_); - bytes += ReadNumber(file, range_max_); - bytes += ReadNumber(file, limit_min_); - bytes += ReadNumber(file, limit_max_); - bytes += ReadNumber(file, limit_ext_min_); - bytes += ReadNumber(file, limit_ext_max_); + bytes += ReadByte(buffer, reserved, 1); + bytes += ReadNumber(buffer, nof_attachments_); + bytes += ReadNumber(buffer, range_min_); + bytes += ReadNumber(buffer, range_max_); + bytes += ReadNumber(buffer, limit_min_); + bytes += ReadNumber(buffer, limit_max_); + bytes += ReadNumber(buffer, limit_ext_min_); + bytes += ReadNumber(buffer, limit_ext_max_); - name_ = ReadTx4(file, kIndexName); + name_ = ReadTx4(buffer, kIndexName); if (Link(kIndexCx) > 0) { - SetFilePosition(file, Link(kIndexCx)); - auto block_type = ReadBlockType(file); + SetFilePosition(buffer, Link(kIndexCx)); + auto block_type = ReadBlockType(buffer); if (cx_list_.empty() && (Link(kIndexCx) > 0)) { for (auto link = Link(kIndexCx); link > 0; /* No ++ here*/) { if (block_type == "CA") { auto ca_block = std::make_unique(); ca_block->Init(*this); - SetFilePosition(file, link); - ca_block->Read(file); + SetFilePosition(buffer, link); + ca_block->Read(buffer); link = ca_block->Link(0); cx_list_.emplace_back(std::move(ca_block)); } else if (block_type == "CN") { auto cn_block = std::make_unique(); cn_block->Init(*this); - SetFilePosition(file, link); - cn_block->Read(file); + SetFilePosition(buffer, link); + cn_block->Read(buffer); link = cn_block->Link(0); cx_list_.emplace_back(std::move(cn_block)); } @@ -436,31 +436,31 @@ size_t Cn4Block::Read(std::FILE *file) { } if (Link(kIndexSi) > 0) { - SetFilePosition(file, Link(kIndexSi)); + SetFilePosition(buffer, Link(kIndexSi)); si_block_ = std::make_unique(); si_block_->Init(*this); - si_block_->Read(file); + si_block_->Read(buffer); } if (Link(kIndexCc) > 0) { - SetFilePosition(file, Link(kIndexCc)); + SetFilePosition(buffer, Link(kIndexCc)); cc_block_ = std::make_unique(); cc_block_->Init(*this); cc_block_->ChannelDataType(data_type_); - cc_block_->Read(file); + cc_block_->Read(buffer); } // Need ot check if the data block is owned by this CN block or if it is a // reference only - ReadBlockList(file, kIndexData); + ReadBlockList(buffer, kIndexData); if (Link(kIndexUnit) > 0) { - SetFilePosition(file, Link(kIndexUnit)); + SetFilePosition(buffer, Link(kIndexUnit)); unit_ = std::make_unique(); unit_->Init(*this); - unit_->Read(file); + unit_->Read(buffer); } - ReadMdComment(file, kIndexMd); + ReadMdComment(buffer, kIndexMd); if (nof_attachments_ > 0) { // Need the header block to find the AT blocks by its file position. @@ -490,7 +490,7 @@ size_t Cn4Block::Read(std::FILE *file) { return bytes; } -size_t Cn4Block::Write(std::FILE *file) { +uint64_t Cn4Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // True if already written to file if (update) { return block_length_; @@ -506,16 +506,16 @@ size_t Cn4Block::Write(std::FILE *file) { } block_length_ += 1 + 1 + 1 + 1 + 4 + 4 + 4 + 4 + 1 + 1 + 2 + (6 * 8); link_list_.resize(8 + nof_attachments_ + (default_x ? 1 : 0), 0); - WriteLink4List(file, cx_list_, kIndexCx, + WriteLink4List(buffer, cx_list_, kIndexCx, UpdateOption::DoNotUpdateWrittenBlock); - WriteTx4(file, kIndexName, name_); - WriteBlock4(file, si_block_, kIndexSi); - WriteBlock4(file, cc_block_, kIndexCc); + WriteTx4(buffer, kIndexName, name_); + WriteBlock4(buffer, si_block_, kIndexSi); + WriteBlock4(buffer, cc_block_, kIndexCc); // The signal data shall not be stored here. Instead, the function // WriteSignalData() should be used. It is called by the Mdf(4)Writer class // when the measurement is finalized. - WriteBlock4(file, unit_, kIndexUnit); - WriteMdComment(file, kIndexMd); + WriteBlock4(buffer, unit_, kIndexUnit); + WriteMdComment(buffer, kIndexMd); for (size_t index_at = 0; index_at < attachment_list_.size(); ++index_at) { const auto index = 8 + index_at; const auto *at4 = attachment_list_[index_at]; @@ -531,26 +531,26 @@ size_t Cn4Block::Write(std::FILE *file) { link_list_[index] = cn4 != nullptr ? cn4->Index() : 0; } - auto bytes = MdfBlock::Write(file); - bytes += WriteNumber(file, type_); - bytes += WriteNumber(file, sync_type_); - bytes += WriteNumber(file, data_type_); - bytes += WriteNumber(file, bit_offset_); - bytes += WriteNumber(file, byte_offset_); - bytes += WriteNumber(file, bit_count_); - bytes += WriteNumber(file, flags_); - bytes += WriteNumber(file, invalid_bit_pos_); - bytes += WriteNumber(file, precision_); - - bytes += WriteBytes(file, 1); - bytes += WriteNumber(file, nof_attachments_); - bytes += WriteNumber(file, range_min_); - bytes += WriteNumber(file, range_max_); - bytes += WriteNumber(file, limit_min_); - bytes += WriteNumber(file, limit_max_); - bytes += WriteNumber(file, limit_ext_min_); - bytes += WriteNumber(file, limit_ext_max_); - UpdateBlockSize(file, bytes); + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteNumber(buffer, type_); + bytes += WriteNumber(buffer, sync_type_); + bytes += WriteNumber(buffer, data_type_); + bytes += WriteNumber(buffer, bit_offset_); + bytes += WriteNumber(buffer, byte_offset_); + bytes += WriteNumber(buffer, bit_count_); + bytes += WriteNumber(buffer, flags_); + bytes += WriteNumber(buffer, invalid_bit_pos_); + bytes += WriteNumber(buffer, precision_); + + bytes += WriteBytes(buffer, 1); + bytes += WriteNumber(buffer, nof_attachments_); + bytes += WriteNumber(buffer, range_min_); + bytes += WriteNumber(buffer, range_max_); + bytes += WriteNumber(buffer, limit_min_); + bytes += WriteNumber(buffer, limit_max_); + bytes += WriteNumber(buffer, limit_ext_min_); + bytes += WriteNumber(buffer, limit_ext_max_); + UpdateBlockSize(buffer, bytes); return bytes; } @@ -589,20 +589,20 @@ MdfBlock *Cn4Block::Find(int64_t index) const { return DataListBlock::Find(index); } -void Cn4Block::ReadSignalData(std::FILE *file) const { - const size_t count = DataSize(); +void Cn4Block::ReadSignalData(std::streambuf& buffer) const { + const uint64_t count = DataSize(); - size_t index = 0; - data_list_.resize(count, 0); + uint64_t index = 0; + data_list_.resize(static_cast(count), 0); // The block list should only contain one block. // A SD block is uncompressed data block for (const auto &block : block_list_) { const auto *data_list = dynamic_cast(block.get()); const auto *data_block = dynamic_cast(block.get()); if (data_list != nullptr) { - data_list->CopyDataToBuffer(file, data_list_, index); + data_list->CopyDataToBuffer(buffer, data_list_, index); } else if (data_block != nullptr) { - data_block->CopyDataToBuffer(file, data_list_, index); + data_block->CopyDataToBuffer(buffer, data_list_, index); } } } @@ -645,7 +645,7 @@ bool Cn4Block::GetTextValue(const std::vector &record_buffer, if (index + 4 > data_list_.size()) { return false; } - const LittleBuffer length(data_list_, index); + const LittleBuffer length(data_list_, static_cast(index) ); try { temp.resize(length.value(), 0); } catch (const std::exception&) { @@ -770,7 +770,7 @@ bool Cn4Block::GetByteArrayValue(const std::vector &record_buffer, if (index + 4 > data_list_.size()) { return false; } - const LittleBuffer length(data_list_, index); + const LittleBuffer length(data_list_, static_cast(index) ); try { dest.resize(length.value(), 0); } catch (const std::exception&) { @@ -784,12 +784,12 @@ bool Cn4Block::GetByteArrayValue(const std::vector &record_buffer, } else { try { - dest.resize(nof_bytes, 0); + dest.resize(static_cast(nof_bytes), 0); } catch (const std::exception&) { return false; // Return invalid value } if (offset + nof_bytes <= record_buffer.size()) { - memcpy(dest.data(), record_buffer.data() + offset, nof_bytes); + memcpy(dest.data(), record_buffer.data() + offset, static_cast(nof_bytes) ); } else { valid = false; } @@ -1011,7 +1011,7 @@ void Cn4Block::Flags(uint32_t flags) {flags_ = flags; } uint32_t Cn4Block::Flags() const { return flags_; } -void Cn4Block::PrepareForWriting(size_t offset) { +void Cn4Block::PrepareForWriting(uint64_t offset) { bit_offset_ = 0; byte_offset_ = static_cast(offset); data_list_.clear(); // Temporary storage of signal data (SD) @@ -1170,7 +1170,7 @@ bool Cn4Block::GetValid(const std::vector &record_buffer, bool valid = true; if (Flags() & CnFlag::InvalidValid && cg_block_ != nullptr) { const auto invalid_pos = invalid_bit_pos_ + array_index; - const auto byte_offset = cg_block_->NofDataBytes() + (invalid_pos / 8); + const auto byte_offset = static_cast( cg_block_->NofDataBytes() + (invalid_pos / 8) ); const auto bit_offset = invalid_pos % 8; const uint8_t mask = 0x01 << bit_offset; if (byte_offset < record_buffer.size()) { @@ -1180,31 +1180,31 @@ bool Cn4Block::GetValid(const std::vector &record_buffer, return valid; } -size_t Cn4Block::WriteSignalData(std::FILE *file, bool compress) { - size_t bytes = 0; +uint64_t Cn4Block::WriteSignalData(std::streambuf& buffer, bool compress) { + uint64_t bytes = 0; - if (file == nullptr || Type() == ChannelType::MaxLength || + if (Type() == ChannelType::MaxLength || (Type() == ChannelType::VariableLength && VlsdRecordId() > 0) ) { // Signal data is updated elsewhere return 0; } if (data_list_.empty()) { - UpdateLink(file, kIndexData, 0); // No data link + UpdateLink(buffer, kIndexData, 0); // No data link } else if (!compress || data_list_.size() <= 100 ){ // Store as SD block auto sd4 = std::make_unique(); sd4->Data(data_list_); - bytes = sd4->Write(file); - UpdateLink(file, kIndexData,sd4->FilePosition()); + bytes = sd4->Write(buffer); + UpdateLink(buffer, kIndexData,sd4->FilePosition()); } else if (data_list_.size() <= kMaxDataSize) { // Compress data // Store DZ (SD) block auto dz4 = std::make_unique(); dz4->OrigBlockType("SD"); dz4->Type(Dz4ZipType::Deflate); dz4->Data(data_list_); // Compress and set up the sizes - bytes = dz4->Write(file); - UpdateLink(file, kIndexData,dz4->FilePosition()); + bytes = dz4->Write(buffer); + UpdateLink(buffer, kIndexData,dz4->FilePosition()); } else { // Store HL + DL + DZ blocks auto hl4 = std::make_unique(); @@ -1212,31 +1212,31 @@ size_t Cn4Block::WriteSignalData(std::FILE *file, bool compress) { hl4->Type(Hl4ZipType::Deflate); auto dl4 = std::make_unique(); - std::vector buffer; - buffer.reserve(kMaxDataSize); + std::vector data; + data.reserve(kMaxDataSize); dl4->Flags(Dl4Flags::EqualLength); dl4->EqualLength(kMaxDataSize); for (const auto in_byte : data_list_) { - buffer.push_back(in_byte); - if (buffer.size() + 1 > kMaxDataSize) { + data.push_back(in_byte); + if (data.size() + 1 > kMaxDataSize) { auto dz4 = std::make_unique(); dz4->OrigBlockType("SD"); dz4->Type(Dz4ZipType::Deflate); - dz4->Data(buffer); // Compress and set up the sizes + dz4->Data(data); // Compress and set up the sizes auto& block_list = dl4->DataBlockList(); block_list.push_back(std::move(dz4)); - buffer.clear(); - buffer.reserve(kMaxDataSize); + data.clear(); + data.reserve(kMaxDataSize); } } - if (!buffer.empty()) { + if (!data.empty()) { auto dz4 = std::make_unique(); dz4->OrigBlockType("SD"); dz4->Type(Dz4ZipType::Deflate); - dz4->Data(buffer); // Compress and set up the sizes + dz4->Data(data); // Compress and set up the sizes auto& block_list = dl4->DataBlockList(); block_list.push_back(std::move(dz4)); @@ -1244,8 +1244,8 @@ size_t Cn4Block::WriteSignalData(std::FILE *file, bool compress) { auto& top_list = hl4->DataBlockList(); top_list.push_back(std::move(dl4)); - bytes = hl4->Write(file); - UpdateLink(file, kIndexData,hl4->FilePosition()); + bytes = hl4->Write(buffer); + UpdateLink(buffer, kIndexData,hl4->FilePosition()); } return bytes; } diff --git a/mdflib/src/cn4block.h b/mdflib/src/cn4block.h index daae39b3..d0b7ffda 100644 --- a/mdflib/src/cn4block.h +++ b/mdflib/src/cn4block.h @@ -67,10 +67,10 @@ class Cn4Block : public DataListBlock, public IChannel { void GetBlockProperty(BlockPropertyList& dest) const override; [[nodiscard]] MdfBlock* Find(int64_t index) const override; - size_t Read(std::FILE* file) override; - size_t Write(std::FILE* file) override; - void ReadSignalData(std::FILE* file) const; ///< Reads in (VLSD) channel data (SD) - size_t WriteSignalData(std::FILE* file, bool compress); + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; + void ReadSignalData(std::streambuf& buffer) const; ///< Reads in (VLSD) channel data (SD) + uint64_t WriteSignalData(std::streambuf& buffer, bool compress); void Init(const MdfBlock& id_block) override; @@ -84,7 +84,7 @@ class Cn4Block : public DataListBlock, public IChannel { void ClearData() const { data_list_.clear(); } const std::vector& DataList() const { return data_list_; } - void UpdateDataLink(std::FILE *file, int64_t position); + void UpdateDataLink(std::streambuf& buffer, int64_t position); [[nodiscard]] int64_t DataLink() const; [[nodiscard]] std::vector AtLinkList() const; @@ -109,8 +109,8 @@ class Cn4Block : public DataListBlock, public IChannel { [[nodiscard]] ISourceInformation *SourceInformation() const override; [[nodiscard]] ISourceInformation* CreateSourceInformation() override; - void PrepareForWriting(size_t offset); - void SetInvalidOffset(size_t bit_offset) { + void PrepareForWriting(uint64_t offset); + void SetInvalidOffset(uint64_t bit_offset) { invalid_bit_pos_ = static_cast(bit_offset); } diff --git a/mdflib/src/datablock.cpp b/mdflib/src/datablock.cpp index 69caf436..3efc6722 100644 --- a/mdflib/src/datablock.cpp +++ b/mdflib/src/datablock.cpp @@ -7,50 +7,50 @@ #include namespace mdf::detail { -size_t DataBlock::CopyDataToFile(std::FILE *from_file, - std::FILE *to_file) const { - if (from_file == nullptr || to_file == nullptr) { - throw std::invalid_argument("File pointers may not be null"); - } - +uint64_t DataBlock::CopyDataToFile(std::streambuf& from_file, + std::streambuf& to_file) const { SetFilePosition(from_file, DataPosition()); - auto data_size = DataSize(); + uint64_t data_size = DataSize(); if (data_size == 0) { return 0; } - size_t count = 0; - std::array temp{}; - size_t bytes_to_read = std::min(data_size, temp.size()); - for (auto reads = fread(temp.data(), 1, bytes_to_read, from_file); + uint64_t count = 0; + std::array temp{}; + uint64_t bytes_to_read = std::min(data_size, static_cast(temp.size()) ); + for (uint64_t reads = from_file.sgetn(temp.data(), + static_cast(bytes_to_read)); reads > 0 && bytes_to_read > 0 && data_size > 0; - reads = fread(temp.data(), 1, bytes_to_read, from_file)) { - const auto writes = fwrite(temp.data(), 1, reads, to_file); + reads = from_file.sgetn(temp.data(), + static_cast(bytes_to_read) )) { + const uint64_t writes = to_file.sputn(temp.data(), + static_cast(reads)); count += writes; if (writes != reads) { break; } data_size -= reads; - bytes_to_read = std::min(data_size, temp.size()); + bytes_to_read = std::min(data_size, static_cast(temp.size()) ); } return count; } -size_t DataBlock::CopyDataToBuffer(std::FILE *from_file, - std::vector &buffer, - size_t &buffer_index) const { - if (from_file == nullptr) { - throw std::invalid_argument("File pointers may not be null"); - } - SetFilePosition(from_file, DataPosition()); - const auto data_size = DataSize(); +uint64_t DataBlock::CopyDataToBuffer(std::streambuf& buffer, + std::vector &dest, + uint64_t &buffer_index) const { + SetFilePosition(buffer, DataPosition()); + const uint64_t data_size = DataSize(); if (data_size == 0) { return 0; } + if (dest.size() > (buffer_index + data_size)) { + throw std::runtime_error("Buffer overflow detected."); + } - const auto reads = - fread(buffer.data() + buffer_index, 1, data_size, from_file); + const uint64_t reads = buffer.sgetn( + reinterpret_cast(dest.data()) + buffer_index, + static_cast(data_size)); buffer_index += reads; return reads; } @@ -60,11 +60,12 @@ bool DataBlock::Data(const std::vector &data) { return true; } -size_t DataBlock::ReadData(std::FILE *file) { - if (data_position_ <= 0 || file == nullptr) { +uint64_t DataBlock::ReadData(std::streambuf& buffer) { + if (data_position_ <= 0) { return 0; } - return ReadByte(file, data_,DataSize()); + SetFilePosition(buffer,data_position_); + return ReadByte(buffer, data_,DataSize()); } } // namespace mdf::detail \ No newline at end of file diff --git a/mdflib/src/datablock.h b/mdflib/src/datablock.h index dd449663..1705e50a 100644 --- a/mdflib/src/datablock.h +++ b/mdflib/src/datablock.h @@ -14,14 +14,14 @@ class DataBlock : public MdfBlock { void DataPosition(int64_t position) { data_position_ = position; } [[nodiscard]] int64_t DataPosition() const { return data_position_; } - [[nodiscard]] virtual size_t DataSize() const = 0; - virtual size_t CopyDataToFile(std::FILE* from_file, std::FILE* to_file) const; - virtual size_t CopyDataToBuffer(std::FILE* from_file, + [[nodiscard]] virtual uint64_t DataSize() const = 0; + virtual uint64_t CopyDataToFile( std::streambuf& from_file, std::streambuf& to_file) const; + virtual uint64_t CopyDataToBuffer(std::streambuf& from_file, std::vector& buffer, - size_t& buffer_index) const; + uint64_t& buffer_index) const; virtual void DgBlock(IDataGroup* dg_block) { dg_block_ = dg_block;} - virtual size_t ReadData(std::FILE* file); + virtual uint64_t ReadData(std::streambuf& buffer); virtual bool Data(const std::vector& data); void ClearData() { data_.clear();} protected: diff --git a/mdflib/src/datalistblock.cpp b/mdflib/src/datalistblock.cpp index dfb5e113..8dfd3f6b 100644 --- a/mdflib/src/datalistblock.cpp +++ b/mdflib/src/datalistblock.cpp @@ -25,89 +25,89 @@ constexpr size_t kIndexNext = 0; namespace mdf::detail { -void DataListBlock::ReadBlockList(std::FILE* file, size_t data_index) { +void DataListBlock::ReadBlockList(std::streambuf& buffer, size_t data_index) { if (block_list_.empty() && Link(data_index) > 0) { - SetFilePosition(file, Link(data_index)); - std::string block_type = ReadBlockType(file); + SetFilePosition(buffer, Link(data_index)); + std::string block_type = ReadBlockType(buffer); - SetFilePosition(file, Link(data_index)); + SetFilePosition(buffer, Link(data_index)); if (block_type == "DT") { auto dt = std::make_unique(); dt->Init(*this); - dt->Read(file); + dt->Read(buffer); block_list_.emplace_back(std::move(dt)); } else if (block_type == "DZ") { auto dz = std::make_unique(); dz->Init(*this); - dz->Read(file); + dz->Read(buffer); block_list_.emplace_back(std::move(dz)); } else if (block_type == "DV") { auto dv_block = std::make_unique(); dv_block->Init(*this); - dv_block->Read(file); + dv_block->Read(buffer); block_list_.emplace_back(std::move(dv_block)); } else if (block_type == "DI") { auto di_block = std::make_unique(); di_block->Init(*this); - di_block->Read(file); + di_block->Read(buffer); block_list_.emplace_back(std::move(di_block)); } else if (block_type == "DL") { for (auto link = Link(data_index); link > 0; /* no increment here*/) { - SetFilePosition(file, link); + SetFilePosition(buffer, link); auto dl = std::make_unique(); dl->Init(*this); - dl->Read(file); + dl->Read(buffer); link = dl->Link(kIndexNext); block_list_.emplace_back(std::move(dl)); } } else if (block_type == "LD") { for (auto link = Link(data_index); link > 0; /* no increment here*/) { - SetFilePosition(file, link); + SetFilePosition(buffer, link); auto ld_block = std::make_unique(); ld_block->Init(*this); - ld_block->Read(file); + ld_block->Read(buffer); link = ld_block->Link(kIndexNext); block_list_.emplace_back(std::move(ld_block)); } } else if (block_type == "HL") { auto hl = std::make_unique(); hl->Init(*this); - hl->Read(file); + hl->Read(buffer); block_list_.emplace_back(std::move(hl)); } else if (block_type == "SR") { for (auto link = Link(data_index); link > 0; /* no increment here*/) { - SetFilePosition(file, link); + SetFilePosition(buffer, link); auto sr = std::make_unique(); sr->Init(*this); - sr->Read(file); + sr->Read(buffer); link = sr->Link(kIndexNext); block_list_.emplace_back(std::move(sr)); } } else if (block_type == "RD") { auto rd = std::make_unique(); rd->Init(*this); - rd->Read(file); + rd->Read(buffer); block_list_.emplace_back(std::move(rd)); } else if (block_type == "RV") { auto rv_block = std::make_unique(); rv_block->Init(*this); - rv_block->Read(file); + rv_block->Read(buffer); block_list_.emplace_back(std::move(rv_block)); } else if (block_type == "RI") { auto ri_block = std::make_unique(); ri_block->Init(*this); - ri_block->Read(file); + ri_block->Read(buffer); block_list_.emplace_back(std::move(ri_block)); } else if (block_type == "SD") { auto sd = std::make_unique(); sd->Init(*this); - sd->Read(file); + sd->Read(buffer); block_list_.emplace_back(std::move(sd)); } } } -void DataListBlock::ReadLinkList(std::FILE* file, size_t data_index, +void DataListBlock::ReadLinkList(std::streambuf& buffer, size_t data_index, uint32_t nof_link) { if (block_list_.empty()) { for (uint32_t ii = 0; ii < nof_link; ++ii) { @@ -115,59 +115,59 @@ void DataListBlock::ReadLinkList(std::FILE* file, size_t data_index, if (link <= 0) { continue; } - SetFilePosition(file, link); - std::string block_type = ReadBlockType(file); + SetFilePosition(buffer, link); + std::string block_type = ReadBlockType(buffer); - SetFilePosition(file, link); + SetFilePosition(buffer, link); // Note that we only read in data block that this list own. If it points // to a CG or CN block, this means that someone else is reading in this // block. if (block_type == "DT") { auto dt = std::make_unique(); dt->Init(*this); - dt->Read(file); + dt->Read(buffer); block_list_.emplace_back(std::move(dt)); } else if (block_type == "DZ") { auto dz = std::make_unique(); dz->Init(*this); - dz->Read(file); + dz->Read(buffer); block_list_.emplace_back(std::move(dz)); } else if (block_type == "DV") { auto dv_block = std::make_unique(); dv_block->Init(*this); - dv_block->Read(file); + dv_block->Read(buffer); block_list_.emplace_back(std::move(dv_block)); } else if (block_type == "DI") { auto di_block = std::make_unique(); di_block->Init(*this); - di_block->Read(file); + di_block->Read(buffer); block_list_.emplace_back(std::move(di_block)); } else if (block_type == "RD") { auto rd = std::make_unique(); rd->Init(*this); - rd->Read(file); + rd->Read(buffer); block_list_.emplace_back(std::move(rd)); } else if (block_type == "RV") { auto rv_block = std::make_unique(); rv_block->Init(*this); - rv_block->Read(file); + rv_block->Read(buffer); block_list_.emplace_back(std::move(rv_block)); } else if (block_type == "RI") { auto ri_block = std::make_unique(); ri_block->Init(*this); - ri_block->Read(file); + ri_block->Read(buffer); block_list_.emplace_back(std::move(ri_block)); } else if (block_type == "SD") { auto sd = std::make_unique(); sd->Init(*this); - sd->Read(file); + sd->Read(buffer); block_list_.emplace_back(std::move(sd)); } } } } -void DataListBlock::WriteBlockList(std::FILE* file, size_t first_index) { +void DataListBlock::WriteBlockList(std::streambuf& buffer, size_t first_index) { for (size_t index = 0; index < block_list_.size(); ++index) { auto* block = block_list_[index].get(); @@ -178,8 +178,8 @@ void DataListBlock::WriteBlockList(std::FILE* file, size_t first_index) { continue; } - block->Write(file); - UpdateLink(file, first_index + index, block->FilePosition()); + block->Write(buffer); + UpdateLink(buffer, first_index + index, block->FilePosition()); } } @@ -196,8 +196,8 @@ MdfBlock* DataListBlock::Find(int64_t index) const { return MdfBlock::Find(index); } -size_t DataListBlock::DataSize() const { // NOLINT - size_t count = 0; +uint64_t DataListBlock::DataSize() const { // NOLINT + uint64_t count = 0; for (const auto& block : block_list_) { if (!block) { continue; @@ -226,8 +226,9 @@ void DataListBlock::ClearData() { // NOLINT } } -void DataListBlock::CopyDataToBuffer(std::FILE *from_file, std::vector &buffer, - size_t &buffer_index) const { +void DataListBlock::CopyDataToBuffer(std::streambuf& from_file, + std::vector &buffer, + uint64_t &buffer_index) const { for (const auto &block : block_list_) { const auto *data_list = dynamic_cast(block.get()); const auto *data_block = dynamic_cast(block.get()); diff --git a/mdflib/src/datalistblock.h b/mdflib/src/datalistblock.h index d6cfd795..aafbd3fb 100644 --- a/mdflib/src/datalistblock.h +++ b/mdflib/src/datalistblock.h @@ -16,15 +16,15 @@ class DataListBlock : public MdfBlock { using BlockList = std::vector>; BlockList& DataBlockList() { return block_list_; } [[nodiscard]] const BlockList& DataBlockList() const { return block_list_; } - [[nodiscard]] virtual size_t DataSize() const; + [[nodiscard]] virtual uint64_t DataSize() const; [[nodiscard]] MdfBlock* Find(int64_t index) const override; - void ReadBlockList(std::FILE* file, size_t data_index); - void WriteBlockList(std::FILE* file, size_t data_index); + void ReadBlockList(std::streambuf& buffer, size_t data_index); + void WriteBlockList(std::streambuf& buffer, size_t data_index); - void ReadLinkList(std::FILE* file, size_t data_index, uint32_t nof_link); + void ReadLinkList(std::streambuf& buffer, size_t data_index, uint32_t nof_link); virtual void ClearData(); - void CopyDataToBuffer(FILE *from_file, std::vector &buffer, - size_t &buffer_index) const; + void CopyDataToBuffer(std::streambuf& buffer, std::vector &dest, + uint64_t &buffer_index) const; [[nodiscard]] bool IsRdBlock() const; void GetDataBlockList(std::vector& block_list) const; protected: diff --git a/mdflib/src/dbchelper.cpp b/mdflib/src/dbchelper.cpp index 7c5b7f29..0cbd29a2 100644 --- a/mdflib/src/dbchelper.cpp +++ b/mdflib/src/dbchelper.cpp @@ -110,7 +110,7 @@ void DbcHelper::DoubleToRaw(bool little_endian, size_t start, size_t length, bit = 7; little_endian ? --byte : ++byte; } - if (byte >= (start + length) /8) { + if (byte >= static_cast( (start + length) /8 ) ) { // Buffer overrun. Most likely invalid start bit break; } @@ -144,7 +144,7 @@ void DbcHelper::FloatToRaw(bool little_endian, size_t start, size_t length, bit = 7; little_endian ? --byte : ++byte; } - if (byte >= (start + length) / 8) { + if (byte >= static_cast((start + length) / 8)) { // Buffer overrun. Most likely invalid start bit break; } diff --git a/mdflib/src/dg3block.cpp b/mdflib/src/dg3block.cpp index d54ba1f7..24f0b2d3 100644 --- a/mdflib/src/dg3block.cpp +++ b/mdflib/src/dg3block.cpp @@ -53,24 +53,24 @@ void Dg3Block::GetBlockProperty(BlockPropertyList &dest) const { dest.emplace_back("Record ID size [bytes]", std::to_string(nof_record_id_)); } -size_t Dg3Block::Read(std::FILE *file) { - size_t bytes = ReadHeader3(file); - bytes += ReadLinks3(file, 4); - bytes += ReadNumber(file, nof_cg_blocks_); - bytes += ReadNumber(file, nof_record_id_); +uint64_t Dg3Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader3(buffer); + bytes += ReadLinks3(buffer, 4); + bytes += ReadNumber(buffer, nof_cg_blocks_); + bytes += ReadNumber(buffer, nof_record_id_); if (Link(kIndexTr) > 0) { tr_block_ = std::make_unique(); tr_block_->Init(*this); - SetFilePosition(file, Link(kIndexTr)); - tr_block_->Read(file); + SetFilePosition(buffer, Link(kIndexTr)); + tr_block_->Read(buffer); } if (Link(kIndexData) > 0) { auto dt3 = std::make_unique(); dt3->Init(*this); - SetFilePosition(file, Link(kIndexData)); - dt3->Read(file); + SetFilePosition(buffer, Link(kIndexData)); + dt3->Read(buffer); block_list_.push_back(std::move(dt3)); } @@ -78,8 +78,8 @@ size_t Dg3Block::Read(std::FILE *file) { for (auto link = Link(kIndexCg); link > 0; /* No ++ here*/) { auto cg3 = std::make_unique(); cg3->Init(*this); - SetFilePosition(file, link); - cg3->Read(file); + SetFilePosition(buffer, link); + cg3->Read(buffer); link = cg3->Link(kIndexNext); cg_list_.push_back(std::move(cg3)); } @@ -87,7 +87,7 @@ size_t Dg3Block::Read(std::FILE *file) { return bytes; } -size_t Dg3Block::Write(std::FILE *file) { +uint64_t Dg3Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // Write or update the values inside the block nof_cg_blocks_ = static_cast(cg_list_.size()); @@ -98,15 +98,15 @@ size_t Dg3Block::Write(std::FILE *file) { link_list_.resize(4, 0); } - size_t bytes = update ? MdfBlock::Update(file) : MdfBlock::Write(file); - bytes += WriteNumber(file, nof_cg_blocks_); - bytes += WriteNumber(file, nof_record_id_); + uint64_t bytes = update ? MdfBlock::Update(buffer) : MdfBlock::Write(buffer); + bytes += WriteNumber(buffer, nof_cg_blocks_); + bytes += WriteNumber(buffer, nof_record_id_); const std::vector reserved(4, 0); - bytes += WriteByte(file, reserved); + bytes += WriteByte(buffer, reserved); if (tr_block_ && Link(kIndexTr) <= 0) { - tr_block_->Write(file); - UpdateLink(file, kIndexTr, tr_block_->FilePosition()); + tr_block_->Write(buffer); + UpdateLink(buffer, kIndexTr, tr_block_->FilePosition()); } for (size_t cg_index = 0; cg_index < cg_list_.size(); ++cg_index) { @@ -114,13 +114,13 @@ size_t Dg3Block::Write(std::FILE *file) { if (!cg3) { continue; } - cg3->Write(file); + cg3->Write(buffer); if (cg_index == 0) { - UpdateLink(file, kIndexCg, cg3->FilePosition()); + UpdateLink(buffer, kIndexCg, cg3->FilePosition()); } else { auto &prev = cg_list_[cg_index - 1]; if (prev) { - prev->UpdateLink(file, kIndexNext, cg3->FilePosition()); + prev->UpdateLink(buffer, kIndexNext, cg3->FilePosition()); } } } @@ -133,9 +133,9 @@ size_t Dg3Block::Write(std::FILE *file) { if (data->FilePosition() > 0) { continue; } - data->Write(file); + data->Write(buffer); if (ii == 0) { - UpdateLink(file, kIndexData, data->FilePosition()); + UpdateLink(buffer, kIndexData, data->FilePosition()); } } @@ -174,36 +174,28 @@ IChannelGroup *Dg3Block::CreateChannelGroup() { return cg_list_.empty() ? nullptr : cg_list_.back().get(); } -void Dg3Block::ReadData(std::FILE *file) { - if (file == nullptr) { - throw std::invalid_argument("File pointer is null"); - } +void Dg3Block::ReadData(std::streambuf& buffer) { InitFastObserverList(); - std::FILE *data_file = nullptr; - size_t data_size = DataSize(); - SetFilePosition(file, Link(kIndexData)); - data_file = file; - auto pos = GetFilePosition(data_file); + uint64_t data_size = DataSize(); + SetFilePosition(buffer, Link(kIndexData)); + // Read through all record - ParseDataRecords(data_file, data_size); + ParseDataRecords(buffer, data_size); // Read in all SR block data for (const auto& cg3 :Cg3()) { if (!cg3) { continue;} - cg3->ReadData(file); + cg3->ReadData(buffer); } } -void Dg3Block::ReadRangeData(std::FILE *file, DgRange& range) { - if (file == nullptr) { - throw std::invalid_argument("File pointer is null"); - } +void Dg3Block::ReadRangeData(std::streambuf& buffer, DgRange& range) { + InitFastObserverList(); - std::FILE *data_file = nullptr; - size_t data_size = DataSize(); - SetFilePosition(file, Link(kIndexData)); - data_file = file; + + uint64_t data_size = DataSize(); + SetFilePosition(buffer, Link(kIndexData)); // Read in all SR block data for (const auto& cg3 :Cg3()) { @@ -212,13 +204,13 @@ void Dg3Block::ReadRangeData(std::FILE *file, DgRange& range) { } const auto record_id = cg3->RecordId(); if (range.IsUsed(record_id)) { - cg3->ReadData(file); + cg3->ReadData(buffer); } } // auto pos = GetFilePosition(data_file); // Read through all record - ParseRangeDataRecords(data_file, data_size, range); + ParseRangeDataRecords(buffer, data_size, range); } @@ -227,8 +219,8 @@ void Dg3Block::ClearData() { IDataGroup::ClearData(); } -void Dg3Block::ParseDataRecords(std::FILE *file, size_t nof_data_bytes) { - if (file == nullptr || nof_data_bytes == 0) { +void Dg3Block::ParseDataRecords(std::streambuf& buffer, uint64_t nof_data_bytes) { + if (nof_data_bytes == 0) { return; } for (const auto& channel_group : Cg3() ) { @@ -237,31 +229,31 @@ void Dg3Block::ParseDataRecords(std::FILE *file, size_t nof_data_bytes) { } } - for (size_t count = 0; count < nof_data_bytes; /* No ++count here*/) { + for (uint64_t count = 0; count < nof_data_bytes; /* No ++count here*/) { // 1. Read Record ID uint8_t record_id = 0; if (nof_record_id_ == 1 || nof_record_id_ == 2) { - count += ReadNumber(file, record_id); + count += ReadNumber(buffer, record_id); } const auto *cg3 = FindCgRecordId(record_id); if (cg3 == nullptr) { break; } - const auto read = cg3->ReadDataRecord(file, *this); + const auto read = cg3->ReadDataRecord(buffer, *this); if (read == 0) { break; } count += read; if (nof_record_id_ == 2) { - count += ReadNumber(file, record_id); + count += ReadNumber(buffer, record_id); } } } -void Dg3Block::ParseRangeDataRecords(std::FILE *file, size_t nof_data_bytes, +void Dg3Block::ParseRangeDataRecords(std::streambuf& buffer, uint64_t nof_data_bytes, DgRange& range) { - if (file == nullptr || nof_data_bytes == 0) { + if (nof_data_bytes == 0) { return; } for (const auto& channel_group : Cg3() ) { @@ -270,11 +262,11 @@ void Dg3Block::ParseRangeDataRecords(std::FILE *file, size_t nof_data_bytes, } } - for (size_t count = 0; count < nof_data_bytes; /* No ++count here*/) { + for (uint64_t count = 0; count < nof_data_bytes; /* No ++count here*/) { // 1. Read Record ID uint8_t record_id = 0; if (nof_record_id_ == 1 || nof_record_id_ == 2) { - count += ReadNumber(file, record_id); + count += ReadNumber(buffer, record_id); } const auto *cg3 = FindCgRecordId(record_id); const auto* cg_range = range.GetCgRange(record_id); @@ -282,7 +274,7 @@ void Dg3Block::ParseRangeDataRecords(std::FILE *file, size_t nof_data_bytes, break; } - const auto read = cg3->ReadRangeDataRecord(file, + const auto read = cg3->ReadRangeDataRecord(buffer, *this, range); if (read == 0) { @@ -290,7 +282,7 @@ void Dg3Block::ParseRangeDataRecords(std::FILE *file, size_t nof_data_bytes, } count += read; if (nof_record_id_ == 2) { - count += ReadNumber(file, record_id); + count += ReadNumber(buffer, record_id); } if (range.IsReady()) { break; diff --git a/mdflib/src/dg3block.h b/mdflib/src/dg3block.h index a5f3220d..1c3628a8 100644 --- a/mdflib/src/dg3block.h +++ b/mdflib/src/dg3block.h @@ -33,11 +33,11 @@ class Dg3Block : public DataListBlock, public IDataGroup { uint16_t NofRecordId() const { return nof_record_id_; } void GetBlockProperty(BlockPropertyList& dest) const override; [[nodiscard]] MdfBlock* Find(int64_t index) const override; - size_t Read(std::FILE* file) override; - size_t Write(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; - void ReadData(std::FILE* file); - void ReadRangeData(std::FILE* file, DgRange& range); + void ReadData(std::streambuf& buffer); + void ReadRangeData(std::streambuf& buffer, DgRange& range); void ClearData() override; @@ -49,8 +49,8 @@ class Dg3Block : public DataListBlock, public IDataGroup { std::unique_ptr tr_block_; Cg3List cg_list_; - void ParseDataRecords(std::FILE* file, size_t nof_data_bytes); - void ParseRangeDataRecords(std::FILE* file, size_t nof_data_bytes, + void ParseDataRecords(std::streambuf& buffer, uint64_t nof_data_bytes); + void ParseRangeDataRecords(std::streambuf& buffer, uint64_t nof_data_bytes, DgRange& range); const Cg3Block* FindCgRecordId(const uint64_t record_id) const; }; diff --git a/mdflib/src/dg4block.cpp b/mdflib/src/dg4block.cpp index b8d19c64..f1c7eea5 100644 --- a/mdflib/src/dg4block.cpp +++ b/mdflib/src/dg4block.cpp @@ -31,10 +31,10 @@ struct CgCounter { ///< Helper function that recursively copies all data bytes to a /// destination file. -size_t CopyDataToFile( +uint64_t CopyDataToFile( const mdf::detail::DataListBlock::BlockList& block_list, // NOLINT - std::FILE* from_file, std::FILE* to_file) { - size_t count = 0; + std::streambuf& from_file, std::streambuf& to_file) { + uint64_t count = 0; for (const auto& block : block_list) { if (!block) { continue; @@ -97,19 +97,19 @@ void Dg4Block::GetBlockProperty(BlockPropertyList& dest) const { } } -size_t Dg4Block::Read(std::FILE* file) { - size_t bytes = ReadHeader4(file); - bytes += ReadNumber(file, rec_id_size_); +uint64_t Dg4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadNumber(buffer, rec_id_size_); std::vector reserved; - bytes += ReadByte(file, reserved, 7); + bytes += ReadByte(buffer, reserved, 7); - ReadMdComment(file, kIndexMd); - ReadBlockList(file, kIndexData); + ReadMdComment(buffer, kIndexMd); + ReadBlockList(buffer, kIndexData); return bytes; } -size_t Dg4Block::Write(std::FILE* file) { +uint64_t Dg4Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // True if already written to file if (!update) { block_type_ = "##DG"; @@ -117,18 +117,18 @@ size_t Dg4Block::Write(std::FILE* file) { link_list_.resize(4, 0); } - WriteLink4List(file, cg_list_, kIndexCg, + WriteLink4List(buffer, cg_list_, kIndexCg, UpdateOption::DoUpdateAllBlocks); // Save nof samples in CG block - WriteMdComment(file, kIndexMd); + WriteMdComment(buffer, kIndexMd); - auto bytes = update ? MdfBlock::Update(file) : MdfBlock::Write(file); + uint64_t bytes = update ? MdfBlock::Update(buffer) : MdfBlock::Write(buffer); if (update) { bytes = block_length_; } else { - bytes += WriteNumber(file, rec_id_size_); - bytes += WriteBytes(file, 7); - UpdateBlockSize(file, bytes); + bytes += WriteNumber(buffer, rec_id_size_); + bytes += WriteBytes(buffer, 7); + UpdateBlockSize(buffer, bytes); // Need to update the signal data link for any channels referencing // VLSD CG blocks. for (auto& cg4 : cg_list_) { @@ -139,7 +139,7 @@ size_t Dg4Block::Write(std::FILE* file) { auto* cn4 = other_cg4 != nullptr ? other_cg4->FindVlsdChannel(cg4->RecordId()) : nullptr; if (cn4 != nullptr) { - cn4->UpdateDataLink(file, cg4->FilePosition()); + cn4->UpdateDataLink(buffer, cg4->FilePosition()); } } } @@ -147,20 +147,19 @@ size_t Dg4Block::Write(std::FILE* file) { // Need to write any data block, so it is positioned last in the file // as any DT block should be appended with data bytes. The DT block must be // last in the file - WriteLink4List(file, block_list_, kIndexData, + WriteLink4List(buffer, block_list_, kIndexData, UpdateOption::DoUpdateAllBlocks); // Update last HL or DT return bytes; } -size_t Dg4Block::DataSize() const { return DataListBlock::DataSize(); } -void Dg4Block::ReadCgList(std::FILE* file) { - ReadLink4List(file, cg_list_, kIndexCg); +uint64_t Dg4Block::DataSize() const { return DataListBlock::DataSize(); } + +void Dg4Block::ReadCgList(std::streambuf& buffer) { + ReadLink4List(buffer, cg_list_, kIndexCg); } -void Dg4Block::ReadData(std::FILE* file) { - if (file == nullptr) { - throw std::invalid_argument("File pointer is null"); - } +void Dg4Block::ReadData(std::streambuf& buffer) { + const auto& block_list = DataBlockList(); if (block_list.empty()) { return; @@ -179,7 +178,7 @@ void Dg4Block::ReadData(std::FILE* file) { if (!sr4) { continue; } - sr4->ReadData(file); + sr4->ReadData(buffer); } // Fetch all signal data (SD) @@ -218,13 +217,13 @@ void Dg4Block::ReadData(std::FILE* file) { case ChannelType::VariableLength: if (IsSubscribingOnChannelVlsd(*channel)) { if (block->BlockType() == "SD") { - cn_block->ReadSignalData(file); + cn_block->ReadSignalData(buffer); } else if (block->BlockType() == "DZ") { - cn_block->ReadSignalData(file); + cn_block->ReadSignalData(buffer); } else if (block->BlockType() == "DL") { - cn_block->ReadSignalData(file); + cn_block->ReadSignalData(buffer); } else if (block->BlockType() == "HL") { - cn_block->ReadSignalData(file); + cn_block->ReadSignalData(buffer); } } break; @@ -277,7 +276,7 @@ void Dg4Block::ReadData(std::FILE* file) { channel_group->ResetSampleCounter(); } } - ReadCache read_cache(this, file); + ReadCache read_cache(this, buffer); while (read_cache.ParseRecord()) { } @@ -294,10 +293,7 @@ void Dg4Block::ReadData(std::FILE* file) { } } -void Dg4Block::ReadRangeData(std::FILE* file, DgRange& range) { - if (file == nullptr) { - throw std::invalid_argument("File pointer is null"); - } +void Dg4Block::ReadRangeData(std::streambuf& buffer, DgRange& range) { const auto& block_list = DataBlockList(); if (block_list.empty()) { return; @@ -323,7 +319,7 @@ void Dg4Block::ReadRangeData(std::FILE* file, DgRange& range) { if (!sr4) { continue; } - sr4->ReadData(file); + sr4->ReadData(buffer); } // Fetch all signal data (SD) @@ -361,13 +357,13 @@ void Dg4Block::ReadRangeData(std::FILE* file, DgRange& range) { case ChannelType::VariableLength: if (IsSubscribingOnChannelVlsd(*channel)) { if (block->BlockType() == "SD") { - cn_block->ReadSignalData(file); + cn_block->ReadSignalData(buffer); } else if (block->BlockType() == "DZ") { - cn_block->ReadSignalData(file); + cn_block->ReadSignalData(buffer); } else if (block->BlockType() == "DL") { - cn_block->ReadSignalData(file); + cn_block->ReadSignalData(buffer); } else if (block->BlockType() == "HL") { - cn_block->ReadSignalData(file); + cn_block->ReadSignalData(buffer); } } break; @@ -384,7 +380,7 @@ void Dg4Block::ReadRangeData(std::FILE* file, DgRange& range) { channel_group->ResetSampleCounter(); } } - ReadCache read_cache(this, file); + ReadCache read_cache(this, buffer); while (read_cache.ParseRangeRecord(range)) { } @@ -401,13 +397,10 @@ void Dg4Block::ReadRangeData(std::FILE* file, DgRange& range) { } } -void Dg4Block::ReadVlsdData(std::FILE* file,Cn4Block& channel, +void Dg4Block::ReadVlsdData(std::streambuf& buffer,Cn4Block& channel, const std::vector& offset_list, std::function&)>& callback) { - if (file == nullptr) { - throw std::invalid_argument("File pointer is null"); - } // Fetch the channels referenced data block. Note that some types of // data blocks are owned by this channel as an SD block, but some are only @@ -449,14 +442,14 @@ void Dg4Block::ReadVlsdData(std::FILE* file,Cn4Block& channel, } if (read_signal_data) { - ReadCache read_cache(block, file); + ReadCache read_cache(block, buffer); read_cache.SetOffsetFilter(offset_list); read_cache.SetCallback(callback); while (read_cache.ParseSignalData()) { } } else if (read_vlsd_cg_data) { - ReadCache read_cache(this, file); + ReadCache read_cache(this, buffer); read_cache.SetRecordId(channel.VlsdRecordId()); read_cache.SetOffsetFilter(offset_list); read_cache.SetCallback(callback); @@ -467,8 +460,8 @@ void Dg4Block::ReadVlsdData(std::FILE* file,Cn4Block& channel, } -void Dg4Block::ParseDataRecords(std::FILE* file, size_t nof_data_bytes) { - if (file == nullptr || nof_data_bytes == 0) { +void Dg4Block::ParseDataRecords(std::streambuf& buffer, uint64_t nof_data_bytes) { + if (nof_data_bytes == 0) { return; } for (const auto& channel_group : Cg4() ) { @@ -477,16 +470,16 @@ void Dg4Block::ParseDataRecords(std::FILE* file, size_t nof_data_bytes) { } } - for (size_t count = 0; count < nof_data_bytes; /* No ++count here*/) { + for (uint64_t count = 0; count < nof_data_bytes; /* No ++count here*/) { // 1. Read Record ID uint64_t record_id = 0; - count += ReadRecordId(file, record_id); + count += ReadRecordId(buffer, record_id); const auto* cg4 = FindCgRecordId(record_id); if (cg4 == nullptr) { break; } - const auto read = cg4->ReadDataRecord(file, *this); + const auto read = cg4->ReadDataRecord(buffer, *this); if (read == 0) { break; } @@ -495,37 +488,35 @@ void Dg4Block::ParseDataRecords(std::FILE* file, size_t nof_data_bytes) { } } -size_t Dg4Block::ReadRecordId(std::FILE* file, uint64_t& record_id) const { +uint64_t Dg4Block::ReadRecordId(std::streambuf& buffer, uint64_t& record_id) const { record_id = 0; - if (file == nullptr) { - return 0; - } - size_t count = 0; + + uint64_t count = 0; switch (rec_id_size_) { case 1: { uint8_t id = 0; - count += ReadNumber(file, id); + count += ReadNumber(buffer, id); record_id = id; break; } case 2: { uint16_t id = 0; - count += ReadNumber(file, id); + count += ReadNumber(buffer, id); record_id = id; break; } case 4: { uint32_t id = 0; - count += ReadNumber(file, id); + count += ReadNumber(buffer, id); record_id = id; break; } case 8: { uint64_t id = 0; - count += ReadNumber(file, id); + count += ReadNumber(buffer, id); record_id = id; break; } @@ -610,7 +601,7 @@ void Dg4Block::RecordIdSize(uint8_t id_size) { rec_id_size_ = id_size; } uint8_t Dg4Block::RecordIdSize() const { return rec_id_size_; } -bool Dg4Block::FinalizeDtBlocks(std::FILE *file) { +bool Dg4Block::FinalizeDtBlocks(std::streambuf& buffer) { auto& block_list = DataBlockList(); if (block_list.empty()) { // No data blocks to update @@ -627,7 +618,7 @@ bool Dg4Block::FinalizeDtBlocks(std::FILE *file) { MDF_ERROR() << "Invalid DT block type-cast."; return false; } - dt_block->UpdateDataSize(file); + dt_block->UpdateDataSize(buffer); return true; } @@ -635,7 +626,7 @@ bool Dg4Block::FinalizeDtBlocks(std::FILE *file) { // Update the unfinished payload data (DT) block. This function updates the // channel group (CG) and a CG-VLSD channel group regarding cycle count // and offsets (VLSD) -bool Dg4Block::FinalizeCgAndVlsdBlocks(std::FILE* file, bool update_cg, +bool Dg4Block::FinalizeCgAndVlsdBlocks(std::streambuf& buffer, bool update_cg, bool update_vlsd) { auto& block_list = DataBlockList(); if (block_list.empty()) { @@ -670,11 +661,11 @@ bool Dg4Block::FinalizeCgAndVlsdBlocks(std::FILE* file, bool update_cg, } - SetFilePosition(file, dt_block->DataPosition()); - size_t count = 0; + SetFilePosition(buffer, dt_block->DataPosition()); + uint64_t count = 0; while (count < dt_block->DataSize()) { uint64_t record_id = 0; - count += ReadRecordId(file,record_id); + count += ReadRecordId(buffer,record_id); auto cg_find = counter_list.size() == 1 ? counter_list.begin() : counter_list.find(record_id); if (cg_find == counter_list.end()) { @@ -683,7 +674,7 @@ bool Dg4Block::FinalizeCgAndVlsdBlocks(std::FILE* file, bool update_cg, } auto& counter = cg_find->second; auto* cg_block = counter.CgBlock; - size_t count_bytes = 0; + uint64_t count_bytes = 0; if (cg_block == nullptr) { MDF_ERROR() << "CG block pointer is null. Internal error."; return false; @@ -692,15 +683,15 @@ bool Dg4Block::FinalizeCgAndVlsdBlocks(std::FILE* file, bool update_cg, // This is normally used for string, // and the CG block only includes one signal uint32_t length = 0; - count_bytes += ReadNumber(file, length); + count_bytes += ReadNumber(buffer, length); //std::vector record(length, 0); if (length > 0) { - count_bytes += StepFilePosition(file, length); + count_bytes += StepFilePosition(buffer, length); } } else { // Normal fixed length records const size_t record_size = cg_block->NofDataBytes() + cg_block->NofInvalidBytes(); - count_bytes += StepFilePosition(file, record_size); + count_bytes += StepFilePosition(buffer, record_size); } ++counter.NofSamples; counter.NofBytes += count_bytes; diff --git a/mdflib/src/dg4block.h b/mdflib/src/dg4block.h index c3dd7e7e..cf8717e7 100644 --- a/mdflib/src/dg4block.h +++ b/mdflib/src/dg4block.h @@ -35,12 +35,12 @@ class Dg4Block : public DataListBlock, public IDataGroup { void GetBlockProperty(BlockPropertyList& dest) const override; MdfBlock* Find(int64_t index) const override; - size_t Read(std::FILE* file) override; - void ReadCgList(std::FILE* file); + uint64_t Read(std::streambuf& buffer) override; + void ReadCgList(std::streambuf& buffer); - void ReadData(std::FILE* file); - void ReadRangeData(std::FILE* file, DgRange& range); - void ReadVlsdData(std::FILE* file,Cn4Block& channel, + void ReadData(std::streambuf& buffer); + void ReadRangeData(std::streambuf& buffer, DgRange& range); + void ReadVlsdData(std::streambuf& buffer,Cn4Block& channel, const std::vector& offset_list, std::function&)>& callback); @@ -50,11 +50,11 @@ class Dg4Block : public DataListBlock, public IDataGroup { IMetaData* MetaData() const override; void RecordIdSize(uint8_t id_size) override; uint8_t RecordIdSize() const override; - size_t Write(std::FILE* file) override; - size_t DataSize() const override; + uint64_t Write(std::streambuf& buffer) override; + uint64_t DataSize() const override; - bool FinalizeDtBlocks(std::FILE *file); - bool FinalizeCgAndVlsdBlocks(std::FILE *file, bool update_cg, bool update_vlsd); + bool FinalizeDtBlocks(std::streambuf& buffer); + bool FinalizeCgAndVlsdBlocks(std::streambuf& buffer, bool update_cg, bool update_vlsd); [[nodiscard]] IChannelGroup *FindParentChannelGroup( const IChannel &channel) const override; @@ -64,8 +64,8 @@ class Dg4Block : public DataListBlock, public IDataGroup { /* 7 byte reserved */ Cg4List cg_list_; - void ParseDataRecords(std::FILE* file, size_t nof_data_bytes); - size_t ReadRecordId(std::FILE* file, uint64_t& record_id) const; + void ParseDataRecords(std::streambuf& buffer, uint64_t nof_data_bytes); + uint64_t ReadRecordId(std::streambuf& buffer, uint64_t& record_id) const; }; diff --git a/mdflib/src/di4block.cpp b/mdflib/src/di4block.cpp index 46b42983..6d79a82c 100644 --- a/mdflib/src/di4block.cpp +++ b/mdflib/src/di4block.cpp @@ -13,13 +13,13 @@ void Di4Block::GetBlockProperty(BlockPropertyList &dest) const { dest.emplace_back("Data Size [byte]", std::to_string(DataSize())); } -size_t Di4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - data_position_ = GetFilePosition(file); +uint64_t Di4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + data_position_ = GetFilePosition(buffer); return bytes; } -size_t Di4Block::DataSize() const { +uint64_t Di4Block::DataSize() const { return block_length_ > 24 ? block_length_ - 24 : 0; } diff --git a/mdflib/src/di4block.h b/mdflib/src/di4block.h index 3ba83898..5a8a3962 100644 --- a/mdflib/src/di4block.h +++ b/mdflib/src/di4block.h @@ -12,8 +12,8 @@ namespace mdf::detail { class Di4Block : public DataBlock { public: void GetBlockProperty(BlockPropertyList& dest) const override; - size_t Read(std::FILE* file) override; - [[nodiscard]] size_t DataSize() const override; + uint64_t Read(std::streambuf& buffer) override; + [[nodiscard]] uint64_t DataSize() const override; }; } // namespace mdf::detail diff --git a/mdflib/src/dl4block.cpp b/mdflib/src/dl4block.cpp index 66606103..0b52fd94 100644 --- a/mdflib/src/dl4block.cpp +++ b/mdflib/src/dl4block.cpp @@ -41,31 +41,31 @@ void Dl4Block::GetBlockProperty(BlockPropertyList &dest) const { } } -size_t Dl4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - bytes += ReadNumber(file, flags_); +uint64_t Dl4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadNumber(buffer, flags_); std::vector reserved; - bytes += ReadByte(file, reserved, 3); - bytes += ReadNumber(file, nof_blocks_); + bytes += ReadByte(buffer, reserved, 3); + bytes += ReadNumber(buffer, nof_blocks_); if (flags_ & Dl4Flags::EqualLength) { - bytes += ReadNumber(file, equal_length_); + bytes += ReadNumber(buffer, equal_length_); } else { for (uint32_t ii = 0; ii < nof_blocks_; ++ii) { uint64_t offset = 0; - bytes += ReadNumber(file, offset); + bytes += ReadNumber(buffer, offset); offset_list_.push_back(offset); } } - ReadLinkList(file, kIndexData, nof_blocks_); + ReadLinkList(buffer, kIndexData, nof_blocks_); return bytes; } -size_t Dl4Block::Write(std::FILE *file) { +uint64_t Dl4Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; if (update) { // The DL block properties cannot be changed, but it // is possible to append DL blocks - WriteBlockList(file, kIndexData); + WriteBlockList(buffer, kIndexData); return block_length_; } const size_t nof = block_list_.size(); // Number of DZ/DT blocks @@ -93,39 +93,39 @@ size_t Dl4Block::Write(std::FILE *file) { block_length_ += 8 * nof; } - auto bytes = MdfBlock::Write(file); - bytes += WriteNumber(file,flags_); - bytes += WriteBytes(file, 3); - bytes += WriteNumber(file, static_cast(nof)); + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteNumber(buffer,flags_); + bytes += WriteBytes(buffer, 3); + bytes += WriteNumber(buffer, static_cast(nof)); if (equal) { - bytes += WriteNumber(file, equal_length_); + bytes += WriteNumber(buffer, equal_length_); } else { for (size_t index = 0; index < nof; ++index) { - bytes += WriteNumber(file, Offset(index)); + bytes += WriteNumber(buffer, Offset(index)); } } if (time) { for (size_t index = 0; index < nof; ++index) { - bytes += WriteNumber(file, TimeValue(index)); + bytes += WriteNumber(buffer, TimeValue(index)); } } if (angle) { for (size_t index = 0; index < nof; ++index) { - bytes += WriteNumber(file, AngleValue(index)); + bytes += WriteNumber(buffer, AngleValue(index)); } } if (distance) { for (size_t index = 0; index < nof; ++index) { - bytes += WriteNumber(file, DistanceValue(index)); + bytes += WriteNumber(buffer, DistanceValue(index)); } } - UpdateBlockSize(file, bytes); + UpdateBlockSize(buffer, bytes); - WriteBlockList(file, kIndexData); + WriteBlockList(buffer, kIndexData); return bytes; } diff --git a/mdflib/src/dl4block.h b/mdflib/src/dl4block.h index a573f85a..12a67a59 100644 --- a/mdflib/src/dl4block.h +++ b/mdflib/src/dl4block.h @@ -16,8 +16,8 @@ constexpr uint8_t DistanceValues = 0x08; class Dl4Block : public DataListBlock { public: void GetBlockProperty(BlockPropertyList& dest) const override; - size_t Read(std::FILE* file) override; - size_t Write(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; void Flags(uint8_t flags) {flags_ = flags;} [[nodiscard]] uint8_t Flags() const {return flags_;} diff --git a/mdflib/src/dt3block.cpp b/mdflib/src/dt3block.cpp index 3fc77db1..8dc4c07d 100644 --- a/mdflib/src/dt3block.cpp +++ b/mdflib/src/dt3block.cpp @@ -16,28 +16,28 @@ void Dt3Block::GetBlockProperty(BlockPropertyList &dest) const { dest.emplace_back("Data Size [byte]", std::to_string(DataSize())); } -size_t Dt3Block::Read(std::FILE *file) { +uint64_t Dt3Block::Read(std::streambuf& buffer) { block_type_ = "DT"; - file_position_ = GetFilePosition(file); + file_position_ = GetFilePosition(buffer); data_position_ = file_position_; return 0; } -size_t Dt3Block::Write(std::FILE *file) { +uint64_t Dt3Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; if (update) { return block_size_; } - SetLastFilePosition(file); + SetLastFilePosition(buffer); block_type_ = "DT"; - file_position_ = GetFilePosition(file); + file_position_ = GetFilePosition(buffer); data_position_ = file_position_; // ToDo: Fix write of data return 0; } -size_t Dt3Block::DataSize() const { - size_t bytes = 0; +uint64_t Dt3Block::DataSize() const { + uint64_t bytes = 0; if (dg_block_ == nullptr) { return 0; } diff --git a/mdflib/src/dt3block.h b/mdflib/src/dt3block.h index 76dcb097..5c4c17c9 100644 --- a/mdflib/src/dt3block.h +++ b/mdflib/src/dt3block.h @@ -14,9 +14,9 @@ class Dt3Block : public DataBlock { public: void Init(const MdfBlock &id_block) override; void GetBlockProperty(BlockPropertyList &dest) const override; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; - [[nodiscard]] size_t DataSize() const override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; + [[nodiscard]] uint64_t DataSize() const override; }; diff --git a/mdflib/src/dt4block.cpp b/mdflib/src/dt4block.cpp index c5c6842c..4775ad3e 100644 --- a/mdflib/src/dt4block.cpp +++ b/mdflib/src/dt4block.cpp @@ -24,18 +24,18 @@ void Dt4Block::GetBlockProperty(BlockPropertyList &dest) const { dest.emplace_back("Data Size [byte]", std::to_string(DataSize())); } -size_t Dt4Block::Read(std::FILE *file) { - const size_t bytes = ReadHeader4(file); - data_position_ = GetFilePosition(file); +uint64_t Dt4Block::Read(std::streambuf& buffer) { + const uint64_t bytes = ReadHeader4(buffer); + data_position_ = GetFilePosition(buffer); return bytes; } -size_t Dt4Block::DataSize() const { +uint64_t Dt4Block::DataSize() const { return block_length_ > 24 ? block_length_ - 24 : 0; } -void Dt4Block::UpdateDataSize(std::FILE *file) { - int64_t last_file_position = GetLastFilePosition(file); +void Dt4Block::UpdateDataSize(std::streambuf& buffer) { + int64_t last_file_position = GetLastFilePosition(buffer); const auto data_size = last_file_position - data_position_; if (data_size > 0) { block_length_ = 24 + static_cast(data_size); @@ -43,7 +43,7 @@ void Dt4Block::UpdateDataSize(std::FILE *file) { MDF_TRACE() << "Updated the last DT block data size. Size: " << data_size; } -size_t Dt4Block::Write(std::FILE *file) { +uint64_t Dt4Block::Write(std::streambuf& buffer) { const auto update = FilePosition() > 0; if (!update) { block_type_ = "##DT"; @@ -53,11 +53,11 @@ size_t Dt4Block::Write(std::FILE *file) { } - size_t bytes = update ? MdfBlock::Update(file) : MdfBlock::Write(file); + uint64_t bytes = update ? MdfBlock::Update(buffer) : MdfBlock::Write(buffer); if (!update) { - data_position_ = GetLastFilePosition(file); - bytes += WriteByte(file, data_); + data_position_ = GetLastFilePosition(buffer); + bytes += WriteByte(buffer, data_); } else { bytes = block_length_; } diff --git a/mdflib/src/dt4block.h b/mdflib/src/dt4block.h index c2aab6f5..a3aec1e0 100644 --- a/mdflib/src/dt4block.h +++ b/mdflib/src/dt4block.h @@ -14,10 +14,10 @@ class Dt4Block : public DataBlock { Dt4Block(); void Init(const MdfBlock &id_block) override; void GetBlockProperty(BlockPropertyList& dest) const override; - size_t Read(std::FILE* file) override; - size_t Write(std::FILE *file) override; - [[nodiscard]] size_t DataSize() const override; - void UpdateDataSize(std::FILE* file); + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; + [[nodiscard]] uint64_t DataSize() const override; + void UpdateDataSize(std::streambuf& buffer); }; diff --git a/mdflib/src/dv4block.cpp b/mdflib/src/dv4block.cpp index cb0b1cc0..fb5fece8 100644 --- a/mdflib/src/dv4block.cpp +++ b/mdflib/src/dv4block.cpp @@ -13,13 +13,13 @@ void Dv4Block::GetBlockProperty(BlockPropertyList &dest) const { dest.emplace_back("Data Size [byte]", std::to_string(DataSize())); } -size_t Dv4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - data_position_ = GetFilePosition(file); +uint64_t Dv4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + data_position_ = GetFilePosition(buffer); return bytes; } -size_t Dv4Block::DataSize() const { +uint64_t Dv4Block::DataSize() const { return block_length_ > 24 ? block_length_ - 24 : 0; } } // namespace mdf::detail \ No newline at end of file diff --git a/mdflib/src/dv4block.h b/mdflib/src/dv4block.h index dc80981c..b866e373 100644 --- a/mdflib/src/dv4block.h +++ b/mdflib/src/dv4block.h @@ -12,8 +12,8 @@ namespace mdf::detail { class Dv4Block : public DataBlock { public: void GetBlockProperty(BlockPropertyList& dest) const override; - size_t Read(std::FILE* file) override; - [[nodiscard]] size_t DataSize() const override; + uint64_t Read(std::streambuf& buffer) override; + [[nodiscard]] uint64_t DataSize() const override; }; } // namespace mdf::detail diff --git a/mdflib/src/dz4block.cpp b/mdflib/src/dz4block.cpp index c32b3fc3..0b265719 100644 --- a/mdflib/src/dz4block.cpp +++ b/mdflib/src/dz4block.cpp @@ -36,20 +36,20 @@ void Dz4Block::GetBlockProperty(BlockPropertyList &dest) const { dest.emplace_back("Data Size [byte]", std::to_string(data_length_)); } -size_t Dz4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - bytes += ReadStr(file, orig_block_type_, 2); - bytes += ReadNumber(file, type_); +uint64_t Dz4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadStr(buffer, orig_block_type_, 2); + bytes += ReadNumber(buffer, type_); std::vector reserved; - bytes += ReadByte(file, reserved, 1); - bytes += ReadNumber(file, parameter_); - bytes += ReadNumber(file, orig_data_length_); - bytes += ReadNumber(file, data_length_); - data_position_ = GetFilePosition(file); + bytes += ReadByte(buffer, reserved, 1); + bytes += ReadNumber(buffer, parameter_); + bytes += ReadNumber(buffer, orig_data_length_); + bytes += ReadNumber(buffer, data_length_); + data_position_ = GetFilePosition(buffer); return bytes; } -size_t Dz4Block::Write(std::FILE *file) { +uint64_t Dz4Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; if (update) { // The DZ block properties cannot be changed after it has been written @@ -60,27 +60,27 @@ size_t Dz4Block::Write(std::FILE *file) { link_list_.clear(); block_length_ = 24 + 2 + 1 + 1 + 4 + 8 + 8 + data_length_; - auto bytes = MdfBlock::Write(file); - bytes += WriteStr(file, orig_block_type_, 2); - bytes += WriteNumber(file, type_); - bytes += WriteBytes(file, 1); - bytes += WriteNumber(file, parameter_); - bytes += WriteNumber(file, orig_data_length_); - bytes += WriteNumber(file, data_length_); - bytes += WriteByte(file,data_); - UpdateBlockSize(file, bytes); + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteStr(buffer, orig_block_type_, 2); + bytes += WriteNumber(buffer, type_); + bytes += WriteBytes(buffer, 1); + bytes += WriteNumber(buffer, parameter_); + bytes += WriteNumber(buffer, orig_data_length_); + bytes += WriteNumber(buffer, data_length_); + bytes += WriteByte(buffer,data_); + UpdateBlockSize(buffer, bytes); return bytes; } -size_t Dz4Block::CopyDataToFile(std::FILE *from_file, - std::FILE *to_file) const { +uint64_t Dz4Block::CopyDataToFile(std::streambuf& from_file, + std::streambuf& to_file) const { if (data_position_ == 0 || orig_data_length_ == 0 || data_length_ == 0) { return 0; } SetFilePosition(from_file, data_position_); - size_t count = 0; + uint64_t count = 0; switch (static_cast(type_)) { case Dz4ZipType::Deflate: { const bool inflate = Inflate(from_file, to_file, data_length_); @@ -89,16 +89,15 @@ size_t Dz4Block::CopyDataToFile(std::FILE *from_file, } case Dz4ZipType::TransposeAndDeflate: { - ByteArray temp(data_length_, 0); - { - auto dummy = fread(temp.data(), 1, temp.size(), from_file); - if (dummy == 0) { - } - } - ByteArray out(orig_data_length_, 0); + ByteArray temp(static_cast(data_length_), 0); + from_file.sgetn( + reinterpret_cast(temp.data()), + static_cast(temp.size()) ); + ByteArray out(static_cast(orig_data_length_), 0); const bool inflate = Inflate(temp, out); InvTranspose(out, parameter_); - fwrite(out.data(), 1, out.size(), to_file); + to_file.sputn(reinterpret_cast(out.data()), + static_cast(out.size()) ); count = inflate ? orig_data_length_ : 0; break; } @@ -109,45 +108,39 @@ size_t Dz4Block::CopyDataToFile(std::FILE *from_file, return count; } -size_t Dz4Block::CopyDataToBuffer(std::FILE *from_file, - std::vector &buffer, - size_t &buffer_index) const { +uint64_t Dz4Block::CopyDataToBuffer(std::streambuf& from_file, + std::vector &dest, + uint64_t &buffer_index) const { if (data_position_ == 0 || orig_data_length_ == 0 || data_length_ == 0) { return 0; } SetFilePosition(from_file, data_position_); - size_t count = 0; + uint64_t count = 0; switch (static_cast(type_)) { case Dz4ZipType::Deflate: { - ByteArray temp(data_length_, 0); - { - auto dummy = fread(temp.data(), 1, temp.size(), from_file); - if (dummy == 0) { - } - } - ByteArray out(orig_data_length_, 0); + ByteArray temp(static_cast(data_length_), 0); + from_file.sgetn( reinterpret_cast(temp.data()), + static_cast(temp.size()) ); + ByteArray out(static_cast(orig_data_length_), 0); Inflate(temp, out); count = orig_data_length_; - memcpy(buffer.data() + buffer_index, out.data(), count); + memcpy(dest.data() + buffer_index, out.data(), static_cast(count) ); buffer_index += count; break; } case Dz4ZipType::TransposeAndDeflate: { - ByteArray temp(data_length_, 0); - { - auto dummy = fread(temp.data(), 1, temp.size(), from_file); - if (dummy == 0) { - } - } - ByteArray out(orig_data_length_, 0); + ByteArray temp(static_cast(data_length_), 0); + from_file.sgetn(reinterpret_cast(temp.data()), + static_cast(temp.size()) ); + ByteArray out(static_cast( orig_data_length_ ), 0); Inflate(temp, out); InvTranspose(out, parameter_); count = orig_data_length_; - memcpy(buffer.data() + buffer_index, out.data(), count); + memcpy(dest.data() + buffer_index, out.data(), static_cast(count) ); buffer_index += count; break; } diff --git a/mdflib/src/dz4block.h b/mdflib/src/dz4block.h index fda02018..382eb38a 100644 --- a/mdflib/src/dz4block.h +++ b/mdflib/src/dz4block.h @@ -24,17 +24,17 @@ class Dz4Block : public DataBlock { [[nodiscard]] uint32_t Parameter() const { return parameter_; } - [[nodiscard]] size_t DataSize() const override { return orig_data_length_; } - [[nodiscard]] size_t CompressedDataSize() const { return data_length_; } + [[nodiscard]] uint64_t DataSize() const override { return orig_data_length_; } + [[nodiscard]] uint64_t CompressedDataSize() const { return data_length_; } void GetBlockProperty(BlockPropertyList& dest) const override; - size_t Read(std::FILE* file) override; - size_t Write(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; - size_t CopyDataToFile(std::FILE* from_file, - std::FILE* to_file) const override; - size_t CopyDataToBuffer(std::FILE* from_file, std::vector& buffer, - size_t& buffer_index) const override; + uint64_t CopyDataToFile(std::streambuf& from_file, + std::streambuf& to_file) const override; + uint64_t CopyDataToBuffer(std::streambuf& from_file, std::vector& buffer, + uint64_t& buffer_index) const override; bool Data(const std::vector& uncompressed_data) override; diff --git a/mdflib/src/ev4block.cpp b/mdflib/src/ev4block.cpp index a35c1f39..e8cd1a1b 100644 --- a/mdflib/src/ev4block.cpp +++ b/mdflib/src/ev4block.cpp @@ -142,31 +142,32 @@ void Ev4Block::GetBlockProperty(BlockPropertyList &dest) const { } } -size_t Ev4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - bytes += ReadNumber(file, type_); - bytes += ReadNumber(file, sync_type_); - bytes += ReadNumber(file, range_type_); - bytes += ReadNumber(file, cause_); - bytes += ReadNumber(file, flags_); +uint64_t Ev4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadNumber(buffer, type_); + bytes += ReadNumber(buffer, sync_type_); + bytes += ReadNumber(buffer, range_type_); + bytes += ReadNumber(buffer, cause_); + bytes += ReadNumber(buffer, flags_); std::vector reserved; - bytes += ReadByte(file, reserved, 3); - bytes += ReadNumber(file, length_m_); - bytes += ReadNumber(file, length_n_); - bytes += ReadNumber(file, creator_index_); - bytes += ReadNumber(file, sync_base_value_); - bytes += ReadNumber(file, sync_factor_); - - name_ = ReadTx4(file, kIndexName); + bytes += ReadByte(buffer, reserved, 3); + bytes += ReadNumber(buffer, length_m_); + bytes += ReadNumber(buffer, length_n_); + bytes += ReadNumber(buffer, creator_index_); + bytes += ReadNumber(buffer, sync_base_value_); + bytes += ReadNumber(buffer, sync_factor_); + + name_ = ReadTx4(buffer, kIndexName); const size_t group_index = 5 + length_m_ + length_n_; if (group_index < link_list_.size()) { - group_name_ = ReadTx4(file, group_index); + group_name_ = ReadTx4(buffer, group_index); } - ReadMdComment(file, kIndexMd); + ReadMdComment(buffer, kIndexMd); return bytes; } -size_t Ev4Block::Write(std::FILE *file) { + +uint64_t Ev4Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // Write or update the values inside the block if (update) { @@ -199,25 +200,25 @@ size_t Ev4Block::Write(std::FILE *file) { const auto *block = attachment_list_[index_n]; link_list_[index] = block != nullptr ? block->Index() : 0; } - WriteTx4(file, kIndexName, name_); + WriteTx4(buffer, kIndexName, name_); if (group) { - WriteTx4(file, link_list_.size() - 1, group_name_); + WriteTx4(buffer, link_list_.size() - 1, group_name_); } - WriteMdComment(file, kIndexMd); - - auto bytes = MdfBlock::Write(file); - bytes += WriteNumber(file, type_); - bytes += WriteNumber(file, sync_type_); - bytes += WriteNumber(file, range_type_); - bytes += WriteNumber(file, cause_); - bytes += WriteNumber(file, flags_); - bytes += WriteBytes(file, 3); - bytes += WriteNumber(file, length_m_); - bytes += WriteNumber(file, length_n_); - bytes += WriteNumber(file, creator_index_); - bytes += WriteNumber(file, sync_base_value_); - bytes += WriteNumber(file, sync_factor_); - UpdateBlockSize(file, bytes); + WriteMdComment(buffer, kIndexMd); + + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteNumber(buffer, type_); + bytes += WriteNumber(buffer, sync_type_); + bytes += WriteNumber(buffer, range_type_); + bytes += WriteNumber(buffer, cause_); + bytes += WriteNumber(buffer, flags_); + bytes += WriteBytes(buffer, 3); + bytes += WriteNumber(buffer, length_m_); + bytes += WriteNumber(buffer, length_n_); + bytes += WriteNumber(buffer, creator_index_); + bytes += WriteNumber(buffer, sync_base_value_); + bytes += WriteNumber(buffer, sync_factor_); + UpdateBlockSize(buffer, bytes); return bytes; } diff --git a/mdflib/src/ev4block.h b/mdflib/src/ev4block.h index 45b4c09c..6b5867bd 100644 --- a/mdflib/src/ev4block.h +++ b/mdflib/src/ev4block.h @@ -15,8 +15,8 @@ class Ev4Block : public MdfBlock, public IEvent { Ev4Block(); void GetBlockProperty(BlockPropertyList &dest) const override; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; void FindReferencedBlocks(const Hd4Block &hd4); [[nodiscard]] int64_t Index() const override; diff --git a/mdflib/src/fh4block.cpp b/mdflib/src/fh4block.cpp index 26633669..39f0aed5 100644 --- a/mdflib/src/fh4block.cpp +++ b/mdflib/src/fh4block.cpp @@ -8,7 +8,13 @@ constexpr size_t kIndexNext = 0; constexpr size_t kIndexMd = 1; } // namespace namespace mdf::detail { -Fh4Block::Fh4Block() { block_type_ = "##FH"; } + +Fh4Block::Fh4Block() { + block_type_ = "##FH"; + UtcTimestamp now(MdfHelper::NowNs()); + timestamp_.SetTime(now); +} + void Fh4Block::GetBlockProperty(BlockPropertyList &dest) const { MdfBlock::GetBlockProperty(dest); @@ -26,15 +32,15 @@ void Fh4Block::GetBlockProperty(BlockPropertyList &dest) const { } } -size_t Fh4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); +uint64_t Fh4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); timestamp_.Init(*this); - bytes += timestamp_.Read(file); - ReadMdComment(file, kIndexMd); + bytes += timestamp_.Read(buffer); + ReadMdComment(buffer, kIndexMd); return bytes; } -size_t Fh4Block::Write(std::FILE *file) { +uint64_t Fh4Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // Write or update the values inside the block if (update) { @@ -44,11 +50,11 @@ size_t Fh4Block::Write(std::FILE *file) { block_length_ = 24 + (2 * 8) + 8 + 2 + 2 + 1 + 3; link_list_.resize(2, 0); - auto bytes = MdfBlock::Write(file); - bytes += timestamp_.Write(file); - bytes += WriteBytes(file, 3); - UpdateBlockSize(file, bytes); - WriteMdComment(file, kIndexMd); + uint64_t bytes = MdfBlock::Write(buffer); + bytes += timestamp_.Write(buffer); + bytes += WriteBytes(buffer, 3); + UpdateBlockSize(buffer, bytes); + WriteMdComment(buffer, kIndexMd); return bytes; } diff --git a/mdflib/src/fh4block.h b/mdflib/src/fh4block.h index 049d2d60..00562845 100644 --- a/mdflib/src/fh4block.h +++ b/mdflib/src/fh4block.h @@ -24,8 +24,8 @@ class Fh4Block : public MdfBlock, public IFileHistory { void GetBlockProperty(BlockPropertyList& dest) const override; [[nodiscard]] IMetaData* CreateMetaData() override; [[nodiscard]] IMetaData* MetaData() const override; - size_t Read(std::FILE* file) override; - size_t Write(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; private: Mdf4Timestamp timestamp_; diff --git a/mdflib/src/hd3block.cpp b/mdflib/src/hd3block.cpp index bf728ed4..fee5c39d 100644 --- a/mdflib/src/hd3block.cpp +++ b/mdflib/src/hd3block.cpp @@ -20,7 +20,11 @@ constexpr size_t kIndexNext = 0; } // namespace namespace mdf::detail { - +Hd3Block::Hd3Block() { + block_type_ = "HD"; + UtcTimestamp now(MdfHelper::NowNs()); + timestamp_.SetTime(now); +} const Hd3Block::Dg3List &Hd3Block::Dg3() const { return dg_list_; } std::string Hd3Block::Comment() const { return comment_; } @@ -92,63 +96,63 @@ void Hd3Block::GetBlockProperty(BlockPropertyList &dest) const { dest.emplace_back("Comment", comment_); } -size_t Hd3Block::Read(std::FILE *file) { - size_t bytes = ReadHeader3(file); - bytes += ReadLinks3(file, 3); +uint64_t Hd3Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader3(buffer); + bytes += ReadLinks3(buffer, 3); // The for loop handles earlier versions of the MDF file for (int ii = 3; bytes < block_size_; ++ii) { switch (ii) { case 3: - bytes += ReadNumber(file, nof_dg_blocks_); + bytes += ReadNumber(buffer, nof_dg_blocks_); break; case 4: - bytes += ReadStr(file, timestamp_.date_, 10); + bytes += ReadStr(buffer, timestamp_.date_, 10); break; case 5: - bytes += ReadStr(file, timestamp_.time_, 8); + bytes += ReadStr(buffer, timestamp_.time_, 8); break; case 6: - bytes += ReadStr(file, author_, 32); + bytes += ReadStr(buffer, author_, 32); break; case 7: - bytes += ReadStr(file, organisation_, 32); + bytes += ReadStr(buffer, organisation_, 32); break; case 8: - bytes += ReadStr(file, project_, 32); + bytes += ReadStr(buffer, project_, 32); break; case 9: - bytes += ReadStr(file, subject_, 32); + bytes += ReadStr(buffer, subject_, 32); break; case 10: - bytes += ReadNumber(file, timestamp_.local_timestamp_); + bytes += ReadNumber(buffer, timestamp_.local_timestamp_); break; case 11: - bytes += ReadNumber(file, timestamp_.utc_offset_); + bytes += ReadNumber(buffer, timestamp_.utc_offset_); break; case 12: - bytes += ReadNumber(file, timestamp_.time_quality_); + bytes += ReadNumber(buffer, timestamp_.time_quality_); break; case 13: - bytes += ReadStr(file, timestamp_.timer_id_, 32); + bytes += ReadStr(buffer, timestamp_.timer_id_, 32); break; default: std::string temp; - bytes += ReadStr(file, temp, 1); + bytes += ReadStr(buffer, temp, 1); break; } } - comment_ = ReadTx3(file, kIndexTx); + comment_ = ReadTx3(buffer, kIndexTx); if (Link(kIndexPr) > 0) { pr_block_ = std::make_unique(); pr_block_->Init(*this); - SetFilePosition(file, Link(kIndexPr)); - pr_block_->Read(file); + SetFilePosition(buffer, Link(kIndexPr)); + pr_block_->Read(buffer); } return bytes; } -size_t Hd3Block::Write(std::FILE *file) { +uint64_t Hd3Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // Write or update the values inside the block if (!update) { @@ -157,36 +161,36 @@ size_t Hd3Block::Write(std::FILE *file) { link_list_.resize(3, 0); } - auto bytes = update ? MdfBlock::Update(file) : MdfBlock::Write(file); + uint64_t bytes = update ? MdfBlock::Update(buffer) : MdfBlock::Write(buffer); nof_dg_blocks_ = static_cast(dg_list_.size()); - bytes += WriteNumber(file, nof_dg_blocks_); - bytes += WriteStr(file, timestamp_.date_, 10); - bytes += WriteStr(file, timestamp_.time_, 8); - bytes += WriteStr(file, author_, 32); - bytes += WriteStr(file, organisation_, 32); - bytes += WriteStr(file, project_, 32); - bytes += WriteStr(file, subject_, 32); - bytes += WriteNumber(file, timestamp_.local_timestamp_); - bytes += WriteNumber(file, timestamp_.utc_offset_); - bytes += WriteNumber(file, timestamp_.time_quality_); - bytes += WriteStr(file, timestamp_.timer_id_, 32); + bytes += WriteNumber(buffer, nof_dg_blocks_); + bytes += WriteStr(buffer, timestamp_.date_, 10); + bytes += WriteStr(buffer, timestamp_.time_, 8); + bytes += WriteStr(buffer, author_, 32); + bytes += WriteStr(buffer, organisation_, 32); + bytes += WriteStr(buffer, project_, 32); + bytes += WriteStr(buffer, subject_, 32); + bytes += WriteNumber(buffer, timestamp_.local_timestamp_); + bytes += WriteNumber(buffer, timestamp_.utc_offset_); + bytes += WriteNumber(buffer, timestamp_.time_quality_); + bytes += WriteStr(buffer, timestamp_.timer_id_, 32); if (!update) { - UpdateBlockSize(file, bytes); + UpdateBlockSize(buffer, bytes); } if (!comment_.empty() && Link(kIndexTx) <= 0) { Tx3Block tx(comment_); tx.Init(*this); - tx.Write(file); - UpdateLink(file, kIndexTx, tx.FilePosition()); + tx.Write(buffer); + UpdateLink(buffer, kIndexTx, tx.FilePosition()); } if (pr_block_ && Link(kIndexPr) <= 0) { pr_block_->Init(*this); - pr_block_->Write(file); - UpdateLink(file, kIndexPr, pr_block_->FilePosition()); + pr_block_->Write(buffer); + UpdateLink(buffer, kIndexPr, pr_block_->FilePosition()); } for (size_t index = 0; index < dg_list_.size(); ++index) { @@ -202,40 +206,40 @@ size_t Hd3Block::Write(std::FILE *file) { continue; } - dg3->Write(file); + dg3->Write(buffer); if (index == 0) { - UpdateLink(file, kIndexDg, dg3->FilePosition()); + UpdateLink(buffer, kIndexDg, dg3->FilePosition()); } else { auto &prev = dg_list_[index - 1]; if (prev) { - prev->UpdateLink(file, kIndexNext, dg3->FilePosition()); + prev->UpdateLink(buffer, kIndexNext, dg3->FilePosition()); } } } return bytes; } -void Hd3Block::ReadMeasurementInfo(std::FILE *file) { +void Hd3Block::ReadMeasurementInfo(std::streambuf& buffer) { dg_list_.clear(); for (auto link = Link(kIndexDg); link > 0; /* No ++ here*/) { auto dg = std::make_unique(); dg->Init(*this); - SetFilePosition(file, link); - dg->Read(file); + SetFilePosition(buffer, link); + dg->Read(buffer); link = dg->Link(kIndexNext); dg_list_.emplace_back(std::move(dg)); } } -void Hd3Block::ReadEverythingButData(std::FILE *file) { +void Hd3Block::ReadEverythingButData(std::streambuf& buffer) { // We assume that ReadMeasurementInfo have been called earlier for (auto &dg : dg_list_) { if (!dg) { continue; } for (auto &cg : dg->Cg3()) { - cg->ReadCnList(file); - cg->ReadSrList(file); + cg->ReadCnList(buffer); + cg->ReadSrList(buffer); } } } @@ -305,4 +309,5 @@ const mdf::IMdfTimestamp *Hd3Block::StartTimestamp() const { return ×tamp_; } + } // end namespace mdf::detail \ No newline at end of file diff --git a/mdflib/src/hd3block.h b/mdflib/src/hd3block.h index 1e8bbdee..8372ef6e 100644 --- a/mdflib/src/hd3block.h +++ b/mdflib/src/hd3block.h @@ -19,7 +19,7 @@ namespace mdf::detail { class Hd3Block : public MdfBlock, public IHeader { public: using Dg3List = std::vector>; - Hd3Block() = default; + Hd3Block(); ~Hd3Block() override = default; [[nodiscard]] int64_t Index() const override; @@ -57,11 +57,11 @@ class Hd3Block : public MdfBlock, public IHeader { [[nodiscard]] std::string Comment() const override; [[nodiscard]] MdfBlock *Find(int64_t index) const override; void GetBlockProperty(BlockPropertyList &dest) const override; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; - void ReadMeasurementInfo(std::FILE *file); - void ReadEverythingButData(std::FILE *file); + void ReadMeasurementInfo(std::streambuf& buffer); + void ReadEverythingButData(std::streambuf& buffer); private: uint16_t nof_dg_blocks_ = 0; diff --git a/mdflib/src/hd4block.cpp b/mdflib/src/hd4block.cpp index 4f9f6387..d3cdd5e4 100644 --- a/mdflib/src/hd4block.cpp +++ b/mdflib/src/hd4block.cpp @@ -68,7 +68,11 @@ void SetCommonProperty(mdf::detail::Hd4Block& block, const std::string& key, namespace mdf::detail { -Hd4Block::Hd4Block() { block_type_ = "##HD"; } +Hd4Block::Hd4Block() { + block_type_ = "##HD"; + UtcTimestamp now(MdfHelper::NowNs()); + timestamp_.SetTime(now); +} MdfBlock* Hd4Block::Find(int64_t index) const { if (index <= 0) { @@ -169,48 +173,48 @@ void Hd4Block::GetBlockProperty(BlockPropertyList& dest) const { } } -size_t Hd4Block::Read(std::FILE* file) { - size_t bytes = ReadHeader4(file); +uint64_t Hd4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); timestamp_.Init(*this); - bytes += timestamp_.Read(file); + bytes += timestamp_.Read(buffer); - bytes += ReadNumber(file, time_class_); - bytes += ReadNumber(file, flags_); + bytes += ReadNumber(buffer, time_class_); + bytes += ReadNumber(buffer, flags_); std::vector reserved; - bytes += ReadByte(file, reserved, 1); - bytes += ReadNumber(file, start_angle_); - bytes += ReadNumber(file, start_distance_); + bytes += ReadByte(buffer, reserved, 1); + bytes += ReadNumber(buffer, start_angle_); + bytes += ReadNumber(buffer, start_distance_); - ReadLink4List(file, fh_list_, kIndexFh); - ReadMdComment(file, kIndexMd); + ReadLink4List(buffer, fh_list_, kIndexFh); + ReadMdComment(buffer, kIndexMd); return bytes; } -void Hd4Block::ReadMeasurementInfo(std::FILE* file) { +void Hd4Block::ReadMeasurementInfo(std::streambuf& buffer) { // We assume that the ID and HD block have been read (see ReadHeader) // Special handling of DG blocks. - ReadLink4List(file, dg_list_, kIndexDg); + ReadLink4List(buffer, dg_list_, kIndexDg); for (auto& dg4 : dg_list_) { - dg4->ReadCgList(file); + dg4->ReadCgList(buffer); } // Need to read in any attachments before we read in the channels as // they reference the attachments. - ReadLink4List(file, at_list_, kIndexAt); + ReadLink4List(buffer, at_list_, kIndexAt); } -void Hd4Block::ReadEverythingButData(std::FILE* file) { +void Hd4Block::ReadEverythingButData(std::streambuf& buffer) { // We assume that ReadMeasurementInfo have been called earlier for (auto& dg4 : dg_list_) { if (!dg4) { continue; } for (auto& cg4 : dg4->Cg4()) { - cg4->ReadCnList(file); - cg4->ReadSrList(file); + cg4->ReadCnList(buffer); + cg4->ReadSrList(buffer); // Update the VLSD record id reference on all channels // and fix the MSLD channel as well @@ -239,8 +243,8 @@ void Hd4Block::ReadEverythingButData(std::FILE* file) { } // Must read in all channels before creating CH block that references the CN // blocks - ReadLink4List(file, ch_list_, kIndexCh); - ReadLink4List(file, ev_list_, kIndexEv); + ReadLink4List(buffer, ch_list_, kIndexCh); + ReadLink4List(buffer, ev_list_, kIndexEv); // Need to scan through the event and hierarchy blocks to find the referenced // blocks for (auto& ch4 : ch_list_) { @@ -459,7 +463,7 @@ std::optional Hd4Block::StartDistance() const { return {}; } -size_t Hd4Block::Write(std::FILE* file) { +uint64_t Hd4Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // Write or update the values inside the block if (!update) { @@ -467,53 +471,53 @@ size_t Hd4Block::Write(std::FILE* file) { block_length_ = 24 + (6 * 8) + 8 + 4 + 4 + 1 + 1 + 1 + 1 + 8 + 8; link_list_.resize(6, 0); } - auto bytes = update ? MdfBlock::Update(file) : MdfBlock::Write(file); + uint64_t bytes = update ? MdfBlock::Update(buffer) : MdfBlock::Write(buffer); // These values may change after the initial write - bytes += timestamp_.Write(file); - bytes += WriteNumber(file, time_class_); - bytes += WriteNumber(file, flags_); - bytes += WriteBytes(file, 1); - bytes += WriteNumber(file, start_angle_); - bytes += WriteNumber(file, start_distance_); + bytes += timestamp_.Write(buffer); + bytes += WriteNumber(buffer, time_class_); + bytes += WriteNumber(buffer, flags_); + bytes += WriteBytes(buffer, 1); + bytes += WriteNumber(buffer, start_angle_); + bytes += WriteNumber(buffer, start_distance_); if (!update) { - UpdateBlockSize(file, bytes); + UpdateBlockSize(buffer, bytes); } - WriteLink4List(file, fh_list_, kIndexFh, + WriteLink4List(buffer, fh_list_, kIndexFh, UpdateOption::DoNotUpdateWrittenBlock); - WriteMdComment(file, kIndexMd); - WriteLink4List(file, at_list_, kIndexAt, + WriteMdComment(buffer, kIndexMd); + WriteLink4List(buffer, at_list_, kIndexAt, UpdateOption::DoNotUpdateWrittenBlock); - WriteLink4List(file, ch_list_, kIndexCh, + WriteLink4List(buffer, ch_list_, kIndexCh, UpdateOption::DoNotUpdateWrittenBlock); - WriteLink4List(file, ev_list_, kIndexEv, + WriteLink4List(buffer, ev_list_, kIndexEv, UpdateOption::DoNotUpdateWrittenBlock); // Always write the list of DG last as it may contain a DT block that shall // be appended with data bytes. The DT block must be the last written block // in these cases. - WriteLink4List(file, dg_list_, kIndexDg, + WriteLink4List(buffer, dg_list_, kIndexDg, UpdateOption::DoUpdateOnlyLastBlock); // Always rewrite last DG block return bytes; } -bool Hd4Block::FinalizeDtBlocks(std::FILE *file) { +bool Hd4Block::FinalizeDtBlocks(std::streambuf& buffer) { if (dg_list_.empty()) { return true; } Dg4Block* last_dg = dg_list_.back().get(); - return last_dg != nullptr && last_dg->FinalizeDtBlocks(file); + return last_dg != nullptr && last_dg->FinalizeDtBlocks(buffer); } -bool Hd4Block::FinalizeCgAndVlsdBlocks(std::FILE* file, bool update_cg, +bool Hd4Block::FinalizeCgAndVlsdBlocks(std::streambuf& buffer, bool update_cg, bool update_vlsd) { if (dg_list_.empty()) { return true; } auto* last_dg = dg_list_.back().get(); return last_dg != nullptr && - last_dg->FinalizeCgAndVlsdBlocks(file, update_cg, update_vlsd); + last_dg->FinalizeCgAndVlsdBlocks(buffer, update_cg, update_vlsd); } const IMdfTimestamp* Hd4Block::StartTimestamp() const { diff --git a/mdflib/src/hd4block.h b/mdflib/src/hd4block.h index a39cc757..a93fb9cb 100644 --- a/mdflib/src/hd4block.h +++ b/mdflib/src/hd4block.h @@ -108,11 +108,11 @@ class Hd4Block : public MdfBlock, public IHeader { [[nodiscard]] MdfBlock *Find(int64_t index) const override; void GetBlockProperty(BlockPropertyList &dest) const override; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; - void ReadMeasurementInfo(std::FILE *file); - void ReadEverythingButData(std::FILE *file); + void ReadMeasurementInfo(std::streambuf& buffer); + void ReadEverythingButData(std::streambuf& buffer); [[nodiscard]] IEvent *CreateEvent() override; [[nodiscard]] std::vector Events() const override; @@ -122,9 +122,9 @@ class Hd4Block : public MdfBlock, public IHeader { const override; IDataGroup *CreateDataGroup() override; - bool FinalizeDtBlocks(std::FILE* file); - bool FinalizeCgAndVlsdBlocks(std::FILE* file, bool update_cg, bool update_vlsd); - bool UpdateVlsdBlocks(std::FILE* file); + bool FinalizeDtBlocks(std::streambuf& buffer); + bool FinalizeCgAndVlsdBlocks(std::streambuf& buffer, bool update_cg, bool update_vlsd); + bool UpdateVlsdBlocks(std::streambuf& buffer); private: Mdf4Timestamp timestamp_; diff --git a/mdflib/src/hl4block.cpp b/mdflib/src/hl4block.cpp index 33a57bd5..75b1a965 100644 --- a/mdflib/src/hl4block.cpp +++ b/mdflib/src/hl4block.cpp @@ -42,22 +42,22 @@ void Hl4Block::GetBlockProperty(BlockPropertyList &dest) const { dest.emplace_back("Zip Type", MakeZipTypeString(type_)); } -size_t Hl4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - bytes += ReadNumber(file, flags_); - bytes += ReadNumber(file, type_); +uint64_t Hl4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadNumber(buffer, flags_); + bytes += ReadNumber(buffer, type_); std::vector reserved; - bytes += ReadByte(file, reserved, 5); - ReadBlockList(file, kIndexNext); + bytes += ReadByte(buffer, reserved, 5); + ReadBlockList(buffer, kIndexNext); return bytes; } -size_t Hl4Block::Write(std::FILE *file) { +uint64_t Hl4Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // Write or update the values inside the block if (update) { // Note that the block_list is used for the dl_list - WriteLink4List(file, block_list_,kIndexNext, + WriteLink4List(buffer, block_list_,kIndexNext, UpdateOption::DoNotUpdateWrittenBlock); // Only save non-updated return block_length_; } @@ -66,13 +66,13 @@ size_t Hl4Block::Write(std::FILE *file) { block_length_ = 24 + (1*8) + 2 + 1 + 5; link_list_.resize(1, 0); - auto bytes = MdfBlock::Write(file); - bytes += WriteNumber(file,flags_); - bytes += WriteNumber(file,type_); - bytes += WriteBytes(file, 5); - UpdateBlockSize(file, bytes); + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteNumber(buffer,flags_); + bytes += WriteNumber(buffer,type_); + bytes += WriteBytes(buffer, 5); + UpdateBlockSize(buffer, bytes); - WriteLink4List(file, block_list_,kIndexNext, + WriteLink4List(buffer, block_list_,kIndexNext, UpdateOption::DoNotUpdateWrittenBlock); // Only save non-updated return bytes; } diff --git a/mdflib/src/hl4block.h b/mdflib/src/hl4block.h index 5dc09024..0b7a727e 100644 --- a/mdflib/src/hl4block.h +++ b/mdflib/src/hl4block.h @@ -31,8 +31,8 @@ class Hl4Block : public DataListBlock { } void GetBlockProperty(BlockPropertyList& dest) const override; - size_t Read(std::FILE* file) override; - size_t Write(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; private: uint16_t flags_ = 0; uint8_t type_ = 0; // ZIP types diff --git a/mdflib/src/ichannel.cpp b/mdflib/src/ichannel.cpp index d1934458..f15f4c97 100644 --- a/mdflib/src/ichannel.cpp +++ b/mdflib/src/ichannel.cpp @@ -18,7 +18,7 @@ bool IChannel::GetUnsignedValue(const std::vector &record_buffer, uint64_t array_index) const { const size_t bit_offset = (ByteOffset() * 8 + BitOffset()) - + (array_index * BitCount()); + + static_cast( (array_index * BitCount()) ); if (Type() == ChannelType::VariableLength) { dest = detail::DbcHelper::RawToUnsigned(true, bit_offset, @@ -61,7 +61,7 @@ bool IChannel::GetSignedValue(const std::vector &record_buffer, // std::vector data_buffer; // CopyToDataBuffer(record_buffer, data_buffer, array_index); const size_t bit_offset = (ByteOffset() * 8 + BitOffset()) - + (array_index * BitCount()); + + static_cast( (array_index * BitCount()) ); const bool little_endian = DataType() == ChannelDataType::SignedIntegerLe; dest = detail::DbcHelper::RawToSigned(little_endian, bit_offset, @@ -74,7 +74,7 @@ bool IChannel::GetFloatValue(const std::vector &record_buffer, double &dest, uint64_t array_index ) const { const size_t bit_offset = (ByteOffset() * 8 + BitOffset()) - + (array_index * BitCount()); + + static_cast( (array_index * BitCount()) ); const bool little_endian = DataType() == ChannelDataType::FloatLe; bool valid = true; switch (BitCount()) { @@ -191,7 +191,7 @@ bool IChannel::GetTextValue(const std::vector &record_buffer, bool IChannel::GetByteArrayValue(const std::vector &record_buffer, std::vector &dest) const { try { - dest.resize(DataBytes(), 0); + dest.resize(static_cast(DataBytes()), 0); } catch (const std::exception&) { return false; } @@ -200,7 +200,7 @@ bool IChannel::GetByteArrayValue(const std::vector &record_buffer, } else { if (dest.size() != DataBytes()) { try { - dest.resize(DataBytes()); + dest.resize(static_cast(DataBytes()) ); } catch (const std::exception&) { return false; } @@ -208,8 +208,8 @@ bool IChannel::GetByteArrayValue(const std::vector &record_buffer, if (dest.empty()) { return true; } - if (ByteOffset() + DataBytes() <= record_buffer.size()) { - memcpy(dest.data(), record_buffer.data() + ByteOffset(), DataBytes()); + if (ByteOffset() + static_cast(DataBytes()) <= record_buffer.size()) { + memcpy(dest.data(), record_buffer.data() + ByteOffset(), static_cast(DataBytes()) ); } else { return false; } @@ -258,7 +258,7 @@ void IChannel::SetUnsignedValueLe(uint64_t value, bool valid, return; // Invalid use of function } - const size_t bytes = DataBytes(); + const auto bytes = static_cast(DataBytes()); const auto max_bytes = ByteOffset() + (bytes * (array_index + 1)); if (max_bytes > buffer.size()) { @@ -305,7 +305,7 @@ void IChannel::SetUnsignedValueBe(uint64_t value, bool valid, uint64_t array_ind MDF_ERROR() << "Sample buffer not sized. Invalid use of function."; return; // Invalid use of function } - const size_t bytes = DataBytes(); + const size_t bytes = static_cast(DataBytes()); const auto max_bytes = ByteOffset() + (bytes * array_index); if (max_bytes > buffer.size()) { @@ -352,7 +352,7 @@ void IChannel::SetSignedValueLe(int64_t value, bool valid, MDF_ERROR() << "Sample buffer not sized. Invalid use of function."; return; // Invalid use of function } - const size_t bytes = DataBytes(); + const size_t bytes = static_cast(DataBytes()); const auto max_bytes = ByteOffset() + (bytes * (array_index + 1)); if (max_bytes > buffer.size()) { @@ -400,7 +400,7 @@ void IChannel::SetSignedValueBe(int64_t value, bool valid, MDF_ERROR() << "Sample buffer not sized. Invalid use of function."; return; // Invalid use of function } - const size_t bytes = DataBytes(); + const size_t bytes = static_cast( DataBytes() ); const auto max_bytes = ByteOffset() + (bytes * (array_index + 1)); if (max_bytes > buffer.size()) { @@ -446,7 +446,7 @@ void IChannel::SetFloatValueLe(double value, bool valid, uint64_t array_index) { MDF_ERROR() << "Sample buffer not sized. Invalid use of function."; return; // Invalid use of function } - const size_t bytes = DataBytes(); + const size_t bytes = static_cast(DataBytes()); const auto max_bytes = ByteOffset() + (bytes * (array_index + 1)); if (max_bytes > buffer.size()) { @@ -481,7 +481,7 @@ void IChannel::SetFloatValueBe(double value, bool valid, uint64_t array_index) { MDF_ERROR() << "Sample buffer not sized. Invalid use of function."; return; // Invalid use of function } - const size_t bytes = DataBytes(); + const size_t bytes = static_cast( DataBytes() ); const auto max_bytes = ByteOffset() + (bytes * (array_index + 1)); if (max_bytes > buffer.size()) { diff --git a/mdflib/src/ichannelarray.cpp b/mdflib/src/ichannelarray.cpp index cc187bbe..863be25c 100644 --- a/mdflib/src/ichannelarray.cpp +++ b/mdflib/src/ichannelarray.cpp @@ -21,7 +21,7 @@ std::string IChannelArray::DimensionAsString() const { } std::vector& IChannelArray::DataLinks() { - const size_t prod_dim = ProductOfArray(); + const size_t prod_dim = static_cast( ProductOfArray() ); if (Storage() == ArrayStorage::DgTemplate && data_links_.size() < prod_dim) { data_links_.resize(prod_dim, 0); @@ -64,8 +64,8 @@ std::vector& IChannelArray::AxisList() { void IChannelArray::ResizeArrays() { const size_t dim = Dimensions(); - const size_t sum_of_array = SumOfArray(); - const size_t prod_of_array = ProductOfArray(); + const size_t sum_of_array = static_cast( SumOfArray() ); + const size_t prod_of_array = static_cast( ProductOfArray() ); if (Storage() == ArrayStorage::DgTemplate && data_links_.size() != prod_of_array) { data_links_.resize(prod_of_array,0); diff --git a/mdflib/src/idatagroup.cpp b/mdflib/src/idatagroup.cpp index 9b3e0f5f..8bfa35fb 100644 --- a/mdflib/src/idatagroup.cpp +++ b/mdflib/src/idatagroup.cpp @@ -32,7 +32,7 @@ void IDataGroup::DetachSampleObserver(const ISampleObserver *observer) const { void IDataGroup::DetachAllSampleObservers() const { observer_list_.clear(); } -bool IDataGroup::NotifySampleObservers(size_t sample, uint64_t record_id, +bool IDataGroup::NotifySampleObservers(uint64_t sample, uint64_t record_id, const std::vector &record) const { if (fast_observer_list_.empty()) { return false; // No meaning to continue reading diff --git a/mdflib/src/idblock.cpp b/mdflib/src/idblock.cpp index b508ebac..bb99e4b9 100644 --- a/mdflib/src/idblock.cpp +++ b/mdflib/src/idblock.cpp @@ -72,48 +72,46 @@ void IdBlock::GetBlockProperty(BlockPropertyList &dest) const { } -size_t IdBlock::Read(std::FILE *file) { +uint64_t IdBlock::Read(std::streambuf& buffer) { block_type_ = "ID"; block_length_ = 64; - file_position_ = GetFilePosition(file); - size_t bytes = ReadStr(file, file_identifier_, 8); - bytes += ReadStr(file, format_identifier_, 8); - bytes += ReadStr(file, program_identifier_, 8); - bytes += ReadNumber(file, byte_order_); // Note defined in MdfBlock class - bytes += ReadNumber(file, floating_point_format_); - bytes += ReadNumber(file, version_); - bytes += ReadNumber(file, code_page_number_); + file_position_ = GetFilePosition(buffer); + uint64_t bytes = ReadStr(buffer, file_identifier_, 8); + bytes += ReadStr(buffer, format_identifier_, 8); + bytes += ReadStr(buffer, program_identifier_, 8); + bytes += ReadNumber(buffer, byte_order_); // Note defined in MdfBlock class + bytes += ReadNumber(buffer, floating_point_format_); + bytes += ReadNumber(buffer, version_); + bytes += ReadNumber(buffer, code_page_number_); std::vector reserved; - bytes += ReadByte(file, reserved, 28); - bytes += ReadNumber(file, standard_flags_); - bytes += ReadNumber(file, custom_flags_); + bytes += ReadByte(buffer, reserved, 28); + bytes += ReadNumber(buffer, standard_flags_); + bytes += ReadNumber(buffer, custom_flags_); return bytes; } -size_t IdBlock::Write(std::FILE *file) { +uint64_t IdBlock::Write(std::streambuf& buffer) { // Check if it has been written. Update is not supported in ID if (FilePosition() == 0) { return 64; } // Do not call MdfBlock::Write(file) as the other block writes do - if (file == nullptr) { - throw std::runtime_error("File pointer is null"); - } - SetFirstFilePosition(file); - file_position_ = GetFilePosition(file); - size_t bytes = WriteStr(file, file_identifier_, 8); - bytes += WriteStr(file, format_identifier_, 8); - bytes += WriteStr(file, program_identifier_, 8); - bytes += WriteNumber(file, byte_order_); - bytes += WriteNumber(file, floating_point_format_); - bytes += WriteNumber(file, version_); - bytes += WriteNumber(file, code_page_number_); + + SetFirstFilePosition(buffer); + file_position_ = GetFilePosition(buffer); + uint64_t bytes = WriteStr(buffer, file_identifier_, 8); + bytes += WriteStr(buffer, format_identifier_, 8); + bytes += WriteStr(buffer, program_identifier_, 8); + bytes += WriteNumber(buffer, byte_order_); + bytes += WriteNumber(buffer, floating_point_format_); + bytes += WriteNumber(buffer, version_); + bytes += WriteNumber(buffer, code_page_number_); std::vector reserved(28, 0); - bytes += WriteByte(file, reserved); - bytes += WriteNumber(file, standard_flags_); - bytes += WriteNumber(file, custom_flags_); + bytes += WriteByte(buffer, reserved); + bytes += WriteNumber(buffer, standard_flags_); + bytes += WriteNumber(buffer, custom_flags_); if (bytes != 64) { throw std::runtime_error("ID block not 64 bytes"); } @@ -173,7 +171,7 @@ void IdBlock::MinorVersion(int minor) { version_ = 100 * major + minor; } -void IdBlock::IsFinalized(bool finalized, std::FILE *file, +void IdBlock::IsFinalized(bool finalized, std::streambuf& buffer, uint16_t standard_flags, uint16_t custom_flags) { if (finalized) { file_identifier_ = "MDF "; @@ -186,12 +184,12 @@ void IdBlock::IsFinalized(bool finalized, std::FILE *file, } // Check if the file also needs update - if (file != nullptr && FilePosition() == 0) { - SetFirstFilePosition(file); - WriteStr(file, file_identifier_, 8); - SetFilePosition(file, 60); - WriteNumber(file, standard_flags_); - WriteNumber(file, custom_flags_); + if (FilePosition() == 0) { + SetFirstFilePosition(buffer); + WriteStr(buffer, file_identifier_, 8); + SetFilePosition(buffer, 60); + WriteNumber(buffer, standard_flags_); + WriteNumber(buffer, custom_flags_); } } diff --git a/mdflib/src/idblock.h b/mdflib/src/idblock.h index 4eef9fd6..c8b87779 100644 --- a/mdflib/src/idblock.h +++ b/mdflib/src/idblock.h @@ -10,8 +10,8 @@ class IdBlock : public MdfBlock { public: IdBlock(); void GetBlockProperty(BlockPropertyList &dest) const override; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; [[nodiscard]] std::string FileId() const; [[nodiscard]] std::string VersionString() const; @@ -22,7 +22,7 @@ class IdBlock : public MdfBlock { [[nodiscard]] std::string ProgramId() const; - void IsFinalized(bool finalized, std::FILE *file, uint16_t standard_flags, + void IsFinalized(bool finalized, std::streambuf& buffer, uint16_t standard_flags, uint16_t custom_flags); [[nodiscard]] bool IsFinalized(uint16_t &standard_flags, uint16_t &custom_flags) const; diff --git a/mdflib/src/ld4block.cpp b/mdflib/src/ld4block.cpp index 6101eeda..1ce312fb 100644 --- a/mdflib/src/ld4block.cpp +++ b/mdflib/src/ld4block.cpp @@ -65,42 +65,42 @@ void Ld4Block::GetBlockProperty(BlockPropertyList &dest) const { } } -size_t Ld4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - bytes += ReadNumber(file, flags_); - bytes += ReadNumber(file, nof_blocks_); +uint64_t Ld4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadNumber(buffer, flags_); + bytes += ReadNumber(buffer, nof_blocks_); if (flags_ & Ld4Flags::EqualSampleCount) { - bytes += ReadNumber(file, equal_sample_count_); + bytes += ReadNumber(buffer, equal_sample_count_); } else { for (uint32_t ii = 0; ii < nof_blocks_; ++ii) { uint64_t offset = 0; - bytes += ReadNumber(file, offset); + bytes += ReadNumber(buffer, offset); offset_list_.push_back(offset); } } if (flags_ & Ld4Flags::TimeValues) { for (uint32_t ii = 0; ii < nof_blocks_; ++ii) { int64_t value = 0; - bytes += ReadNumber(file, value); + bytes += ReadNumber(buffer, value); time_values_.push_back(value); } } if (flags_ & Ld4Flags::AngleValues) { for (uint32_t ii = 0; ii < nof_blocks_; ++ii) { int64_t value = 0; - bytes += ReadNumber(file, value); + bytes += ReadNumber(buffer, value); angle_values_.push_back(value); } } if (flags_ & Ld4Flags::DistanceValues) { for (uint32_t ii = 0; ii < nof_blocks_; ++ii) { int64_t value = 0; - bytes += ReadNumber(file, value); + bytes += ReadNumber(buffer, value); distance_values_.push_back(value); } } - ReadLinkList(file, kIndexData, nof_blocks_); + ReadLinkList(buffer, kIndexData, nof_blocks_); return bytes; } } // namespace mdf::detail diff --git a/mdflib/src/ld4block.h b/mdflib/src/ld4block.h index aeffb3d3..764a5f8a 100644 --- a/mdflib/src/ld4block.h +++ b/mdflib/src/ld4block.h @@ -19,7 +19,7 @@ constexpr uint32_t InvalidData = 0x80000000; class Ld4Block : public DataListBlock { public: void GetBlockProperty(BlockPropertyList& dest) const override; - size_t Read(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; private: uint32_t flags_ = 0; diff --git a/mdflib/src/mdf3file.cpp b/mdflib/src/mdf3file.cpp index c580c2eb..2b486e59 100644 --- a/mdflib/src/mdf3file.cpp +++ b/mdflib/src/mdf3file.cpp @@ -38,13 +38,13 @@ void Mdf3File::DataGroups(DataGroupList &dest) const { IHeader *Mdf3File::Header() const { return hd_block_.get(); } -void Mdf3File::ReadHeader(std::FILE *file) { +void Mdf3File::ReadHeader(std::streambuf& buffer) { if (!id_block_) { id_block_ = std::make_unique(); } if (id_block_->FilePosition() < 0) { - SetFilePosition(file, 0); - id_block_->Read(file); + SetFilePosition(buffer, 0); + id_block_->Read(buffer); } if (!hd_block_) { @@ -52,22 +52,22 @@ void Mdf3File::ReadHeader(std::FILE *file) { } if (hd_block_->FilePosition() <= 0) { hd_block_->Init(*id_block_); - SetFilePosition(file, 64); - hd_block_->Read(file); + SetFilePosition(buffer, 64); + hd_block_->Read(buffer); } } -void Mdf3File::ReadMeasurementInfo(std::FILE *file) { - ReadHeader(file); +void Mdf3File::ReadMeasurementInfo(std::streambuf& buffer) { + ReadHeader(buffer); if (hd_block_) { - hd_block_->ReadMeasurementInfo(file); + hd_block_->ReadMeasurementInfo(buffer); } } -void Mdf3File::ReadEverythingButData(std::FILE *file) { - ReadHeader(file); +void Mdf3File::ReadEverythingButData(std::streambuf& buffer) { + ReadHeader(buffer); if (hd_block_) { - hd_block_->ReadMeasurementInfo(file); - hd_block_->ReadEverythingButData(file); + hd_block_->ReadMeasurementInfo(buffer); + hd_block_->ReadEverythingButData(buffer); } } bool Mdf3File::IsMdf4() const { return false; } @@ -106,18 +106,15 @@ IDataGroup *Mdf3File::CreateDataGroup() { return hd_block_ ? hd_block_->CreateDataGroup() : nullptr; } -bool Mdf3File::Write(std::FILE *file) { - if (file == nullptr) { - MDF_ERROR() << "File pointer is null. Invalid use of function."; - return false; - } +bool Mdf3File::Write(std::streambuf& buffer) { + if (!id_block_ || !hd_block_) { MDF_ERROR() << "No ID or HD block defined. Invalid use of function."; return false; } try { - id_block_->Write(file); - hd_block_->Write(file); + id_block_->Write(buffer); + hd_block_->Write(buffer); } catch (const std::exception &err) { MDF_ERROR() << "Failed to write MDF3 file. Error: " << err.what(); } @@ -143,10 +140,10 @@ void Mdf3File::MinorVersion(int minor) { id_block_->MinorVersion(minor); } } -void Mdf3File::IsFinalized(bool finalized, std::FILE *file, +void Mdf3File::IsFinalized(bool finalized, std::streambuf& buffer, uint16_t standard_flags, uint16_t custom_flags) { if (id_block_) { - id_block_->IsFinalized(finalized, file, standard_flags, custom_flags); + id_block_->IsFinalized(finalized, buffer, standard_flags, custom_flags); } } diff --git a/mdflib/src/mdf3file.h b/mdflib/src/mdf3file.h index ad91ce62..b9e38c30 100644 --- a/mdflib/src/mdf3file.h +++ b/mdflib/src/mdf3file.h @@ -33,19 +33,19 @@ class Mdf3File : public MdfFile { [[nodiscard]] MdfBlock *Find(int64_t id) const; [[nodiscard]] bool IsMdf4() const override; - void IsFinalized(bool finalized, std::FILE *file, uint16_t standard_flags, + void IsFinalized(bool finalized, std::streambuf& buffer, uint16_t standard_flags, uint16_t custom_flags) override; [[nodiscard]] bool IsFinalized(uint16_t &standard_flags, uint16_t &custom_flags) const override; - void ReadHeader(std::FILE *file) override; - void ReadMeasurementInfo(std::FILE *file) override; - void ReadEverythingButData(std::FILE *file) override; + void ReadHeader(std::streambuf& buffer) override; + void ReadMeasurementInfo(std::streambuf& buffer) override; + void ReadEverythingButData(std::streambuf& buffer) override; [[nodiscard]] const IdBlock &Id() const; [[nodiscard]] const Hd3Block &Hd() const; - bool Write(std::FILE *file) override; + bool Write(std::streambuf& buffer) override; Mdf3File(const Mdf3File &) = delete; Mdf3File(Mdf3File &&) = delete; diff --git a/mdflib/src/mdf3timestamp.cpp b/mdflib/src/mdf3timestamp.cpp index c838ae9f..9fd4085e 100644 --- a/mdflib/src/mdf3timestamp.cpp +++ b/mdflib/src/mdf3timestamp.cpp @@ -8,9 +8,11 @@ void Mdf3Timestamp::GetBlockProperty(detail::BlockPropertyList& dest) const { MdfBlock::GetBlockProperty(dest); } -size_t Mdf3Timestamp::Read(std::FILE* file) { return 0; } +uint64_t Mdf3Timestamp::Read(std::streambuf& buffer) { return 0; } -size_t Mdf3Timestamp::Write(std::FILE* file) { return MdfBlock::Write(file); } +uint64_t Mdf3Timestamp::Write(std::streambuf& buffer) { + return MdfBlock::Write(buffer); +} void Mdf3Timestamp::SetTime(uint64_t time) { date_ = MdfHelper::NanoSecToDDMMYYYY(time); diff --git a/mdflib/src/mdf3timestamp.h b/mdflib/src/mdf3timestamp.h index e848dd5a..bbdd80da 100644 --- a/mdflib/src/mdf3timestamp.h +++ b/mdflib/src/mdf3timestamp.h @@ -8,8 +8,8 @@ namespace mdf::detail { class Mdf3Timestamp : public IMdfTimestamp, public MdfBlock { public: void GetBlockProperty(detail::BlockPropertyList &dest) const override; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; void SetTime(uint64_t time) override; void SetTime(ITimestamp ×tamp) override; diff --git a/mdflib/src/mdf3writer.cpp b/mdflib/src/mdf3writer.cpp index b2b7d596..41863653 100644 --- a/mdflib/src/mdf3writer.cpp +++ b/mdflib/src/mdf3writer.cpp @@ -30,8 +30,8 @@ void Mdf3Writer::CreateMdfFile() { mdf_file_ = std::move(mdf3); } -void Mdf3Writer::SetLastPosition(std::FILE *file) { - Platform::fseek64(file, 0, SEEK_END); +void Mdf3Writer::SetLastPosition(std::streambuf& buffer) { + buffer.pubseekoff(0, std::ios_base::end); auto *header = Header(); if (header == nullptr) { @@ -50,10 +50,10 @@ void Mdf3Writer::SetLastPosition(std::FILE *file) { return; } - dg3->SetLastFilePosition(file); - auto position = detail::GetFilePosition(file); - dg3->UpdateLink(file, 3, position); - dg3->SetLastFilePosition(file); + dg3->SetLastFilePosition(buffer); + auto position = detail::GetFilePosition(buffer); + dg3->UpdateLink(buffer, 3, position); + dg3->SetLastFilePosition(buffer); } bool Mdf3Writer::PrepareForWriting() { diff --git a/mdflib/src/mdf3writer.h b/mdflib/src/mdf3writer.h index d3c7af4c..9b5b43e5 100644 --- a/mdflib/src/mdf3writer.h +++ b/mdflib/src/mdf3writer.h @@ -19,7 +19,7 @@ class Mdf3Writer : public MdfWriter { protected: void CreateMdfFile() override; bool PrepareForWriting() override; - void SetLastPosition(std::FILE* file) override; + void SetLastPosition(std::streambuf& buffer) override; }; } // namespace mdf::detail diff --git a/mdflib/src/mdf4file.cpp b/mdflib/src/mdf4file.cpp index 7b44c9d6..916c134c 100644 --- a/mdflib/src/mdf4file.cpp +++ b/mdflib/src/mdf4file.cpp @@ -22,39 +22,39 @@ Mdf4File::Mdf4File(std::unique_ptr id_block) IHeader *Mdf4File::Header() const { return hd_block_.get(); } -void Mdf4File::ReadHeader(std::FILE *file) { +void Mdf4File::ReadHeader(std::streambuf& buffer) { if (!id_block_) { id_block_ = std::make_unique(); - SetFilePosition(file, 0); - id_block_->Read(file); + SetFilePosition(buffer, 0); + id_block_->Read(buffer); } if (!hd_block_) { hd_block_ = std::make_unique(); hd_block_->Init(*id_block_); - SetFilePosition(file, 64); - hd_block_->Read(file); + SetFilePosition(buffer, 64); + hd_block_->Read(buffer); } } -void Mdf4File::ReadMeasurementInfo(std::FILE *file) { - ReadHeader(file); +void Mdf4File::ReadMeasurementInfo(std::streambuf& buffer) { + ReadHeader(buffer); if (hd_block_) { - hd_block_->ReadMeasurementInfo(file); + hd_block_->ReadMeasurementInfo(buffer); } } -void Mdf4File::ReadEverythingButData(std::FILE *file) { - ReadHeader(file); +void Mdf4File::ReadEverythingButData(std::streambuf& buffer) { + ReadHeader(buffer); if (hd_block_) { - hd_block_->ReadMeasurementInfo(file); - hd_block_->ReadEverythingButData(file); + hd_block_->ReadMeasurementInfo(buffer); + hd_block_->ReadEverythingButData(buffer); } // Now when all blocks are read in, it is time to read // in all referenced blocks. // This is mainly done for the channel array blocks. - FindAllReferences(file); + FindAllReferences(buffer); // Check if the file needs to be finalized uint16_t standard_flags = 0; @@ -62,7 +62,7 @@ void Mdf4File::ReadEverythingButData(std::FILE *file) { if (!finalized_done_ && id_block_ && !id_block_->IsFinalized(standard_flags, custom_flags)) { // Try to finalize the last DG block. - finalized_done_ = FinalizeFile(file); + finalized_done_ = FinalizeFile(buffer); } } @@ -159,19 +159,16 @@ IDataGroup *Mdf4File::CreateDataGroup() { return dg; } -bool Mdf4File::Write(std::FILE *file) { - if (file == nullptr) { - MDF_ERROR() << "File pointer is null. Invalid use of function."; - return false; - } +bool Mdf4File::Write(std::streambuf& buffer) { + if (!id_block_ || !hd_block_) { MDF_ERROR() << "No ID or HD block defined. Invalid use of function."; return false; } try { - id_block_->Write(file); - hd_block_->Write(file); + id_block_->Write(buffer); + hd_block_->Write(buffer); } catch (const std::exception &err) { MDF_ERROR() << "Failed to write the MDF4 file. Error: " << err.what(); return false; @@ -179,10 +176,10 @@ bool Mdf4File::Write(std::FILE *file) { return true; } -void Mdf4File::IsFinalized(bool finalized, std::FILE *file, +void Mdf4File::IsFinalized(bool finalized, std::streambuf& buffer, uint16_t standard_flags, uint16_t custom_flags) { if (id_block_) { - id_block_->IsFinalized(finalized, file, standard_flags, custom_flags); + id_block_->IsFinalized(finalized, buffer, standard_flags, custom_flags); } } @@ -198,7 +195,7 @@ bool Mdf4File::IsFinalized(uint16_t &standard_flags, return finalized; } -bool Mdf4File::FinalizeFile(std::FILE* file) { +bool Mdf4File::FinalizeFile(std::streambuf& buffer) { uint16_t standard_flags = 0; uint16_t custom_flags = 0; @@ -228,7 +225,7 @@ bool Mdf4File::FinalizeFile(std::FILE* file) { } if (update_dt_blocks) { // Update the number of bytes in the DT block. - const bool update_dt = hd_block_->FinalizeDtBlocks(file); + const bool update_dt = hd_block_->FinalizeDtBlocks(buffer); if (!update_dt) { MDF_ERROR() << "Fail to finalize last DT block. File: " << Name(); updated = false; @@ -241,7 +238,7 @@ bool Mdf4File::FinalizeFile(std::FILE* file) { if (update_cg_blocks || update_vlsd_bytes || update_vlsd_offset ) { const bool update_nof_samples = hd_block_->FinalizeCgAndVlsdBlocks( - file, update_cg_blocks, update_vlsd_bytes || update_vlsd_offset); + buffer, update_cg_blocks, update_vlsd_bytes || update_vlsd_offset); if (!update_nof_samples) { MDF_ERROR() << "Failed to update number of samples and VLSD block sizes. File: " << Name(); updated = false; @@ -268,7 +265,7 @@ IDataGroup *Mdf4File::FindParentDataGroup(const IChannel &channel) const { return itr != dg_list.cend() ? itr->get() : nullptr; } -void Mdf4File::FindAllReferences(std::FILE *file) { +void Mdf4File::FindAllReferences(std::streambuf& buffer) { // Find all channel arrays if (!hd_block_) { return; @@ -295,7 +292,7 @@ void Mdf4File::FindAllReferences(std::FILE *file) { try { auto* ca4 = dynamic_cast (block.get()); if (ca4 != nullptr) { - ca4->FindAllReferences(file); + ca4->FindAllReferences(buffer); } } catch (const std::exception& ) { } diff --git a/mdflib/src/mdf4file.h b/mdflib/src/mdf4file.h index dad54b10..698bafcb 100644 --- a/mdflib/src/mdf4file.h +++ b/mdflib/src/mdf4file.h @@ -41,20 +41,20 @@ class Mdf4File : public MdfFile { [[nodiscard]] bool IsMdf4() const override; - void IsFinalized(bool finalized, std::FILE* file, uint16_t standard_flags, + void IsFinalized(bool finalized, std::streambuf& buffer, uint16_t standard_flags, uint16_t custom_flags) override; [[nodiscard]] bool IsFinalized(uint16_t& standard_flags, uint16_t& custom_flags) const override; [[nodiscard]] bool IsFinalizedDone() const override; - void ReadHeader(std::FILE* file) override; - void ReadMeasurementInfo(std::FILE* file) override; - void ReadEverythingButData(std::FILE* file) override; + void ReadHeader(std::streambuf& buffer) override; + void ReadMeasurementInfo(std::streambuf& buffer) override; + void ReadEverythingButData(std::streambuf& buffer) override; [[nodiscard]] const IdBlock& Id() const; [[nodiscard]] const Hd4Block& Hd() const; - bool Write(std::FILE* file) override; + bool Write(std::streambuf& buffer) override; [[nodiscard]] IDataGroup* FindParentDataGroup( const IChannel& channel) const override; @@ -64,7 +64,7 @@ class Mdf4File : public MdfFile { std::unique_ptr hd_block_; bool finalized_done_ = false; - bool FinalizeFile(std::FILE* file); - void FindAllReferences(std::FILE* file); + bool FinalizeFile(std::streambuf& buffer); + void FindAllReferences(std::streambuf& buffer); }; } // namespace mdf::detail diff --git a/mdflib/src/mdf4timestamp.cpp b/mdflib/src/mdf4timestamp.cpp index d2becc3b..4dabc07e 100644 --- a/mdflib/src/mdf4timestamp.cpp +++ b/mdflib/src/mdf4timestamp.cpp @@ -20,25 +20,25 @@ void Mdf4Timestamp::GetBlockProperty(detail::BlockPropertyList &dest) const { dest.emplace_back("Time Flags", flags.str()); } -size_t Mdf4Timestamp::Read(std::FILE *file) { - file_position_ = detail::GetFilePosition(file); - size_t bytes = ReadNumber(file, time_); - bytes += ReadNumber(file, tz_offset_); - bytes += ReadNumber(file, dst_offset_); - bytes += ReadNumber(file, flags_); +uint64_t Mdf4Timestamp::Read(std::streambuf& buffer) { + file_position_ = detail::GetFilePosition(buffer); + uint64_t bytes = ReadNumber(buffer, time_); + bytes += ReadNumber(buffer, tz_offset_); + bytes += ReadNumber(buffer, dst_offset_); + bytes += ReadNumber(buffer, flags_); return bytes; } -size_t Mdf4Timestamp::Write(std::FILE *file) { +uint64_t Mdf4Timestamp::Write(std::streambuf& buffer) { if (file_position_ <= 0) { - file_position_ = detail::GetFilePosition(file); + file_position_ = detail::GetFilePosition(buffer); } else { - detail::SetFilePosition(file, file_position_); + detail::SetFilePosition(buffer, file_position_); } - auto bytes = WriteNumber(file, time_); - bytes += WriteNumber(file, tz_offset_); - bytes += WriteNumber(file, dst_offset_); - bytes += WriteNumber(file, flags_); + uint64_t bytes = WriteNumber(buffer, time_); + bytes += WriteNumber(buffer, tz_offset_); + bytes += WriteNumber(buffer, dst_offset_); + bytes += WriteNumber(buffer, flags_); return bytes; } diff --git a/mdflib/src/mdf4timestamp.h b/mdflib/src/mdf4timestamp.h index 59610ae6..2df9222f 100644 --- a/mdflib/src/mdf4timestamp.h +++ b/mdflib/src/mdf4timestamp.h @@ -22,8 +22,8 @@ class Mdf4Timestamp : public IMdfTimestamp, public detail::MdfBlock { public: Mdf4Timestamp(); void GetBlockProperty(detail::BlockPropertyList &dest) const override; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; void SetTime(uint64_t time) override; void SetTime(ITimestamp ×tamp) override; diff --git a/mdflib/src/mdf4writer.cpp b/mdflib/src/mdf4writer.cpp index 7af64f67..2fbe0134 100644 --- a/mdflib/src/mdf4writer.cpp +++ b/mdflib/src/mdf4writer.cpp @@ -5,6 +5,7 @@ #include "mdf4writer.h" #include +#include #include "mdf/mdflogstream.h" #include "mdf4file.h" #include "platform.h" @@ -37,8 +38,8 @@ void Mdf4Writer::CreateMdfFile() { mdf_file_ = std::move(mdf4); } -void Mdf4Writer::SetLastPosition(std::FILE* file) { - Platform::fseek64(file, 0, SEEK_END); +void Mdf4Writer::SetLastPosition(std::streambuf& buffer) { + buffer.pubseekoff(0, std::ios_base::end); auto* header = Header(); if (header == nullptr) { @@ -57,10 +58,10 @@ void Mdf4Writer::SetLastPosition(std::FILE* file) { return; } - dg4->SetLastFilePosition(file); - auto position = GetFilePosition(file); - dg4->UpdateLink(file, 2, position); - dg4->SetLastFilePosition(file); + dg4->SetLastFilePosition(buffer); + auto position = GetFilePosition(buffer); + dg4->UpdateLink(buffer, 2, position); + dg4->SetLastFilePosition(buffer); } bool Mdf4Writer::PrepareForWriting() { @@ -143,9 +144,9 @@ void Mdf4Writer::SaveQueue(std::unique_lock& lock) { } lock.unlock(); - std::FILE* file = nullptr; - Platform::fileopen(&file, filename_.c_str(), "r+b"); - if (file == nullptr) { + std::filebuf file; + file.open(filename_, std::ios_base::in | std::ios_base::out | std::ios_base::binary); + if (!file.is_open()) { lock.lock(); return; } @@ -220,7 +221,7 @@ void Mdf4Writer::SaveQueue(std::unique_lock& lock) { uint64_t block_length = 24 + (last_position - data_position); dt4->UpdateBlockSize(file, block_length); dg4->Write(file); // Flush out data - fclose(file); + file.close(); lock.lock(); } @@ -285,9 +286,9 @@ void Mdf4Writer::CleanQueueCompressed(std::unique_lock& lock, // Open the file for writing lock.unlock(); - std::FILE* file = nullptr; - Platform::fileopen(&file, filename_.c_str(), "r+b"); - if (file == nullptr) { + std::filebuf file; + file.open(filename_, std::ios_base::in | std::ios_base::out | std::ios_base::binary); + if (!file.is_open()) { lock.lock(); return; } @@ -433,13 +434,13 @@ void Mdf4Writer::CleanQueueCompressed(std::unique_lock& lock, dg4->Write(file); // Flush out data - fclose(file); + file.close(); lock.lock(); hl4->ClearData(); // Remove temp data } -void Mdf4Writer::SetDataPosition(std::FILE* file) { +void Mdf4Writer::SetDataPosition(std::streambuf& buffer) { if (CompressData()) { return; } @@ -465,8 +466,8 @@ void Mdf4Writer::SetDataPosition(std::FILE* file) { if (dt4 == nullptr) { return; } - SetLastPosition(file); - const auto data_position = GetFilePosition(file); + SetLastPosition(buffer); + const auto data_position = GetFilePosition(buffer); dt4->DataPosition(data_position); } @@ -519,7 +520,7 @@ size_t Mdf4Writer::CalculateNofDzBlocks() { nof_bytes += id_size + 4 + sample.vlsd_buffer.size(); } } - return (nof_bytes / 4'000'000) + 1; + return static_cast((nof_bytes / 4'000'000) + 1); } bool Mdf4Writer::InitMeasurement() { @@ -527,11 +528,7 @@ bool Mdf4Writer::InitMeasurement() { return MdfWriter::InitMeasurement(); } -bool Mdf4Writer::WriteSignalData(std::FILE* file) { - if (file == nullptr) { - MDF_ERROR() << "File is not opened. File: " << Name(); - return false; - } +bool Mdf4Writer::WriteSignalData(std::streambuf& buffer) { const auto *header = Header(); if (header == nullptr) { @@ -559,7 +556,7 @@ bool Mdf4Writer::WriteSignalData(std::FILE* file) { if (cn4 == nullptr) { continue; } - cn4->WriteSignalData(file, CompressData()); + cn4->WriteSignalData(buffer, CompressData()); cn4->ClearData(); } } diff --git a/mdflib/src/mdf4writer.h b/mdflib/src/mdf4writer.h index 74ca93db..61d665ae 100644 --- a/mdflib/src/mdf4writer.h +++ b/mdflib/src/mdf4writer.h @@ -22,7 +22,7 @@ class Mdf4Writer : public MdfWriter { protected: uint64_t offset_ = 0; void CreateMdfFile() override; - void SetLastPosition(std::FILE* file) override; + void SetLastPosition(std::streambuf& buffer) override; bool PrepareForWriting() override; void SaveQueue(std::unique_lock& lock) override; void CleanQueue(std::unique_lock& lock) override; @@ -34,8 +34,8 @@ class Mdf4Writer : public MdfWriter { /** \brief Save one DZ block from the sample queue. */ virtual void CleanQueueCompressed(std::unique_lock& lock, bool finalize); - void SetDataPosition(std::FILE* file) override; - bool WriteSignalData(std::FILE* file) override; + void SetDataPosition(std::streambuf& buffer) override; + bool WriteSignalData(std::streambuf& buffer) override; Dg4Block* GetLastDg4(); private: diff --git a/mdflib/src/mdfblock.cpp b/mdflib/src/mdfblock.cpp index 2c4615a6..b32ac5f4 100644 --- a/mdflib/src/mdfblock.cpp +++ b/mdflib/src/mdfblock.cpp @@ -9,8 +9,10 @@ #include #include #include +#include #include #include +#include #include "ixmlfile.h" #include "md4block.h" @@ -18,9 +20,10 @@ #include "tx3block.h" using namespace std::chrono_literals; +using namespace std::filesystem; namespace mdf::detail { - +/* int64_t GetFilePosition(std::FILE *file) { const auto pos = Platform::ftell64(file); if (pos == -1) { @@ -29,6 +32,8 @@ int64_t GetFilePosition(std::FILE *file) { return pos; } + + int64_t GetLastFilePosition(std::FILE *file) { Platform::fseek64(file, 0, SEEK_END); const auto pos = Platform::ftell64(file); @@ -129,16 +134,120 @@ std::size_t WriteStr(std::FILE *file, const std::string &source, size_t size) { } return size; } +*/ + +int64_t GetFilePosition(std::streambuf& buffer) { + const auto pos = buffer.pubseekoff(0, std::ios_base::cur); + if (pos < 0) { + throw std::ios_base::failure("Failed to get a file position"); + } + return pos; +} + +int64_t GetLastFilePosition(std::streambuf& buffer) { + const auto pos = buffer.pubseekoff(0, std::ios_base::end); + if (pos < 0) { + throw std::ios_base::failure("Failed to get last file position"); + } + return pos; +} + +void SetFilePosition(std::streambuf& buffer, int64_t position) { + const auto pos = buffer.pubseekpos( + static_cast(position)); + if (pos < 0) { + throw std::ios_base::failure("Failed to set a file position"); + } +} + +void SetFirstFilePosition(std::streambuf& buffer) { + const auto pos = buffer.pubseekoff(0, std::ios_base::beg); + if (pos < 0) { + throw std::ios_base::failure("Failed to set first file position"); + } +} +uint64_t StepFilePosition(std::streambuf& buffer, uint64_t steps) { + const auto pos = buffer.pubseekoff( + static_cast(steps), std::ios_base::cur); + if (pos < 0) { + throw std::ios_base::failure("Failed to set a file position"); + } + return steps; +} + +std::string ReadBlockType(std::streambuf& buffer) { + std::string type_mdf3; + ReadStr(buffer, type_mdf3, 2); + if (type_mdf3 == "##") { + std::string type_mdf4; + ReadStr(buffer, type_mdf4, 2); + return type_mdf4; + } + return type_mdf3; +} + +uint64_t ReadByte(std::streambuf& buffer, + std::vector &dest, + uint64_t size) { + if (size == 0) { + dest.clear(); + return 0; + } + + dest.resize(static_cast(size), 0); + const auto ret = buffer.sgetn( + reinterpret_cast(dest.data()), + static_cast(size)); + if (ret != size) { + throw std::ios_base::failure("End of stream reached (EOF)."); + } + return static_cast(ret); +} + +uint64_t WriteByte(std::streambuf& buffer, const std::vector &source) { + const auto ret = buffer.sputn( + reinterpret_cast(source.data()), + static_cast(source.size()) ); + if (ret != source.size()) { + throw std::ios_base::failure("End of stream reached (EOF)."); + } + return ret; +} + +uint64_t WriteBytes(std::streambuf& buffer, uint64_t nof_bytes) { + const std::vector empty_array(static_cast(nof_bytes), 0); + return WriteByte(buffer, empty_array); +} + +uint64_t ReadStr(std::streambuf& buffer, std::string &dest, uint64_t size) { + std::ostringstream temp; + + for (uint64_t ii = 0; ii < size; ++ii) { + const auto input = buffer.sbumpc(); + temp << static_cast(input); + } + dest = temp.str(); + MdfHelper::Trim(dest); + return size; +} + +uint64_t WriteStr(std::streambuf& buffer , const std::string &source, uint64_t size) { + for (size_t ii = 0; ii < size; ++ii) { + const char input = ii < source.size() ? source[ii] : '\0'; + buffer.sputc(input); + } + return size; +} std::string ToMd5String(const std::vector &md5) { std::ostringstream temp; for (auto byte : md5) { temp << std::hex << std::setw(2) << std::setfill('0') << std::uppercase << static_cast(byte); - }; + } return temp.str(); } - +/* bool OpenMdfFile(FILE *&file, const std::string &filename, const std::string &mode) { if (file != nullptr) { @@ -186,6 +295,41 @@ bool OpenMdfFile(FILE *&file, const std::string &filename, } return file != nullptr; } +*/ + +bool OpenMdfFile(std::streambuf& buffer, const std::string &filename, + std::ios_base::openmode mode) { + const std::filebuf* file = nullptr; + try { + auto& file_buffer = dynamic_cast(buffer); + + for (size_t delay = 0; delay < 6'000; delay += 100) { + if (file_buffer.is_open()) { + file_buffer.close(); + } + file = file_buffer.open(filename, mode); + if (file == nullptr) { + if (!exists(filename)) { + MDF_ERROR() << "The file doesn't exist. File: " << filename; + return false; + } + // Failed to open the file. Try again with a delay + std::this_thread::sleep_for( 100ms); + } + } + + } catch (const std::exception& ) { + // No error that the buffer isn't a file buffer. + // Simulate that the stream is open. + return true; + } + + if (file == nullptr) { + MDF_ERROR() << "Failed to open the file due to lock timeout (5 s). File: " + << filename; + } + return file != nullptr; +} int64_t MdfBlock::Index() const { return file_position_; @@ -202,7 +346,7 @@ int64_t MdfBlock::FilePosition() const { return file_position_; } bool MdfBlock::IsBigEndian() const { return byte_order_ != 0; } - +/* size_t MdfBlock::ReadHeader3(std::FILE *file) { file_position_ = GetFilePosition(file); size_t bytes = ReadStr(file, block_type_, 2); @@ -241,6 +385,48 @@ size_t MdfBlock::ReadHeader4(std::FILE *file) { } return bytes; } +*/ + +uint64_t MdfBlock::ReadHeader3(std::streambuf& buffer) { + file_position_ = GetFilePosition(buffer); + uint64_t bytes = ReadStr(buffer, block_type_, 2); + bytes += ReadNumber(buffer, block_size_); + block_length_ = block_size_; + return bytes; +} + +uint64_t MdfBlock::ReadLinks3(std::streambuf& buffer, size_t nof_links) { + uint64_t bytes = 0; + link_list_.clear(); + for (size_t ii = 0; ii < nof_links; ++ii) { + uint32_t link = 0; + bytes += ReadNumber(buffer, link); + link_list_.emplace_back(link); + } + link_count_ = link_list_.size(); + return bytes; +} + + +uint64_t MdfBlock::ReadHeader4(std::streambuf& buffer) { + file_position_ = GetFilePosition(buffer); + uint64_t bytes = ReadStr(buffer, block_type_, 4); + uint32_t reserved = 0; + bytes += ReadNumber(buffer, reserved); + bytes += ReadNumber(buffer, block_length_); + bytes += ReadNumber(buffer, link_count_); + + block_size_ = static_cast(block_length_); + + link_list_.clear(); + for (uint64_t ii = 0; ii < link_count_; ++ii) { + int64_t link = 0; + bytes += ReadNumber(buffer, link); + link_list_.emplace_back(link); + } + return bytes; +} + void MdfBlock::Init(const MdfBlock &id_block) { byte_order_ = id_block.byte_order_; @@ -268,7 +454,18 @@ const MdfBlock* MdfBlock::CgBlock() const { } return parent_ != nullptr ? parent_->CgBlock() : nullptr; } +uint64_t MdfBlock::ReadBool(std::streambuf& buffer, bool &dest) const { + uint16_t temp = 0; + auto bytes = ReadNumber(buffer, temp); + dest = temp != 0; + return bytes; +} +uint64_t MdfBlock::WriteBool(std::streambuf& buffer, bool value) const { + const uint16_t temp = value ? 1 : 0; + return WriteNumber(buffer, temp); +} +/* std::size_t MdfBlock::ReadBool(std::FILE *file, bool &dest) const { uint16_t temp = 0; auto bytes = ReadNumber(file, temp); @@ -280,7 +477,23 @@ std::size_t MdfBlock::WriteBool(std::FILE *file, bool value) const { const uint16_t temp = value ? 1 : 0; return WriteNumber(file, temp); } +*/ +void MdfBlock::ReadMdComment(std::streambuf& buffer, size_t index_md) { + if (!md_comment_ && Link(index_md) > 0) { + md_comment_ = std::make_unique(); + md_comment_->Init(*this); + SetFilePosition(buffer, Link(index_md)); + md_comment_->Read(buffer); + } +} +void MdfBlock::WriteMdComment(std::streambuf& buffer, size_t index_md) { + if (md_comment_ && Link(index_md) == 0) { + md_comment_->Write(buffer); + UpdateLink(buffer, index_md, md_comment_->FilePosition()); + } +} +/* void MdfBlock::ReadMdComment(std::FILE *file, size_t index_md) { if (!md_comment_ && Link(index_md) > 0) { md_comment_ = std::move(std::make_unique()); @@ -296,34 +509,34 @@ void MdfBlock::WriteMdComment(std::FILE *file, size_t index_md) { UpdateLink(file, index_md, md_comment_->FilePosition()); } } - -void MdfBlock::WriteTx4(std::FILE *file, size_t index_tx, +*/ +void MdfBlock::WriteTx4(std::streambuf& buffer, size_t index_tx, const std::string &text) { if (!text.empty() && Link(index_tx) == 0) { Tx4Block tx4(text); tx4.Init(*this); - tx4.Write(file); - UpdateLink(file, index_tx, tx4.FilePosition()); + tx4.Write(buffer); + UpdateLink(buffer, index_tx, tx4.FilePosition()); } } -std::string MdfBlock::ReadTx3(std::FILE *file, size_t index_tx) const { +std::string MdfBlock::ReadTx3(std::streambuf& buffer, size_t index_tx) const { if (Link(index_tx) > 0) { - SetFilePosition(file, Link(index_tx)); + SetFilePosition(buffer, Link(index_tx)); Tx3Block tx; tx.Init(*this); - tx.Read(file); + tx.Read(buffer); return tx.Text(); } return {}; } -std::string MdfBlock::ReadTx4(std::FILE *file, size_t index_tx) const { +std::string MdfBlock::ReadTx4(std::streambuf& buffer, size_t index_tx) const { if (Link(index_tx) > 0) { - SetFilePosition(file, Link(index_tx)); + SetFilePosition(buffer, Link(index_tx)); Tx4Block tx; tx.Init(*this); - tx.Read(file); + tx.Read(buffer); return tx.Text(); } return {}; @@ -380,6 +593,42 @@ std::string MdfBlock::MdText() const { return tx == nullptr ? std::string() : tx->Text(); } +uint64_t MdfBlock::Write(std::streambuf& buffer) { + SetLastFilePosition(buffer); + file_position_ = GetFilePosition(buffer); + + uint64_t bytes = 0; + if (IsMdf4()) { + bytes += WriteStr(buffer, block_type_, 4); + const std::vector reserved(4, 0); + bytes += WriteByte(buffer, reserved); + bytes += WriteNumber(buffer, block_length_); + uint64_t link_count = link_list_.size(); + bytes += WriteNumber(buffer, link_count); + for (auto link : link_list_) { + bytes += WriteNumber(buffer, link); + } + } else { + bytes += WriteStr(buffer, block_type_, 2); + bytes += WriteNumber(buffer, block_size_); + link_count_ = link_list_.size(); + for (auto link : link_list_) { + const auto link32 = static_cast(link); + bytes += WriteNumber(buffer, link32); + } + } + return bytes; +} + +uint64_t MdfBlock::Update(std::streambuf& buffer) const { + SetFilePosition(buffer, FilePosition()); + + return IsMdf4() ? + StepFilePosition(buffer, 24 + (link_count_ * sizeof(int64_t))) + : StepFilePosition(buffer, 4 + (link_count_ * sizeof(uint32_t))); +} + +/* size_t MdfBlock::Write(std::FILE *file) { if (file == nullptr) { throw std::runtime_error("File pointer is null"); @@ -410,7 +659,7 @@ size_t MdfBlock::Write(std::FILE *file) { return bytes; } -size_t MdfBlock::Update(std::FILE *file) { +size_t MdfBlock::Update(std::FILE *file) const { if (file == nullptr) { throw std::runtime_error("File pointer is null"); } @@ -420,7 +669,23 @@ size_t MdfBlock::Update(std::FILE *file) { StepFilePosition(file, 24 + (link_count_ * sizeof(int64_t))) : StepFilePosition(file, 4 + (link_count_ * sizeof(uint32_t))); } - +*/ +void MdfBlock::SetLastFilePosition(std::streambuf& buffer) const { + constexpr char fill = 0; + auto pos = buffer.pubseekoff(0, std::ios_base::end); + if (pos < 0) { + throw std::ios_base::failure("Failed to set last file position"); + } + if (IsMdf4()) { + // If this is an MDF4 file, fill with empty byte so the position + // has 64-bits alignments. + for (pos = GetFilePosition(buffer); (pos % 8) != 0; + pos = GetFilePosition(buffer)) { + buffer.sputc(fill); + } + } +} +/* void MdfBlock::SetLastFilePosition(std::FILE *file) const { Platform::fseek64(file, 0, SEEK_END); if (IsMdf4()) { // Well if its MDF4 file @@ -432,11 +697,62 @@ void MdfBlock::SetLastFilePosition(std::FILE *file) const { } } } - +*/ bool MdfBlock::IsMdf4() const { return !block_type_.empty() && block_type_[0] == '#'; } + +void MdfBlock::UpdateLink(std::streambuf& buffer, size_t link_index, int64_t link) { + if (link_index >= link_list_.size()) { + throw std::runtime_error("index is out of bounds"); + } + if (link == link_list_[link_index]) { + return; // No need to update the link + } + + auto pos = FilePosition(); + + // If the block not yet is written, the link will be written later + if (pos > 0) { + if (IsMdf4()) { + pos += 24 + static_cast(link_index * 8); + SetFilePosition(buffer, pos); + WriteNumber(buffer, link); + } else { + pos += 4 + static_cast(link_index * 4); + const auto link32 = static_cast(link); + SetFilePosition(buffer, pos); + WriteNumber(buffer, link32); + } + } + link_list_[link_index] = link; +} + +void MdfBlock::UpdateBlockSize(std::streambuf& buffer, uint64_t bytes) { + auto pos = FilePosition(); + if (pos <= 0) { + throw std::runtime_error("Invalid file position"); + } + + if (IsMdf4()) { + if (block_length_ != static_cast(bytes)) { + block_length_ = static_cast(bytes); + pos += 8; + SetFilePosition(buffer, pos); + WriteNumber(buffer, block_length_); + } + } else { + if (block_size_ != static_cast(bytes)) { + block_size_ = static_cast(bytes); + pos += 2; + SetFilePosition(buffer, pos); + WriteNumber(buffer, block_size_); + } + } +} + +/* void MdfBlock::UpdateBlockSize(std::FILE *file, size_t bytes) { auto pos = FilePosition(); if (pos <= 0) { @@ -491,7 +807,7 @@ void MdfBlock::UpdateLink(std::FILE *file, size_t link_index, int64_t link) { } link_list_[link_index] = link; } - +*/ void MdfBlock::CreateMd4Block() { const auto *metadata = MetaData(); if (md_comment_ && md_comment_->BlockType() == "MD") { diff --git a/mdflib/src/mdfblock.h b/mdflib/src/mdfblock.h index d2c546c9..e2eddd3b 100644 --- a/mdflib/src/mdfblock.h +++ b/mdflib/src/mdfblock.h @@ -27,7 +27,7 @@ enum class UpdateOption : int { class Md4Block; using BlockPropertyList = std::vector; - +/* int64_t GetFilePosition(std::FILE *file); int64_t GetLastFilePosition(std::FILE *file); void SetFilePosition(std::FILE *file, int64_t position); @@ -42,6 +42,20 @@ std::size_t WriteBytes(std::FILE *file, size_t nof_bytes); std::size_t ReadStr(std::FILE *file, std::string &dest, size_t size); std::size_t WriteStr(std::FILE *file, const std::string &source, size_t size); +*/ +int64_t GetFilePosition(std::streambuf& buffer); +int64_t GetLastFilePosition(std::streambuf& buffer); +void SetFilePosition(std::streambuf& buffer, int64_t position); +void SetFirstFilePosition(std::streambuf& buffer); +uint64_t StepFilePosition(std::streambuf& buffer, uint64_t steps); + +[[nodiscard]] std::string ReadBlockType(std::streambuf& buffer); +uint64_t ReadByte(std::streambuf& buffer, std::vector &dest, uint64_t size); +uint64_t WriteByte(std::streambuf& buffer, const std::vector &source); +uint64_t WriteBytes(std::streambuf& buffer, uint64_t nof_bytes); + +uint64_t ReadStr(std::streambuf& buffer, std::string &dest, uint64_t size); +uint64_t WriteStr(std::streambuf& buffer, const std::string &source, uint64_t size); template std::string ToHexString(const T &value) { @@ -73,13 +87,15 @@ std::string ToMd5String(const std::vector &md5); * Support function that opens an MDF file. This may fail if * both a writer and a reader tries to use the file at the * same time. - * @param file Reference to a file stream pointer. + * @param buffer Reference to a stream buffer. * @param filename Full path to file. - * @param mode Open mode. + * @param mode Open mode according to a file stream.. * @return True if the file was opened. */ -bool OpenMdfFile(std::FILE *&file, const std::string &filename, - const std::string &mode); +bool OpenMdfFile(std::streambuf& buffer, const std::string &filename, + std::ios_base::openmode mode); +//bool OpenMdfFile(std::FILE *&file, const std::string &filename, +// const std::string &mode); class MdfBlock { public: @@ -91,7 +107,8 @@ class MdfBlock { virtual void GetBlockProperty(BlockPropertyList &dest) const; [[nodiscard]] virtual MdfBlock *Find(int64_t index) const; - void SetLastFilePosition(std::FILE *file) const; + //void SetLastFilePosition(std::FILE *file) const; + void SetLastFilePosition(std::streambuf& buffer) const; [[nodiscard]] uint64_t BlockLength() const { return block_length_ > 0 ? block_length_ : block_size_; @@ -115,20 +132,34 @@ class MdfBlock { [[nodiscard]] const Md4Block *Md4() const; void Md4(const std::string &xml); - virtual size_t Read(std::FILE *file) = 0; - virtual size_t Write(std::FILE *file); - size_t Update(std::FILE *file); - void UpdateLink(std::FILE *file, size_t link_index, int64_t link); + //virtual size_t Read(std::FILE *file) = 0; + //virtual size_t Write(std::FILE *file); + + virtual uint64_t Read(std::streambuf& buffer) = 0; + virtual uint64_t Write(std::streambuf& buffer); + + // size_t Update(std::FILE *file) const; + uint64_t Update(std::streambuf& buffer) const; + + //void UpdateLink(std::FILE *file, size_t link_index, int64_t link); + void UpdateLink(std::streambuf& buffer, size_t link_index, int64_t link); [[nodiscard]] virtual std::string Comment() const; + // template + // std::size_t ReadNumber(std::FILE *file, T &dest) const; + + //template + //std::size_t WriteNumber(std::FILE *file, const T &source) const; + template - std::size_t ReadNumber(std::FILE *file, T &dest) const; + uint64_t ReadNumber(std::streambuf& buffer, T &dest) const; template - std::size_t WriteNumber(std::FILE *file, const T &source) const; + uint64_t WriteNumber(std::streambuf& buffer, const T &source) const; - void UpdateBlockSize(std::FILE *file, size_t bytes); + //void UpdateBlockSize(std::FILE *file, size_t bytes); + void UpdateBlockSize(std::streambuf& buffer, uint64_t bytes); [[nodiscard]] bool IsMdf4() const; @@ -136,6 +167,7 @@ class MdfBlock { [[nodiscard]] const MdfBlock* DgBlock() const; [[nodiscard]] const MdfBlock* CgBlock() const; + protected: int64_t file_position_ = 0; ///< 64-bit file position. std::string block_type_; ///< MDF header. MDF3 has 2 characters. MDF4 has 4 @@ -157,23 +189,28 @@ class MdfBlock { MdfBlock() = default; + // size_t ReadHeader3(std::FILE *file); ///< Reads a MDF3 block header. + //size_t ReadLinks3( + // std::FILE *file, + // size_t nof_links); ///< Reads MDF3 links into the link list. - size_t ReadHeader3(std::FILE *file); ///< Reads a MDF3 block header. - size_t ReadLinks3( - std::FILE *file, - size_t nof_links); ///< Reads MDF3 links into the link list. + // size_t ReadHeader4(std::FILE *file); ///< Read in MDF4 header and links. + uint64_t ReadHeader3(std::streambuf& buffer); ///< Reads a MDF3 block header. + uint64_t ReadLinks3(std::streambuf& buffer, size_t nof_links); ///< Reads MDF3 links into the link list. + uint64_t ReadHeader4(std::streambuf& buffer); ///< Read in MDF4 header and links. - size_t ReadHeader4(std::FILE *file); ///< Read in MDF4 header and links. + void ReadMdComment(std::streambuf& buffer, size_t index_md); + void WriteMdComment(std::streambuf& buffer, size_t index_md); - void ReadMdComment(std::FILE *file, size_t index_md); - void WriteMdComment(std::FILE *file, size_t index_md); + std::string ReadTx3(std::streambuf& buffer, size_t index_tx) const; + std::string ReadTx4(std::streambuf& buffer, size_t index_tx) const; + void WriteTx4(std::streambuf& buffer, size_t index_tx, const std::string &text); - std::string ReadTx3(std::FILE *file, size_t index_tx) const; - std::string ReadTx4(std::FILE *file, size_t index_tx) const; - void WriteTx4(std::FILE *file, size_t index_tx, const std::string &text); + //std::size_t ReadBool(std::FILE *file, bool &dest) const; + //std::size_t WriteBool(std::FILE *file, bool value) const; - std::size_t ReadBool(std::FILE *file, bool &dest) const; - std::size_t WriteBool(std::FILE *file, bool value) const; + uint64_t ReadBool(std::streambuf& buffer, bool &dest) const; + uint64_t WriteBool(std::streambuf& buffer, bool value) const; [[nodiscard]] std::string MdText() const; @@ -190,40 +227,52 @@ class MdfBlock { * * Helper function that reads a list of MDF4 blocks from a file. * @tparam T Block type - * @param file File stream pointer. + * @param buffer Reference to a stream buffer.. * @param block_list List of blocks. * @param link_index Link index to the first block. */ template - void ReadLink4List(std::FILE *file, + void ReadLink4List(std::streambuf& buffer, std::vector> &block_list, size_t link_index); + //template + //void ReadLink4List(std::FILE *file, + // std::vector> &block_list, + // size_t link_index); + /** \brief Writes a list of blocks to the file. * * Helper function that writes a list of MDF4 blocks onto a file. * @tparam T Block type - * @param file File stream pointer. + * @param buffer Reference to stream buffer. * @param block_list List of blocks. * @param link_index Link index to the first block. * @param update_option 0 = Do not update already written block, 1 = Update * only last block, 2 = Update all blocks */ template - void WriteLink4List(std::FILE *file, + void WriteLink4List(std::streambuf& buffer, std::vector> &block_list, size_t link_index, UpdateOption update_option); - +// template +// void WriteLink4List(std::FILE *file, +// std::vector> &block_list, +// size_t link_index, UpdateOption update_option); + +// template +// void WriteBlock4(std::FILE *file, std::unique_ptr &block, +// size_t link_index); template - void WriteBlock4(std::FILE *file, std::unique_ptr &block, + void WriteBlock4(std::streambuf& buffer, std::unique_ptr &block, size_t link_index); - private: const MdfBlock* parent_ = nullptr; ///< Set by the Init() function }; +/* template std::size_t MdfBlock::ReadNumber(std::FILE *file, T &dest) const { if (IsBigEndian()) { @@ -265,22 +314,23 @@ std::size_t MdfBlock::WriteNumber(std::FILE *file, const T &source) const { } return sizeof(T); } - -template -void MdfBlock::ReadLink4List(std::FILE *file, - std::vector> &block_list, - size_t link_index) { - if (block_list.empty() && (Link(link_index) > 0)) - for (auto link = Link(link_index); link > 0; /* No ++ here*/) { - auto block = std::make_unique(); - block->Init(*this); - SetFilePosition(file, link); - block->Read(file); - link = block->Link(0); - block_list.emplace_back(std::move(block)); - } -} - +*/ + +//template +//void MdfBlock::ReadLink4List(std::FILE *file, +// std::vector> &block_list, +// size_t link_index) { +// if (block_list.empty() && (Link(link_index) > 0)) +// for (auto link = Link(link_index); link > 0; /* No ++ here*/) { +// auto block = std::make_unique(); +// block->Init(*this); +// SetFilePosition(file, link); +// block->Read(file); +// link = block->Link(0); +// block_list.emplace_back(std::move(block)); +// } +//} +/* template void MdfBlock::WriteBlock4(std::FILE *file, std::unique_ptr &block, size_t link_index) { @@ -322,5 +372,110 @@ void MdfBlock::WriteLink4List(std::FILE *file, } } } +*/ + +template +uint64_t MdfBlock::ReadNumber(std::streambuf& buffer, T &dest) const { + if (IsBigEndian()) { + BigBuffer buff; + const auto count = buffer.sgetn( + reinterpret_cast(buff.data()), + sizeof(T)); + if (count < sizeof(T)) { + throw std::ios_base::failure("Invalid number of bytes read"); + } + + dest = buff.value(); + } else { + LittleBuffer buff; + const auto count = buffer.sgetn( + reinterpret_cast(buff.data()), + sizeof(T)); + if (count < sizeof(T)) { + throw std::ios_base::failure("Invalid number of bytes read"); + } + + dest = buff.value(); + } + return sizeof(T); +} + +template +uint64_t MdfBlock::WriteNumber(std::streambuf& buffer, const T &source) const { + if (IsBigEndian()) { + const BigBuffer buff(source); + const auto count = buffer.sputn( + reinterpret_cast(buff.data()), sizeof(T)); + if (count < sizeof(T)) { + throw std::runtime_error("Invalid number of bytes written"); + } + } else { + const LittleBuffer buff(source); + const auto count = buffer.sputn( + reinterpret_cast(buff.data()), sizeof(T)); + if (count < sizeof(T)) { + throw std::runtime_error("Invalid number of bytes written"); + } + } + return sizeof(T); +} + +template +void MdfBlock::ReadLink4List(std::streambuf& buffer, + std::vector> &block_list, + size_t link_index) { + if (block_list.empty() && (Link(link_index) > 0)) + for (int64_t link = Link(link_index); link > 0; /* No ++ here*/) { + auto block = std::make_unique(); + block->Init(*this); + SetFilePosition(buffer, link); + block->Read(buffer); + link = block->Link(0); + block_list.emplace_back(std::move(block)); + } +} + +template +void MdfBlock::WriteBlock4(std::streambuf& buffer, std::unique_ptr &block, + size_t link_index) { + if (!block || block->FilePosition() > 0) { + return; + } + block->Write(buffer); + UpdateLink(buffer, link_index, block->FilePosition()); +} + +template +void MdfBlock::WriteLink4List(std::streambuf& buffer, + std::vector> &block_list, + size_t link_index, + UpdateOption update_option) { + for (size_t index = 0; index < block_list.size(); ++index) { + auto &block = block_list[index]; + const bool last_block = index + 1 >= block_list.size(); + if (!block) { + continue; + } + bool need_update = block->FilePosition() <= 0 || + update_option == UpdateOption::DoUpdateAllBlocks; + if (block->FilePosition() > 0 && last_block && + update_option == UpdateOption::DoUpdateOnlyLastBlock) { + need_update = true; + } + + if (!need_update) { + continue; + } + block->Write(buffer); + if (index == 0) { + UpdateLink(buffer, link_index, block->FilePosition()); + } else { + auto &prev = block_list[index - 1]; + if (prev) { + prev->UpdateLink(buffer, 0, block->FilePosition()); + } + } + } +} } // namespace mdf::detail diff --git a/mdflib/src/mdfconverter.cpp b/mdflib/src/mdfconverter.cpp index 88528cb3..0634e01d 100644 --- a/mdflib/src/mdfconverter.cpp +++ b/mdflib/src/mdfconverter.cpp @@ -19,18 +19,16 @@ using namespace std::chrono_literals; namespace mdf::detail { MdfConverter::~MdfConverter() { StopWorkThread(); - if (file_ != nullptr) { - fclose(file_); - file_ = nullptr; + if (file_.is_open()) { + file_.close(); } } bool MdfConverter::InitMeasurement() { StopWorkThread(); // Just in case - if (file_ != nullptr) { - fclose(file_); - file_ = nullptr; + if (file_.is_open()) { + file_.close(); } if (!mdf_file_) { @@ -48,8 +46,10 @@ bool MdfConverter::InitMeasurement() { // 1: Save ID, HD, DG, AT, CG and CN blocks to the file. detail::OpenMdfFile(file_, filename_, - write_state_ == WriteState::Create ? "wb" : "r+b"); - if (file_ == nullptr) { + write_state_ == WriteState::Create ? + std::ios_base::out | std::ios_base::trunc | std::ios_base::binary + : std::ios_base::out | std::ios_base::in |std::ios_base::trunc | std::ios_base::binary); + if (!file_.is_open()) { MDF_ERROR() << "Failed to open the file for writing. File: " << filename_; return false; } @@ -97,7 +97,7 @@ void MdfConverter::SaveQueue(std::unique_lock& lock) { } // File should be open at this point - if (file_ == nullptr) { + if (!file_.is_open()) { lock.lock(); return; } @@ -217,7 +217,7 @@ void MdfConverter::CleanQueueCompressed(std::unique_lock& lock, } lock.unlock(); - if (file_ == nullptr) { + if (!file_.is_open()) { lock.lock(); return; } @@ -372,14 +372,14 @@ bool MdfConverter::FinalizeMeasurement() { return false; } - if (file_ == nullptr) { + if (!file_.is_open()) { MDF_ERROR() << "Failed to open the file for writing. File: " << filename_; return false; } const bool write = mdf_file_ && mdf_file_->Write(file_); const bool signal_data = WriteSignalData(file_); - fclose(file_); - file_ = nullptr; + file_.close(); + write_state_ = WriteState::Finalize; return write && signal_data; } diff --git a/mdflib/src/mdfconverter.h b/mdflib/src/mdfconverter.h index a1fa3b8c..a1a44b85 100644 --- a/mdflib/src/mdfconverter.h +++ b/mdflib/src/mdfconverter.h @@ -6,7 +6,7 @@ #pragma once #include "mdf4writer.h" - +#include namespace mdf::detail { class MdfConverter : public Mdf4Writer { @@ -28,7 +28,7 @@ class MdfConverter : public Mdf4Writer { void CleanQueueCompressed(std::unique_lock& lock, bool finalize) override; private: - std::FILE* file_ = nullptr; ///< File pointer as the file is open between calls. + std::filebuf file_; ///< File pointer as the file is open between calls. void ConverterThread(); }; diff --git a/mdflib/src/mdfreader.cpp b/mdflib/src/mdfreader.cpp index b22486b7..72b32a5f 100644 --- a/mdflib/src/mdfreader.cpp +++ b/mdflib/src/mdfreader.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "channelobserver.h" @@ -35,29 +36,29 @@ using namespace mdf::detail; namespace mdf { bool IsMdfFile(const std::string &filename) { - FILE* file = nullptr; + std::filebuf file; try { - Platform::fileopen(&file, filename.c_str(), "rb"); + file.open(filename, std::ios_base::in | std::ios_base::binary); } catch (const std::exception&) { return false; } - if (file == nullptr) { + if (!file.is_open()) { return false; } detail::IdBlock oId; bool bError = true; try { - size_t bytes = oId.Read(file); + uint64_t bytes = oId.Read(file); if (bytes == 64) { bError = false; } } catch (const std::exception &) { bError = true; } - std::fclose(file); + file.close(); if (bError) { return false; } @@ -232,7 +233,7 @@ void CreateChannelObserverForDataGroup(const IDataGroup &data_group, } } -MdfReader::MdfReader(const std::string &filename) : filename_(filename) { +MdfReader::MdfReader(std::string filename) : filename_(std::move(filename)) { // Need to create MDF3 of MDF4 file bool bExist = false; try { @@ -251,17 +252,37 @@ MdfReader::MdfReader(const std::string &filename) : filename_(filename) { // No meaning to continue if the file doesn't exist return; } - bool open = Open(); - if (!open ) { + + // Create an internal std::filebuf + auto file_buffer = std::make_shared(); + file_ = std::move(file_buffer); + + + VerifyMdfFile(); +} + +MdfReader::MdfReader(std::shared_ptr& buffer) { + file_ = buffer; + VerifyMdfFile(); +} + +void MdfReader::VerifyMdfFile() { + if (!file_) { + MDF_ERROR() << "No stream attached. Invalid use of function"; + return; + } + + const bool open = Open(); + if (!open) { MDF_ERROR() << "The file couldn't be opened for reading (locked?). Filename: " - << filename; - // No meaning to continue if the file doesn't exist + << filename_; + // No meaning to continue if the file cannot be opened return; } - std::unique_ptr id_block = - std::make_unique(); - id_block->Read(file_); + + auto id_block = std::make_unique(); + id_block->Read(*file_); if (Platform::strnicmp(id_block->FileId().c_str(), "MDF", 3) == 0 || Platform::strnicmp(id_block->FileId().c_str(), "UnFinMF", 7) == 0) { @@ -287,36 +308,70 @@ MdfReader::~MdfReader() { Close(); } std::string MdfReader::ShortName() const { try { auto filename = fs::u8path(filename_).stem().u8string(); - return std::string(filename.begin(), filename.end()); + return {filename.begin(), filename.end()}; } catch (const std::exception &) { } return {}; } -bool MdfReader::Open() { return detail::OpenMdfFile(file_, filename_, "rb"); } +bool MdfReader::Open() { + if (!file_) { + MDF_ERROR() << + "No stream buffer has been assigned. Invalid use of the function"; + return false; + } + // Note that the above function will return true if it isn't a file + // buffer. + return detail::OpenMdfFile(*file_, filename_, + std::ios_base::in | std::ios_base::binary); +} + +bool MdfReader::IsOpen() const { + std::streambuf* buffer = file_.get(); + if (buffer == nullptr) { + return false; + } + + try { + auto* file_buf = dynamic_cast(buffer); + return file_buf == nullptr ? true : file_buf->is_open(); + } catch (const std::exception& err) { + MDF_ERROR() << "Dynamic cast of pointer failed. Error: " << err.what(); + } + return true; +} void MdfReader::Close() { - if (file_ != nullptr) { - fclose(file_); - file_ = nullptr; + std::streambuf* buffer = file_.get(); + if (buffer == nullptr) { + return; + } + + try { + auto* file_buf = dynamic_cast(buffer); + if (file_buf != nullptr && file_buf->is_open()) { + file_buf->close(); + } + } catch (const std::exception& err) { + MDF_ERROR() << "Dynamic cast of pointer failed. Error: " << err.what(); } } bool MdfReader::ReadHeader() { - if (!instance_) { + if (!instance_ || !file_) { MDF_ERROR() << "No instance created. File: " << filename_; return false; } // If the file is not open, then open and close the file in this call - bool shall_close = file_ == nullptr && Open(); - if (file_ == nullptr) { + bool shall_close = !IsOpen() && Open(); + if (!IsOpen()) { MDF_ERROR() << "File is not open. File: " << filename_; return false; } bool no_error = true; try { - instance_->ReadHeader(file_); + instance_->ReadHeader(*file_); } catch (const std::exception &error) { MDF_ERROR() << "Initialization failed. Error: " << error.what(); no_error = false; @@ -328,18 +383,18 @@ bool MdfReader::ReadHeader() { } bool MdfReader::ReadMeasurementInfo() { - if (!instance_) { + if (!instance_ || !file_) { MDF_ERROR() << "No instance created. File: " << filename_; return false; } - bool shall_close = file_ == nullptr && Open(); - if (file_ == nullptr) { + bool shall_close = !IsOpen() && Open(); + if (!IsOpen()) { MDF_ERROR() << "File is not open. File: " << filename_; return false; } bool no_error = true; try { - instance_->ReadMeasurementInfo(file_); + instance_->ReadMeasurementInfo(*file_); } catch (const std::exception &error) { MDF_ERROR() << "Failed to read the DG/CG blocks. Error: " << error.what(); @@ -352,18 +407,18 @@ bool MdfReader::ReadMeasurementInfo() { } bool MdfReader::ReadEverythingButData() { - if (!instance_) { + if (!instance_ || !file_) { MDF_ERROR() << "No instance created. File: " << filename_; return false; } - bool shall_close = file_ == nullptr && Open(); - if (file_ == nullptr) { + bool shall_close = !IsOpen() && Open(); + if (!IsOpen()) { MDF_ERROR() << "File is not open. File: " << filename_; return false; } bool no_error = true; try { - instance_->ReadEverythingButData(file_); + instance_->ReadEverythingButData(*file_); } catch (const std::exception &error) { MDF_ERROR() << "Failed to read the file information blocks. Error: " @@ -378,13 +433,13 @@ bool MdfReader::ReadEverythingButData() { bool MdfReader::ExportAttachmentData(const IAttachment &attachment, const std::string &dest_file) { - if (!instance_) { + if (!instance_ || !file_) { MDF_ERROR() << "No instance created. File: " << filename_; return false; } - bool shall_close = file_ == nullptr && Open(); - if (file_ == nullptr) { + bool shall_close = !IsOpen() && Open(); + if (!IsOpen()) { MDF_ERROR() << "Failed to open file. File: " << filename_; return false; } @@ -392,7 +447,7 @@ bool MdfReader::ExportAttachmentData(const IAttachment &attachment, bool no_error = true; try { auto &at4 = dynamic_cast(attachment); - at4.ReadData(file_, dest_file); + at4.ReadData(*file_, dest_file); } catch (const std::exception &error) { MDF_ERROR() << "Failed to read the file information blocks. Error: " << error.what(); @@ -406,13 +461,13 @@ bool MdfReader::ExportAttachmentData(const IAttachment &attachment, } bool MdfReader::ReadData(IDataGroup &data_group) { - if (!instance_) { + if (!instance_ || !file_) { MDF_ERROR() << "No instance created. File: " << filename_; return false; } - bool shall_close = file_ == nullptr && Open(); - if (file_ == nullptr) { + bool shall_close = !IsOpen() && Open(); + if (!IsOpen()) { MDF_ERROR() << "Failed to open file. File: " << filename_; return false; } @@ -421,10 +476,10 @@ bool MdfReader::ReadData(IDataGroup &data_group) { try { if (instance_->IsMdf4()) { auto &dg4 = dynamic_cast(data_group); - dg4.ReadData(file_); + dg4.ReadData(*file_); } else { auto &dg3 = dynamic_cast(data_group); - dg3.ReadData(file_); + dg3.ReadData(*file_); } } catch (const std::exception &err) { MDF_ERROR() << "Failed to read the file information blocks. Error: " @@ -440,15 +495,15 @@ bool MdfReader::ReadData(IDataGroup &data_group) { bool MdfReader::ReadPartialData(IDataGroup &data_group, size_t min_sample, size_t max_sample) { - if (!instance_) { + if (!instance_ || !file_) { MDF_ERROR() << "No instance created. File: " << filename_; return false; } if (max_sample < min_sample) { max_sample = min_sample; } - bool shall_close = file_ == nullptr && Open(); - if (file_ == nullptr) { + bool shall_close = !IsOpen() && Open(); + if (!IsOpen()) { MDF_ERROR() << "Failed to open file. File: " << filename_; return false; } @@ -459,11 +514,11 @@ bool MdfReader::ReadPartialData(IDataGroup &data_group, size_t min_sample, auto &dg4 = dynamic_cast(data_group); DgRange range(dg4, min_sample, max_sample); - dg4.ReadRangeData(file_, range); + dg4.ReadRangeData(*file_, range); } else { auto &dg3 = dynamic_cast(data_group); DgRange range(dg3, min_sample, max_sample); - dg3.ReadRangeData(file_, range); + dg3.ReadRangeData(*file_, range); } } catch (const std::exception &err) { MDF_ERROR() << "Failed to read the file information blocks. Error: " @@ -478,13 +533,13 @@ bool MdfReader::ReadPartialData(IDataGroup &data_group, size_t min_sample, } bool MdfReader::ReadSrData(ISampleReduction &sr_group) { - if (!instance_) { + if (!instance_ || !file_) { MDF_ERROR() << "No instance created. File: " << filename_; return false; } - bool shall_close = file_ == nullptr && Open(); - if (file_ == nullptr) { + bool shall_close = !IsOpen() && Open(); + if (!IsOpen()) { MDF_ERROR() << "Failed to open file. File: " << filename_; return false; } @@ -493,10 +548,10 @@ bool MdfReader::ReadSrData(ISampleReduction &sr_group) { try { if (instance_->IsMdf4()) { auto &sr4 = dynamic_cast(sr_group); - sr4.ReadData(file_); + sr4.ReadData(*file_); } else { auto &sr3 = dynamic_cast(sr_group); - sr3.ReadData(file_); + sr3.ReadData(*file_); } } catch (const std::exception &err) { MDF_ERROR() << "Failed to read the file information blocks. Error: " @@ -542,13 +597,13 @@ bool MdfReader::ReadVlsdData(IDataGroup &data_group, return false; } - if (!instance_) { + if (!instance_ || !file_ ) { MDF_ERROR() << "No instance created. File: " << filename_; return false; } - bool shall_close = file_ == nullptr && Open(); - if (file_ == nullptr) { + bool shall_close = !IsOpen() && Open(); + if (!IsOpen()) { MDF_ERROR() << "Failed to open file. File: " << filename_; return false; } @@ -558,7 +613,7 @@ bool MdfReader::ReadVlsdData(IDataGroup &data_group, if (instance_->IsMdf4()) { auto &dg4 = dynamic_cast(data_group); auto &cn4 = dynamic_cast(vlsd_channel); - dg4.ReadVlsdData(file_, cn4,offset_list, callback); + dg4.ReadVlsdData(*file_, cn4,offset_list, callback); } else { MDF_ERROR() << "Function not support for version MDF version 3."; error = true; diff --git a/mdflib/src/mdfwriter.cpp b/mdflib/src/mdfwriter.cpp index 79a45a6e..3e9ed8dc 100644 --- a/mdflib/src/mdfwriter.cpp +++ b/mdflib/src/mdfwriter.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "dg3block.h" #include "mdfblock.h" @@ -115,15 +116,15 @@ bool MdfWriter::Init(const std::string& filename) { if (mdf_file_) { mdf_file_->FileName(filename); } - std::FILE* file = nullptr; + std::filebuf file; try { if (fs::exists(filename_)) { // Read in existing file so we can append to it - detail::OpenMdfFile(file, filename_, "rb"); - if (file != nullptr) { + detail::OpenMdfFile(file, filename_, std::ios_base::in | std::ios_base::binary); + if (!file.is_open()) { mdf_file_->ReadEverythingButData(file); - std::fclose(file); + file.close(); write_state_ = WriteState::Finalize; // Append to the file MDF_DEBUG() << "Reading existing file. File: " << filename_; init = true; @@ -139,8 +140,8 @@ bool MdfWriter::Init(const std::string& filename) { init = true; } } catch (const std::exception& err) { - if (file != nullptr) { - fclose(file); + if (file.is_open()) { + file.close(); write_state_ = WriteState::Finalize; MDF_ERROR() << "Failed to read the existing MDF file. Error: " << err.what() << ", File: " << filename_; @@ -168,17 +169,19 @@ bool MdfWriter::InitMeasurement() { return false; } // 1: Save ID, HD, DG, AT, CG and CN blocks to the file. - std::FILE* file = nullptr; + std::filebuf file; detail::OpenMdfFile(file, filename_, - write_state_ == WriteState::Create ? "wb" : "r+b"); - if (file == nullptr) { + write_state_ == WriteState::Create ? + std::ios_base::out | std::ios_base::binary | std::ios_base::trunc: + std::ios_base::in | std::ios_base::out | std::ios_base::binary); + if (!file.is_open()) { MDF_ERROR() << "Failed to open the file for writing. File: " << filename_; return false; } const bool write = mdf_file_->Write(file); SetDataPosition(file); // Set up data position to end of file - fclose(file); + file.close(); start_time_ = 0; // Zero indicate not started stop_time_ = 0; // Zero indicate not stopped // Start the working thread that handles the samples @@ -365,15 +368,16 @@ bool MdfWriter::FinalizeMeasurement() { return false; } - std::FILE* file = nullptr; - detail::OpenMdfFile(file, filename_, "r+b"); - if (file == nullptr) { + std::filebuf file; + detail::OpenMdfFile(file, filename_, + std::ios_base::in | std::ios_base::out | std::ios_base::binary); + if (!file.is_open()) { MDF_ERROR() << "Failed to open the file for writing. File: " << filename_; return false; } const bool write = mdf_file_ && mdf_file_->Write(file); const bool signal_data = WriteSignalData(file); - fclose(file); + file.close(); write_state_ = WriteState::Finalize; return write && signal_data; } @@ -457,9 +461,10 @@ void MdfWriter::SaveQueue(std::unique_lock& lock) { } lock.unlock(); - std::FILE* file = nullptr; - Platform::fileopen(&file, filename_.c_str(), "r+b"); - if (file == nullptr) { + std::filebuf file; + file.open(filename_, + std::ios_base::in | std::ios_base::out | std::ios_base::binary); + if (!file.is_open()) { lock.lock(); return; } @@ -483,12 +488,13 @@ void MdfWriter::SaveQueue(std::unique_lock& lock) { if (dg3->NofRecordId() > 0) { const auto id = static_cast(sample.record_id); - fwrite(&id, 1, 1, file); + file.sputc(static_cast(id)); } - fwrite(sample.record_buffer.data(), 1, sample.record_buffer.size(), file); + file.sputn(reinterpret_cast(sample.record_buffer.data()), + static_cast(sample.record_buffer.size()) ); if (dg3->NofRecordId() > 1) { const auto id = static_cast(sample.record_id); - fwrite(&id, 1, 1, file); + file.sputc(static_cast(id)); } IncrementNofSamples(sample.record_id); lock.lock(); @@ -502,7 +508,7 @@ void MdfWriter::SaveQueue(std::unique_lock& lock) { } } - fclose(file); + file.close(); lock.lock(); } @@ -532,10 +538,10 @@ IChannel* MdfWriter::CreateChannel(IChannelGroup* parent) { return parent == nullptr ? nullptr : parent->CreateChannel(); } -void MdfWriter::SetDataPosition(std::FILE*) { +void MdfWriter::SetDataPosition(std::streambuf&) { // Only needed for MDF4 and uncompressed storage } -bool MdfWriter::WriteSignalData(std::FILE* file) { +bool MdfWriter::WriteSignalData(std::streambuf&) { // Only supported by MDF4 return true; } diff --git a/mdflib/src/pr3block.cpp b/mdflib/src/pr3block.cpp index 9b08f5ce..ce1520a8 100644 --- a/mdflib/src/pr3block.cpp +++ b/mdflib/src/pr3block.cpp @@ -7,41 +7,24 @@ #include #include +#include namespace mdf::detail { -Pr3Block::Pr3Block(const std::string &meta_data) : text_(meta_data) {} - -size_t Pr3Block::Read(std::FILE *file) { - size_t bytes = ReadHeader3(file); - - std::ostringstream temp; - char in = '\0'; - for (; bytes < block_size_; ++bytes) { - size_t nof = std::fread(&in, 1, 1, file); - if (nof != 1) { - // Suppose end of file or something - break; - } - if (in == '\0') { - // No more to read - break; - } - temp << in; - } - text_ = temp.str(); +Pr3Block::Pr3Block(std::string meta_data) : text_(std::move(meta_data)) {} +uint64_t Pr3Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader3(buffer); + bytes += ReadStr(buffer, text_, block_size_ - bytes); return bytes; } -size_t Pr3Block::Write(std::FILE *file) { +uint64_t Pr3Block::Write(std::streambuf& buffer) { block_type_ = "PR"; block_size_ = static_cast((2 + 2) + text_.size()); link_list_.clear(); - auto bytes = MdfBlock::Write(file); - if (!text_.empty()) { - bytes += std::fwrite(text_.data(), 1, text_.size(), file); - } + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteStr(buffer, text_, text_.size()); return bytes; } diff --git a/mdflib/src/pr3block.h b/mdflib/src/pr3block.h index 1c8489e8..e64ce01f 100644 --- a/mdflib/src/pr3block.h +++ b/mdflib/src/pr3block.h @@ -12,10 +12,11 @@ namespace mdf::detail { class Pr3Block : public MdfBlock { public: Pr3Block() = default; - explicit Pr3Block(const std::string &meta_data); + explicit Pr3Block(std::string meta_data); + + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; [[nodiscard]] std::string Text() const { return text_; } private: diff --git a/mdflib/src/rd4block.cpp b/mdflib/src/rd4block.cpp index 01463952..d029fefc 100644 --- a/mdflib/src/rd4block.cpp +++ b/mdflib/src/rd4block.cpp @@ -6,13 +6,13 @@ namespace mdf::detail { -size_t Rd4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - data_position_ = GetFilePosition(file); +uint64_t Rd4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + data_position_ = GetFilePosition(buffer); return bytes; } -size_t Rd4Block::DataSize() const { +uint64_t Rd4Block::DataSize() const { return block_length_ > 24 ? block_length_ - 24 : 0; } diff --git a/mdflib/src/rd4block.h b/mdflib/src/rd4block.h index c8496e8e..bf7527cf 100644 --- a/mdflib/src/rd4block.h +++ b/mdflib/src/rd4block.h @@ -9,10 +9,10 @@ namespace mdf::detail { class Rd4Block : public DataBlock { public: - size_t Read(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; protected: - [[nodiscard]] size_t DataSize() const override; + [[nodiscard]] uint64_t DataSize() const override; }; } // namespace mdf::detail diff --git a/mdflib/src/readcache.cpp b/mdflib/src/readcache.cpp index 2a1b0ae6..7a47fe44 100644 --- a/mdflib/src/readcache.cpp +++ b/mdflib/src/readcache.cpp @@ -10,8 +10,8 @@ namespace mdf::detail { -ReadCache::ReadCache( MdfBlock* block, FILE* file) -: file_(file) +ReadCache::ReadCache( MdfBlock* block, std::streambuf& buffer) +: buffer_(buffer) { data_list_ = dynamic_cast(block); data_block_ = dynamic_cast(block); @@ -305,16 +305,10 @@ bool ReadCache::ParseVlsdCgData() { } bool ReadCache::GetNextByte(uint8_t &input) { - if (file_ == nullptr) { - return false; - } if ( file_index_ < data_size_) { if (file_buffer_.empty()) { // Read direct from the file - const auto nof_bytes = fread(&input,1,1,file_); - if (nof_bytes != 1) { - return false; - } + input = buffer_.sbumpc(); } else { // Read from buffer in case of DZ block input = file_buffer_[file_index_]; @@ -338,15 +332,16 @@ bool ReadCache::GetNextByte(uint8_t &input) { if (current_block->BlockType() == "DZ") { // Need a temp buffer in between try { - file_buffer_.resize(data_size_); + file_buffer_.resize(static_cast(data_size_) ); } catch (const std::exception&) { return false; } - size_t temp_index = 0; - current_block->CopyDataToBuffer(file_,file_buffer_, temp_index); + + uint64_t temp_index = 0; + current_block->CopyDataToBuffer(buffer_,file_buffer_, temp_index); } else { // Read from the file directly - SetFilePosition(file_, current_block->DataPosition()); + SetFilePosition(buffer_, current_block->DataPosition()); file_buffer_.clear(); // Indicate that we read from the file directly } // Read in the data form file to @@ -354,10 +349,7 @@ bool ReadCache::GetNextByte(uint8_t &input) { return false; } if (file_buffer_.empty()) { - const auto reads = fread(&input, 1, 1, file_); - if (reads != 1) { - return false; - } + input = buffer_.sbumpc(); } else { input = file_buffer_[file_index_]; } @@ -418,7 +410,9 @@ void ReadCache::GetArray(std::vector &buffer) { const auto nof_bytes = buffer.size(); if (file_index_ + nof_bytes <= data_size_) { if (file_buffer_.empty()) { - const auto bytes = fread(buffer.data(), 1, nof_bytes, file_); + const auto bytes = buffer_.sgetn( + reinterpret_cast(buffer.data()), + static_cast(nof_bytes)); if (bytes != nof_bytes) { throw std::runtime_error("End of file detected."); } @@ -440,7 +434,7 @@ void ReadCache::GetArray(std::vector &buffer) { void ReadCache::SkipBytes(size_t nof_skip) { if (file_index_ + nof_skip <= data_size_) { if (file_buffer_.empty()) { - const auto bytes = StepFilePosition(file_, nof_skip); + const auto bytes = StepFilePosition(buffer_, nof_skip); if (bytes != nof_skip) { throw std::runtime_error("End of file detected."); } @@ -457,12 +451,9 @@ void ReadCache::SkipBytes(size_t nof_skip) { } bool ReadCache::SkipByte() { - if (file_ == nullptr) { - return false; - } if ( file_index_ < data_size_) { if (file_buffer_.empty()) { - const auto nof_bytes = StepFilePosition(file_, 1); + const auto nof_bytes = StepFilePosition(buffer_, 1); if (nof_bytes != 1) { return false; } @@ -485,20 +476,20 @@ bool ReadCache::SkipByte() { data_size_ = current_block->DataSize(); if (current_block->BlockType() == "DZ") { try { - file_buffer_.resize(data_size_); + file_buffer_.resize(static_cast(data_size_) ); } catch (const std::exception&) { return false; } } else { file_buffer_.clear(); - SetFilePosition(file_, current_block->DataPosition()); + SetFilePosition(buffer_, current_block->DataPosition()); } if (file_index_ >= data_size_) { return false; } if (file_buffer_.empty()) { - const auto reads = StepFilePosition(file_, 1); + const auto reads = StepFilePosition(buffer_, 1); if (reads != 1) { return false; } diff --git a/mdflib/src/readcache.h b/mdflib/src/readcache.h index 35be996e..6aa17139 100644 --- a/mdflib/src/readcache.h +++ b/mdflib/src/readcache.h @@ -18,7 +18,7 @@ namespace mdf::detail { class ReadCache { public: ReadCache() = delete; - ReadCache( MdfBlock* block, FILE* file); + ReadCache( MdfBlock* block, std::streambuf& buffer); bool ParseRecord(); bool ParseRangeRecord(DgRange& range); @@ -35,14 +35,14 @@ class ReadCache { void SetCallback(const std::function&)>& callback ); private: - FILE* file_; + std::streambuf& buffer_; DataListBlock* data_list_ = nullptr; ///< List of data_block example a DL block DataBlock* data_block_ = nullptr; ///< A single data block Dg4Block* dg4_block_ = nullptr; size_t file_index_ = 0; std::vector file_buffer_; // Needs a file buffer to handle the DZ block. - size_t data_size_ = 0; + uint64_t data_size_ = 0; uint64_t data_count_ = 0; uint64_t max_data_count_ = 0; diff --git a/mdflib/src/ri4block.cpp b/mdflib/src/ri4block.cpp index 1561cc97..fd88fc84 100644 --- a/mdflib/src/ri4block.cpp +++ b/mdflib/src/ri4block.cpp @@ -6,13 +6,13 @@ #include "ri4block.h" namespace mdf::detail { -size_t Ri4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - data_position_ = GetFilePosition(file); +uint64_t Ri4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + data_position_ = GetFilePosition(buffer); return bytes; } -size_t Ri4Block::DataSize() const { +uint64_t Ri4Block::DataSize() const { return block_length_ > 24 ? block_length_ - 24 : 0; } diff --git a/mdflib/src/ri4block.h b/mdflib/src/ri4block.h index 06b98412..6afc9a82 100644 --- a/mdflib/src/ri4block.h +++ b/mdflib/src/ri4block.h @@ -10,10 +10,10 @@ namespace mdf::detail { class Ri4Block : public DataBlock { public: - size_t Read(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; protected: - [[nodiscard]] size_t DataSize() const override; + [[nodiscard]] uint64_t DataSize() const override; }; } // namespace mdf::detail diff --git a/mdflib/src/rv4block.cpp b/mdflib/src/rv4block.cpp index f295f7af..9291ca48 100644 --- a/mdflib/src/rv4block.cpp +++ b/mdflib/src/rv4block.cpp @@ -7,12 +7,13 @@ namespace mdf::detail { -size_t Rv4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - data_position_ = GetFilePosition(file); +uint64_t Rv4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + data_position_ = GetFilePosition(buffer); return bytes; } -size_t Rv4Block::DataSize() const { + +uint64_t Rv4Block::DataSize() const { return block_length_ > 24 ? block_length_ - 24 : 0; } diff --git a/mdflib/src/rv4block.h b/mdflib/src/rv4block.h index 745da912..70e18612 100644 --- a/mdflib/src/rv4block.h +++ b/mdflib/src/rv4block.h @@ -10,10 +10,10 @@ namespace mdf::detail { class Rv4Block : public DataBlock { public: - size_t Read(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; protected: - [[nodiscard]] size_t DataSize() const override; + [[nodiscard]] uint64_t DataSize() const override; private: }; diff --git a/mdflib/src/sd4block.cpp b/mdflib/src/sd4block.cpp index 24e0ff3d..cec8148a 100644 --- a/mdflib/src/sd4block.cpp +++ b/mdflib/src/sd4block.cpp @@ -6,17 +6,17 @@ #include "littlebuffer.h" namespace mdf::detail { -size_t Sd4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - data_position_ = GetFilePosition(file); +uint64_t Sd4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + data_position_ = GetFilePosition(buffer); return bytes; } -size_t Sd4Block::DataSize() const { +uint64_t Sd4Block::DataSize() const { return block_length_ > 24 ? block_length_ - 24 : 0; } -size_t Sd4Block::Write(std::FILE *file) { +uint64_t Sd4Block::Write(std::streambuf& buffer) { const auto update = FilePosition() > 0; if (update) { return block_length_; @@ -25,8 +25,8 @@ size_t Sd4Block::Write(std::FILE *file) { link_list_.clear(); block_length_ = 24 + data_.size(); - auto bytes = MdfBlock::Write(file); - bytes += WriteByte(file, data_); + auto bytes = MdfBlock::Write(buffer); + bytes += WriteByte(buffer, data_); return bytes; } diff --git a/mdflib/src/sd4block.h b/mdflib/src/sd4block.h index 0d1f95f9..c5385d2f 100644 --- a/mdflib/src/sd4block.h +++ b/mdflib/src/sd4block.h @@ -11,13 +11,13 @@ namespace mdf::detail { class Sd4Block : public DataBlock { public: - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; uint64_t AppendData(const std::string& text); uint64_t AppendData(const std::vector& data); protected: - [[nodiscard]] size_t DataSize() const override; + [[nodiscard]] uint64_t DataSize() const override; private: uint64_t AppendData(const VlsdData& data); std::map sorted_data_; diff --git a/mdflib/src/si4block.cpp b/mdflib/src/si4block.cpp index 460eca41..88705770 100644 --- a/mdflib/src/si4block.cpp +++ b/mdflib/src/si4block.cpp @@ -92,20 +92,21 @@ void Si4Block::GetBlockProperty(BlockPropertyList &dest) const { md_comment_->GetBlockProperty(dest); } } -size_t Si4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - bytes += ReadNumber(file, type_); - bytes += ReadNumber(file, bus_type_); - bytes += ReadNumber(file, flags_); + +uint64_t Si4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadNumber(buffer, type_); + bytes += ReadNumber(buffer, bus_type_); + bytes += ReadNumber(buffer, flags_); std::vector reserved; - bytes += ReadByte(file, reserved, 5); - name_ = ReadTx4(file, kIndexName); - path_ = ReadTx4(file, kIndexPath); - ReadMdComment(file, kIndexMd); + bytes += ReadByte(buffer, reserved, 5); + name_ = ReadTx4(buffer, kIndexName); + path_ = ReadTx4(buffer, kIndexPath); + ReadMdComment(buffer, kIndexMd); return bytes; } -size_t Si4Block::Write(std::FILE *file) { +uint64_t Si4Block::Write(std::streambuf& buffer) { const bool update = FilePosition() > 0; // True if already written to file if (update) { return block_length_; @@ -114,16 +115,16 @@ size_t Si4Block::Write(std::FILE *file) { block_type_ = "##SI"; block_length_ = 24 + (3 * 8) + 1 + 1 + 1 + 5; link_list_.resize(3, 0); - WriteTx4(file, kIndexName, name_); - WriteTx4(file, kIndexPath, path_); - WriteMdComment(file, kIndexMd); - - auto bytes = MdfBlock::Write(file); - bytes += WriteNumber(file, type_); - bytes += WriteNumber(file, bus_type_); - bytes += WriteNumber(file, flags_); - bytes += WriteBytes(file, 5); - UpdateBlockSize(file, bytes); + WriteTx4(buffer, kIndexName, name_); + WriteTx4(buffer, kIndexPath, path_); + WriteMdComment(buffer, kIndexMd); + + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteNumber(buffer, type_); + bytes += WriteNumber(buffer, bus_type_); + bytes += WriteNumber(buffer, flags_); + bytes += WriteBytes(buffer, 5); + UpdateBlockSize(buffer, bytes); return bytes; } diff --git a/mdflib/src/si4block.h b/mdflib/src/si4block.h index 11a8074e..1163cf7c 100644 --- a/mdflib/src/si4block.h +++ b/mdflib/src/si4block.h @@ -37,8 +37,8 @@ class Si4Block : public MdfBlock, public ISourceInformation { [[nodiscard]] IMetaData *MetaData() const override; void GetBlockProperty(BlockPropertyList &dest) const override; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; private: uint8_t type_ = 0; diff --git a/mdflib/src/sr3block.cpp b/mdflib/src/sr3block.cpp index 3116e8d2..a63c64a4 100644 --- a/mdflib/src/sr3block.cpp +++ b/mdflib/src/sr3block.cpp @@ -38,15 +38,15 @@ const IChannelGroup *Sr3Block::ChannelGroup() const { return mdf_block != nullptr ? dynamic_cast(mdf_block) : nullptr; } -size_t Sr3Block::Read(std::FILE *file) { - size_t bytes = ReadHeader3(file); - bytes += ReadLinks3(file, 2); - bytes += ReadNumber(file, nof_reduced_samples_); - bytes += ReadNumber(file, time_interval_); +uint64_t Sr3Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader3(buffer); + bytes += ReadLinks3(buffer, 2); + bytes += ReadNumber(buffer, nof_reduced_samples_); + bytes += ReadNumber(buffer, time_interval_); return bytes; } -size_t Sr3Block::Write(std::FILE *file) { +uint64_t Sr3Block::Write(std::streambuf& buffer) { // SR block must be written with its data once with no updates const bool update = FilePosition() > 0; if (update) { @@ -55,9 +55,9 @@ size_t Sr3Block::Write(std::FILE *file) { block_type_ = "SR"; block_size_ = (2 + 2) + (2 * 4) + 4 + 8; link_list_.resize(2, 0); - size_t bytes = MdfBlock::Write(file); - bytes += WriteNumber(file, nof_reduced_samples_); - bytes += WriteNumber(file, time_interval_); + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteNumber(buffer, nof_reduced_samples_); + bytes += WriteNumber(buffer, time_interval_); for (size_t index = 0; index < block_list_.size(); ++index) { auto &data = block_list_[index]; @@ -67,9 +67,9 @@ size_t Sr3Block::Write(std::FILE *file) { if (data->FilePosition() > 0) { continue; } - data->Write(file); + data->Write(buffer); if (index == 0) { - UpdateLink(file, kIndexData, data->FilePosition()); + UpdateLink(buffer, kIndexData, data->FilePosition()); } } @@ -77,25 +77,21 @@ size_t Sr3Block::Write(std::FILE *file) { } -void Sr3Block::ReadData(std::FILE *file) const { - if (file == nullptr) { - throw std::invalid_argument("File pointer is null"); - } - - size_t data_size = DataSize(); +void Sr3Block::ReadData(std::streambuf& buffer) const { + uint64_t data_size = DataSize(); if (data_size == 0) { data_list_.clear(); return; } try { - data_list_.resize(data_size, 0); + data_list_.resize(static_cast(data_size), 0); } catch (const std::exception&) { data_list_.clear(); return; } - SetFilePosition(file, Link(kIndexData)); - ReadByte(file,data_list_, data_size); + SetFilePosition(buffer, Link(kIndexData)); + ReadByte(buffer,data_list_, data_size); } void Sr3Block::ClearData() { diff --git a/mdflib/src/sr3block.h b/mdflib/src/sr3block.h index b9d07944..415f767d 100644 --- a/mdflib/src/sr3block.h +++ b/mdflib/src/sr3block.h @@ -24,10 +24,10 @@ class Sr3Block : public DataListBlock , public ISampleReduction { [[nodiscard]] const IChannelGroup* ChannelGroup() const override; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; - void ReadData(std::FILE *file) const; + void ReadData(std::streambuf& buffer) const; void ClearData() override; void GetChannelValueUint( const IChannel& channel, uint64_t sample, diff --git a/mdflib/src/sr4block.cpp b/mdflib/src/sr4block.cpp index 00b0df54..d8083275 100644 --- a/mdflib/src/sr4block.cpp +++ b/mdflib/src/sr4block.cpp @@ -107,43 +107,42 @@ void Sr4Block::GetBlockProperty(BlockPropertyList &dest) const { dest.emplace_back("Flags", MakeFlagString(flags_)); } -size_t Sr4Block::Read(std::FILE *file) { - size_t bytes = ReadHeader4(file); - bytes += ReadNumber(file, nof_samples_); - bytes += ReadNumber(file, interval_); - bytes += ReadNumber(file, type_); - bytes += ReadNumber(file, flags_); +uint64_t Sr4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadNumber(buffer, nof_samples_); + bytes += ReadNumber(buffer, interval_); + bytes += ReadNumber(buffer, type_); + bytes += ReadNumber(buffer, flags_); std::vector reserved; - bytes += ReadByte(file, reserved, 6); - ReadBlockList(file, kIndexData); + bytes += ReadByte(buffer, reserved, 6); + ReadBlockList(buffer, kIndexData); return bytes; } -void Sr4Block::ReadData(std::FILE *file) const { - const size_t count = DataSize(); +void Sr4Block::ReadData(std::streambuf& buffer) const { + const uint64_t count = DataSize(); if (block_list_.empty() || count == 0) { data_list_.clear(); return; } try { - data_list_.resize(count, 0); + data_list_.resize(static_cast(count), 0); } catch (const std::exception& ) { // No room in memory for the block. data_list_.clear(); return; } - size_t index = 0; - - // The block list should only contain one block. - // A SD block is uncompressed data block + // The block list should only contain one block. + // A SD block is uncompressed data block + uint64_t index = 0; for (const auto &block : block_list_) { const auto *list = dynamic_cast(block.get()); const auto *data = dynamic_cast(block.get()); if (list != nullptr) { - list->CopyDataToBuffer( file, data_list_, index); + list->CopyDataToBuffer( buffer, data_list_, index); } else if (block != nullptr) { - data->CopyDataToBuffer(file, data_list_, index); + data->CopyDataToBuffer(buffer, data_list_, index); } } } diff --git a/mdflib/src/sr4block.h b/mdflib/src/sr4block.h index acbbdc12..bacd2314 100644 --- a/mdflib/src/sr4block.h +++ b/mdflib/src/sr4block.h @@ -30,9 +30,9 @@ class Sr4Block : public DataListBlock, public ISampleReduction { [[nodiscard]] const IChannelGroup* ChannelGroup() const override; void GetBlockProperty(BlockPropertyList& dest) const override; - size_t Read(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; - void ReadData(std::FILE* file) const; ///< Reads in SR/Rx data + void ReadData(std::streambuf& buffer) const; ///< Reads in SR/Rx data void ClearData() override; protected: @@ -87,7 +87,7 @@ void Sr4Block::GetChannelValueT(const IChannel &channel, // Set up a temporary record buffer. It will be used as temporary // buffer. It solves the RD vs RV/RI blocks data storage. - std::vector record_buffer(block_size, 0); + std::vector record_buffer(static_cast(block_size), 0); // Check if the data_list_ buffer is format as an RD block // or as RV/RI blocks. The main idea is to copy to the diff --git a/mdflib/src/tr3block.cpp b/mdflib/src/tr3block.cpp index 667bf105..ebeeb76f 100644 --- a/mdflib/src/tr3block.cpp +++ b/mdflib/src/tr3block.cpp @@ -11,26 +11,27 @@ constexpr size_t kIndexTx = 0; namespace mdf::detail { std::string Tr3Block::Comment() const { return comment_; } -size_t Tr3Block::Read(std::FILE *file) { - size_t bytes = ReadHeader3(file); - bytes += ReadLinks3(file, 1); - bytes += ReadNumber(file, nof_events_); + +uint64_t Tr3Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader3(buffer); + bytes += ReadLinks3(buffer, 1); + bytes += ReadNumber(buffer, nof_events_); for (int event = 0; event < nof_events_; ++event) { if (bytes + 8 > block_size_) { break; } Tr3Event ev; - bytes += ReadNumber(file, ev.event_time); - bytes += ReadNumber(file, ev.pre_time); - bytes += ReadNumber(file, ev.post_time); + bytes += ReadNumber(buffer, ev.event_time); + bytes += ReadNumber(buffer, ev.pre_time); + bytes += ReadNumber(buffer, ev.post_time); event_list_.emplace_back(ev); } - comment_ = ReadTx3(file, kIndexTx); + comment_ = ReadTx3(buffer, kIndexTx); return bytes; } -size_t Tr3Block::Write(std::FILE *file) { +uint64_t Tr3Block::Write(std::streambuf& buffer) { // The TR block is normally added after the measurement has been stopped as it // cannot be appended if (FilePosition() > 0) { @@ -45,17 +46,17 @@ size_t Tr3Block::Write(std::FILE *file) { if (!comment_.empty()) { Tx3Block tx(comment_); tx.Init(*this); - tx.Write(file); + tx.Write(buffer); link_list_[kIndexTx] = tx.FilePosition(); } - size_t bytes = MdfBlock::Write(file); - bytes += WriteNumber(file, nof_events_); + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteNumber(buffer, nof_events_); for (const auto &ev : event_list_) { - bytes += WriteNumber(file, ev.event_time); - bytes += WriteNumber(file, ev.pre_time); - bytes += WriteNumber(file, ev.post_time); + bytes += WriteNumber(buffer, ev.event_time); + bytes += WriteNumber(buffer, ev.pre_time); + bytes += WriteNumber(buffer, ev.post_time); } return bytes; diff --git a/mdflib/src/tr3block.h b/mdflib/src/tr3block.h index 4c419ee6..47a809a5 100644 --- a/mdflib/src/tr3block.h +++ b/mdflib/src/tr3block.h @@ -19,8 +19,8 @@ struct Tr3Event { class Tr3Block : public MdfBlock { public: [[nodiscard]] std::string Comment() const override; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; private: uint16_t nof_events_ = 0; diff --git a/mdflib/src/tx3block.cpp b/mdflib/src/tx3block.cpp index 28b3b0f0..f527e5f9 100644 --- a/mdflib/src/tx3block.cpp +++ b/mdflib/src/tx3block.cpp @@ -6,33 +6,18 @@ #include #include +#include #include "mdf/mdfhelper.h" namespace mdf::detail { -Tx3Block::Tx3Block(const std::string &text) : text_(text) {} - -size_t Tx3Block::Read(std::FILE *file) { - auto bytes = ReadHeader3(file); - - std::ostringstream temp; - char in = '\0'; - for (; bytes < block_size_; ++bytes) { - auto nof = std::fread(&in, 1, 1, file); - if (nof != 1) { - // Suppose end of file or something - break; - } - if (in == '\0') { - // No more to read - break; - } - temp << in; - } - text_ = temp.str(); +Tx3Block::Tx3Block(std::string text) : text_(std::move(text)) {} - return bytes; +uint64_t Tx3Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader3(buffer); + bytes += ReadStr(buffer, text_, block_size_ - bytes -1); + return bytes + 1; } std::string Tx3Block::Text() const { @@ -40,15 +25,18 @@ std::string Tx3Block::Text() const { MdfHelper::Trim(temp); return temp; } -size_t Tx3Block::Write(std::FILE *file) { + +uint64_t Tx3Block::Write(std::streambuf& buffer) { block_type_ = "TX"; block_size_ = static_cast((2 + 2) + text_.size() + 1); link_list_.clear(); - auto bytes = MdfBlock::Write(file); - bytes += std::fwrite(text_.data(), 1, text_.size(), file); + auto bytes = MdfBlock::Write(buffer); + bytes += buffer.sputn(text_.data(), + static_cast(text_.size())); constexpr char blank = '\0'; - bytes += std::fwrite(&blank, 1, 1, file); + buffer.sputc(blank); + ++bytes; return bytes; } diff --git a/mdflib/src/tx3block.h b/mdflib/src/tx3block.h index 7e127a82..5e30a4de 100644 --- a/mdflib/src/tx3block.h +++ b/mdflib/src/tx3block.h @@ -8,10 +8,12 @@ namespace mdf::detail { class Tx3Block : public MdfBlock { public: - explicit Tx3Block(const std::string &text); + explicit Tx3Block(std::string text); Tx3Block() = default; - size_t Read(std::FILE *file) override; - size_t Write(std::FILE *file) override; + + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; + [[nodiscard]] std::string Text() const; private: diff --git a/mdflib/src/tx4block.cpp b/mdflib/src/tx4block.cpp index 481784d9..52acc8f3 100644 --- a/mdflib/src/tx4block.cpp +++ b/mdflib/src/tx4block.cpp @@ -5,13 +5,15 @@ #include "tx4block.h" #include +#include +#include #include "mdf/mdfhelper.h" #include "platform.h" namespace mdf::detail { -Tx4Block::Tx4Block(const std::string &text) : text_(text) {} +Tx4Block::Tx4Block(std::string text) : text_(std::move(text)) {} std::string FixCommentToLine(const std::string &comment, size_t max) { std::ostringstream temp; @@ -31,16 +33,16 @@ std::string FixCommentToLine(const std::string &comment, size_t max) { bool Tx4Block::IsTxtBlock() const { return Platform::strnicmp(block_type_.c_str(), "##TX", 4) == 0; } - +/* size_t Tx4Block::Read(std::FILE *file) { - auto bytes = ReadHeader4(file); + auto bytes = MdfBlock::ReadHeader4(file); std::ostringstream temp; char in = '\0'; for (; bytes < block_size_; ++bytes) { auto nof = std::fread(&in, 1, 1, file); if (nof != 1) { - // Suppose end of file or something + // Suppose end of the file or something break; } if (in == '\0') { @@ -67,7 +69,31 @@ size_t Tx4Block::Write(std::FILE *file) { auto bytes = MdfBlock::Write(file); bytes += WriteStr(file, text_, text_.size()); bytes += WriteBytes(file, 1); - UpdateBlockSize(file, bytes); + MdfBlock::UpdateBlockSize(file, bytes); + return bytes; +} + */ + +uint64_t Tx4Block::Read(std::streambuf& buffer) { + uint64_t bytes = ReadHeader4(buffer); + bytes += ReadStr(buffer, text_, block_size_ - bytes - 1); + return bytes + 1; +} + +uint64_t Tx4Block::Write(std::streambuf& buffer) { + const bool update = FilePosition() > 0; + if (update) { + return block_size_; + } + const bool is_xml = !text_.empty() && text_[0] == '<'; + block_type_ = is_xml ? "##MD" : "##TX"; + block_size_ = static_cast(24 + text_.size() + 1); + link_list_.clear(); + + uint64_t bytes = MdfBlock::Write(buffer); + bytes += WriteStr(buffer, text_, text_.size()); + bytes += WriteBytes(buffer, 1); + UpdateBlockSize(buffer, bytes); return bytes; } diff --git a/mdflib/src/tx4block.h b/mdflib/src/tx4block.h index 7c05a663..921f8d8b 100644 --- a/mdflib/src/tx4block.h +++ b/mdflib/src/tx4block.h @@ -14,12 +14,12 @@ std::string FixCommentToLine(const std::string& comment, size_t max); class Tx4Block : public MdfBlock { public: Tx4Block() = default; - explicit Tx4Block(const std::string& text); + explicit Tx4Block(std::string text); void GetBlockProperty(BlockPropertyList& dest) const override; [[nodiscard]] bool IsTxtBlock() const; - size_t Read(std::FILE* file) override; - size_t Write(std::FILE* file) override; + uint64_t Read(std::streambuf& buffer) override; + uint64_t Write(std::streambuf& buffer) override; void Text(const std::string& text) {text_ = text;} [[nodiscard]] std::string Text() const; diff --git a/mdflib/src/zlibutil.cpp b/mdflib/src/zlibutil.cpp index e57f163a..c8202ed4 100644 --- a/mdflib/src/zlibutil.cpp +++ b/mdflib/src/zlibutil.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "platform.h" @@ -26,11 +27,7 @@ constexpr size_t kZlibChunk = 16384; namespace mdf { -bool Deflate(FILE* in, FILE* out) { - if (in == nullptr || out == nullptr) { - return false; - } - +bool Deflate(std::streambuf& in, std::streambuf& out) { z_stream s{}; std::vector buf_in(kZlibChunk, 0); std::vector buf_out(kZlibChunk, 0); @@ -43,13 +40,9 @@ bool Deflate(FILE* in, FILE* out) { /* compress until end of file */ int flush; do { - s.avail_in = static_cast(fread(buf_in.data(), 1, kZlibChunk, in)); - if (ferror(in)) { - deflateEnd(&s); - return false; - } - - flush = feof(in) ? Z_FINISH : Z_NO_FLUSH; + s.avail_in = static_cast(in.sgetn( + reinterpret_cast(buf_in.data()), kZlibChunk ) ); + flush = s.avail_in < kZlibChunk ? Z_FINISH : Z_NO_FLUSH; s.next_in = buf_in.data(); /* run deflate() on input until output buffer not full, finish @@ -62,7 +55,8 @@ bool Deflate(FILE* in, FILE* out) { return false; } const auto have = kZlibChunk - s.avail_out; - if (fwrite(buf_out.data(), 1, have, out) != have || ferror(out)) { + if (out.sputn( reinterpret_cast(buf_out.data()), + static_cast(have) ) != have ) { deflateEnd(&s); return false; } @@ -85,18 +79,21 @@ bool Deflate(FILE* in, FILE* out) { bool Deflate(const std::string& filename, ByteArray& buf_out) { try { fs::path name = fs::u8path(filename); - auto size = fs::file_size(name); + uint64_t size = fs::file_size(name); - std::FILE* file = nullptr; - Platform::fileopen(&file, filename.c_str(), "rb"); - if (file == nullptr) { + std::filebuf file; + file.open(name.string(), std::ios_base::in | std::ios_base::binary); + if (!file.is_open()) { return false; } - ByteArray buf_in(size, 0); - const auto nof_bytes = fread(buf_in.data(), 1, size, file); - fclose(file); + + ByteArray buf_in(static_cast(size), 0); + const uint64_t nof_bytes = file.sgetn( + reinterpret_cast(buf_in.data()), + static_cast(size) ); + file.close(); if (nof_bytes < size) { - buf_in.resize(nof_bytes, 0); + buf_in.resize(static_cast(nof_bytes), 0); } if (buf_out.size() < buf_in.size()) { buf_out.resize(buf_in.size(), 0); @@ -140,10 +137,8 @@ bool Deflate(const ByteArray& buf_in, ByteArray& buf_out) { return ret == Z_STREAM_END; } -bool Inflate(std::FILE* in, std::FILE* out) { - if (in == nullptr || out == nullptr) { - return false; - } +bool Inflate(std::streambuf& in, std::streambuf& out) { + // Inflate the input file to the output file z_stream o{}; ByteArray buf_in(kZlibChunk, 0); @@ -155,11 +150,9 @@ bool Inflate(std::FILE* in, std::FILE* out) { /* decompress until deflate stream ends or end of file */ do { - o.avail_in = static_cast(fread(buf_in.data(), 1, kZlibChunk, in)); - if (ferror(in)) { - inflateEnd(&o); - return false; - } + o.avail_in = static_cast(in.sgetn( + reinterpret_cast(buf_in.data()), + kZlibChunk) ); if (o.avail_in == 0) { break; } @@ -185,7 +178,9 @@ bool Inflate(std::FILE* in, std::FILE* out) { break; } const auto have = kZlibChunk - o.avail_out; - if (fwrite(buf_out.data(), 1, have, out) != have || ferror(out)) { + if (out.sputn( + reinterpret_cast(buf_out.data()), + static_cast(have) ) != have ) { inflateEnd(&o); return false; } @@ -197,10 +192,7 @@ bool Inflate(std::FILE* in, std::FILE* out) { return ret == Z_STREAM_END; } -bool Inflate(std::FILE* in, std::FILE* out, uint64_t nof_bytes) { - if (in == nullptr || out == nullptr) { - return false; - } +bool Inflate(std::streambuf& in, std::streambuf& out, uint64_t nof_bytes) { // Inflate the input file to the output file z_stream o{}; ByteArray buf_in(kZlibChunk, 0); @@ -217,16 +209,15 @@ bool Inflate(std::FILE* in, std::FILE* out, uint64_t nof_bytes) { break; // Ready } - size_t bytes_to_read = kZlibChunk; + uint64_t bytes_to_read = kZlibChunk; if (count + kZlibChunk > nof_bytes) { bytes_to_read = nof_bytes - count; } - o.avail_in = static_cast(fread(buf_in.data(), 1, bytes_to_read, in)); - if (ferror(in)) { - inflateEnd(&o); - return false; - } + o.avail_in = static_cast(in.sgetn( + reinterpret_cast(buf_in.data()), + static_cast(bytes_to_read))); + if (o.avail_in == 0) { break; } @@ -253,7 +244,9 @@ bool Inflate(std::FILE* in, std::FILE* out, uint64_t nof_bytes) { break; } const auto have = kZlibChunk - o.avail_out; - if (fwrite(buf_out.data(), 1, have, out) != have || ferror(out)) { + if (out.sputn( + reinterpret_cast(buf_out.data()), + static_cast(have)) != have ) { inflateEnd(&o); return false; } @@ -307,8 +300,8 @@ bool Inflate(const ByteArray& buf_in, ByteArray& buf_out) { return ret == Z_STREAM_END; } -bool Inflate(const ByteArray& buf_in, std::FILE* to_file) { - if (buf_in.empty() || to_file == nullptr) { +bool Inflate(const ByteArray& buf_in, std::streambuf& to_file) { + if (buf_in.empty()) { return false; } @@ -342,7 +335,9 @@ bool Inflate(const ByteArray& buf_in, std::FILE* to_file) { break; } const auto have = kZlibChunk - o.avail_out; - if (fwrite(buf_out.data(), 1, have, to_file) != have || ferror(to_file)) { + if (to_file.sputn( + reinterpret_cast(buf_out.data()), + static_cast(have) ) != have) { inflateEnd(&o); return false; } diff --git a/mdflib_test/CMakeLists.txt b/mdflib_test/CMakeLists.txt index 20a042d7..0a39a66b 100644 --- a/mdflib_test/CMakeLists.txt +++ b/mdflib_test/CMakeLists.txt @@ -32,7 +32,9 @@ add_executable(test_mdf src/testchannelarray.cpp src/testchannelarray.h src/testxtensor.cpp - src/testqueue.cpp) + src/testqueue.cpp + src/testiostream.cpp + src/testmdfblock.cpp) target_include_directories(test_mdf PRIVATE ../include ../mdflib/src) if(VCPKG) diff --git a/mdflib_test/src/testiostream.cpp b/mdflib_test/src/testiostream.cpp new file mode 100644 index 00000000..fbfab73b --- /dev/null +++ b/mdflib_test/src/testiostream.cpp @@ -0,0 +1,117 @@ +/* +* Copyright 2024 Ingemar Hedvall +* SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include +using namespace std::filesystem; +using namespace boost::iostreams; + +namespace { + std::string MakeFilePath(const std::string_view& filename) { + try { + path temp_path = temp_directory_path(); + temp_path.append("test"); + temp_path.append("iostreams"); + create_directories(temp_path); + + temp_path.append(filename); + remove(temp_path); + return temp_path.string(); + } catch( const std::exception& err) { + std::cout << "Error: " << err.what() << std::endl; + } + return {}; + } +} + +namespace mdf::test { +TEST(BoostIostreams, SimpleFile) { + + const std::string test_file = MakeFilePath("simple_file.txt"); + + stream_buffer out_buffer(test_file); + + std::ostream out_file(&out_buffer); + constexpr std::string_view test_text = "Hello Boost IO-streams."; + out_file << test_text << std::endl; + + stream_buffer input_buffer(test_file); + std::istream input_file(&input_buffer); + while (!input_file.eof()) { + std::string input_text; + input_file >> input_text; + std::cout << input_text << std::endl; + } +} + +TEST(BoostIostreams, SimpleByteArray) { + std::vector data_list(256,0); + + stream_buffer< array_sink > out_buffer(reinterpret_cast(data_list.data()), + data_list.size()); + std::ostream out_array(&out_buffer); + + for (int index = 0; index < data_list.size(); ++index ) { + out_array.put(static_cast(index)); + } + out_buffer.close(); + + stream_buffer input_buffer(reinterpret_cast(data_list.data()), + data_list.size()); + std::istream input_array(&input_buffer); + int byte_index = 0; + while (!input_array.eof()) { + int input = input_array.get(); + if (input < 0) { + break; + } + EXPECT_EQ(input, byte_index) << byte_index << "/" << input; + ++byte_index; + } + EXPECT_EQ(byte_index, 256); + EXPECT_TRUE(input_array.eof()); + input_array.seekg(0,std::ios_base::beg); + EXPECT_FALSE(input_array.eof()); + +} + +TEST(BoostIostreams, SimpleWrite) { + std::vector data_list; + back_insert_device> insert_device(data_list); + + stream_buffer< back_insert_device >> out_buffer(insert_device); + + std::basic_streambuf& temp = out_buffer; + + std::ostream out_array(&temp); + + for (int index = 0; index < 256; ++index ) { + out_array.put(static_cast(index)); + } + out_buffer.close(); + + std::cout << "Size: " << data_list.size() << std::endl; + + stream_buffer input_buffer(data_list.data(), data_list.size()); + std::istream input_array(&input_buffer); + int byte_index = 0; + while (!input_array.eof()) { + int input = input_array.get(); + if (input < 0) { + break; + } + EXPECT_EQ(input, byte_index) << byte_index << "/" << input; + ++byte_index; + } + EXPECT_EQ(byte_index, 256); + EXPECT_TRUE(input_array.eof()); + input_array.seekg(0,std::ios_base::beg); + EXPECT_FALSE(input_array.eof()); +} + +} // end namespace \ No newline at end of file diff --git a/mdflib_test/src/testmdfblock.cpp b/mdflib_test/src/testmdfblock.cpp new file mode 100644 index 00000000..3febf195 --- /dev/null +++ b/mdflib_test/src/testmdfblock.cpp @@ -0,0 +1,115 @@ +/* +* Copyright 2024 Ingemar Hedvall +* SPDX-License-Identifier: MIT + */ + +#include +#include "mdfblock.h" +#include +#include +using namespace std::filesystem; +using namespace mdf::detail; +namespace { + std::string MakeTestFilePath(const std::string_view& name) { + try { + path filename = temp_directory_path(); + filename.append("test"); + filename.append("mdf"); + create_directories(filename); + filename.append(name); + remove(filename); + return filename.string(); + + } catch (const std::exception& err) { + std::cout << err.what() << std::endl; + } + return {}; + } + +} + +namespace mdf::test { + +TEST(TestMdfBlock, TestStatic) { + std::string test_file = MakeTestFilePath("static.mf4"); + std::filebuf file_buffer; + std::filebuf* write = file_buffer.open(test_file, + std::ios_base::out + | std::ios_base::trunc + | std::ios_base::binary ); + ASSERT_TRUE(write != nullptr); + EXPECT_TRUE(file_buffer.is_open()); + + EXPECT_EQ(GetFilePosition(file_buffer), 0); + EXPECT_EQ(GetLastFilePosition(file_buffer), 0); + + std::vector orig_array = {0,1,2,3,4,5,6,7,8,9}; + const uint64_t orig_size = WriteByte(file_buffer, orig_array); + EXPECT_EQ(orig_size, 10); + + const uint64_t empty_size = WriteBytes(file_buffer, 10); + EXPECT_EQ(empty_size, 10); + + const uint64_t text_size = WriteStr(file_buffer, "Hello", 10); + EXPECT_EQ(text_size, 10); + + file_buffer.close(); + EXPECT_FALSE(file_buffer.is_open()); + + std::filebuf* read = file_buffer.open(test_file, + std::ios_base::in | std::ios_base::binary); + ASSERT_TRUE(read != nullptr); + EXPECT_TRUE(file_buffer.is_open()); + + EXPECT_EQ(GetFilePosition(file_buffer), 0); + EXPECT_GT(GetLastFilePosition(file_buffer), 0); + SetFirstFilePosition(file_buffer); + + std::vector dest_array; + const uint64_t dest_size = ReadByte(file_buffer, dest_array, 10); + EXPECT_EQ(dest_array, orig_array); + EXPECT_EQ(dest_size, 10); + + const uint64_t step_size = StepFilePosition(file_buffer, 10); + EXPECT_EQ(step_size, 10); + + std::string dest_text; + const uint64_t read_size = ReadStr(file_buffer, dest_text, 10); + EXPECT_STREQ(dest_text.c_str(), "Hello"); + EXPECT_EQ(read_size, 10 ); + + file_buffer.close(); + EXPECT_FALSE(file_buffer.is_open()); + +} + +TEST(TestMdfBlock, TestOpenMdf) { + std::string test_file = MakeTestFilePath("open.mf4"); + std::filebuf file_buffer; + const bool write = OpenMdfFile(file_buffer, test_file, + std::ios_base::out + | std::ios_base::trunc + | std::ios_base::binary ); + ASSERT_TRUE(write); + EXPECT_TRUE(file_buffer.is_open()); + std::vector orig_array = {0,1,2,3,4,5,6,7,8,9}; + WriteByte(file_buffer, orig_array); + + file_buffer.close(); + EXPECT_FALSE(file_buffer.is_open()); + + const bool read = OpenMdfFile(file_buffer, test_file, + std::ios_base::in | std::ios_base::binary); + ASSERT_TRUE(read); + EXPECT_TRUE(file_buffer.is_open()); + + std::vector dest_array; + ReadByte(file_buffer, dest_array, 10); + EXPECT_EQ(dest_array, orig_array); + + file_buffer.close(); + EXPECT_FALSE(file_buffer.is_open()); + +} + +} diff --git a/mdflib_test/src/testmdffile.cpp b/mdflib_test/src/testmdffile.cpp index 45ab6da5..74642539 100644 --- a/mdflib_test/src/testmdffile.cpp +++ b/mdflib_test/src/testmdffile.cpp @@ -78,7 +78,7 @@ TEST(TestMdf, Mdf3File) { // NOLINT std::cout << "File Name: " << mdf->FileName() << std::endl; std::cout << "Name: " << mdf->Name() << std::endl; - +/* uint16_t standard_flags = 0; uint16_t custom_flags = 0; EXPECT_TRUE(mdf->IsFinalized(standard_flags, custom_flags)); @@ -90,6 +90,7 @@ TEST(TestMdf, Mdf3File) { // NOLINT EXPECT_TRUE(mdf->IsFinalized(standard_flags, custom_flags)); EXPECT_EQ(standard_flags, 0); EXPECT_EQ(custom_flags, 0); + */ } TEST(TestMdf, Mdf4File) { // NOLINT @@ -154,7 +155,7 @@ TEST(TestMdf, Mdf4File) { // NOLINT std::cout << "File Name: " << mdf->FileName() << std::endl; std::cout << "Name: " << mdf->Name() << std::endl; - +/* uint16_t standard_flags = 0; uint16_t custom_flags = 0; EXPECT_TRUE(mdf->IsFinalized(standard_flags, custom_flags)); @@ -166,7 +167,7 @@ TEST(TestMdf, Mdf4File) { // NOLINT EXPECT_TRUE(mdf->IsFinalized(standard_flags, custom_flags)); EXPECT_EQ(standard_flags, 0); EXPECT_EQ(custom_flags, 0); - +*/ auto* header = mdf->Header(); ASSERT_TRUE(header != nullptr); diff --git a/mdflib_test/src/testread.cpp b/mdflib_test/src/testread.cpp index ff9b38ba..7c1f9239 100644 --- a/mdflib_test/src/testread.cpp +++ b/mdflib_test/src/testread.cpp @@ -9,6 +9,10 @@ #include #include +#include +#include +#include + #include "mdf/mdfreader.h" #include "mdf3file.h" #include "mdf4file.h" @@ -24,6 +28,8 @@ using namespace mdf::detail; using namespace util::log; using namespace std::chrono_literals; using namespace std::chrono; +using namespace boost::iostreams; + namespace { const std::string mdf_source_dir = "k:/test/mdf"; // Where all source MDF files exist @@ -634,4 +640,70 @@ TEST_F(TestRead, TestCssSampleObserver) { << "/" << diff2.count() << " ms)" << std::endl; } + + +TEST_F(TestRead, TestStreamInterface) // NOLINT +{ + if (kMdfList.empty()) { + GTEST_SKIP_("No MDF files found."); + } + // Read into memory and then parse the memory. + + for (const auto &[name, filename] : kMdfList) { + uint64_t file_size = 0; + // Read in file into memory + try { + const path fullname(filename); + file_size = std::filesystem::file_size(fullname); + } catch (std::exception& err) { + ADD_FAILURE() << err.what(); + continue; + } + + if (file_size > 1'000'000'000) { + // Skip large files. + continue; + } + std::vector file_array; + file_array.reserve(file_size); + + back_insert_device> array_device(file_array); + stream_buffer< back_insert_device >> out_buffer(array_device); + std::ostream out_array(&out_buffer); + + std::ifstream in_file(filename, std::ios_base::in | std::ios_base::binary); + for ( int input = in_file.get(); !in_file.eof(); input = in_file.get() ) { + if (input>= 0) { + out_array.put(static_cast(input)); + } + } + in_file.close(); + out_buffer.close(); + + if (file_array.empty()) { + ADD_FAILURE() << "File is empty. File: " << name; + continue; + } + + std::shared_ptr input_buffer = + std::make_shared< stream_buffer >(file_array.data(), file_array.size()); + + MdfReader oRead(input_buffer); + EXPECT_TRUE(oRead.ReadMeasurementInfo()) << name; + const auto *mdf_file = oRead.GetFile(); + ASSERT_TRUE(mdf_file != nullptr) << name; + if (mdf_file->IsMdf4()) { + const auto *file4 = dynamic_cast(mdf_file); + ASSERT_TRUE(file4 != nullptr) << name; + const auto &hd4 = file4->Hd(); + const auto &dg_list = hd4.Dg4(); + std::cout <<"File: " << name << ", Nof Measurement: " << dg_list.size() << std::endl; + EXPECT_FALSE(dg_list.empty()) << name; + } else { + const auto *file3 = dynamic_cast(mdf_file); + EXPECT_TRUE(file3 != nullptr); + } + } +} + } // namespace mdf::test diff --git a/mdflib_test/src/testzlib.cpp b/mdflib_test/src/testzlib.cpp index 0c997631..57170eaf 100644 --- a/mdflib_test/src/testzlib.cpp +++ b/mdflib_test/src/testzlib.cpp @@ -5,6 +5,7 @@ #include "testzlib.h" #include +#include #include "mdf/zlibutil.h" #include "platform.h" @@ -69,24 +70,30 @@ TEST_F(TestZlib, FileCompress) { GTEST_SKIP() << "Skipped Test"; } - auto* in = fopen(kTestFile.c_str(), "rb"); - EXPECT_TRUE(in != nullptr); - auto* out = fopen(kDeflateFile.c_str(), "wb"); - EXPECT_TRUE(out != nullptr); + std::filebuf in; + in.open(kTestFile, std::ios_base::in | std::ios_base::binary); + EXPECT_TRUE(in.is_open()); + + std::filebuf out; + out.open(kDeflateFile, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary); + EXPECT_TRUE(out.is_open()); EXPECT_TRUE(Deflate(in, out)); - fclose(in); - fclose(out); + in.close(); + out.close(); + + std::filebuf in1; + in1.open(kDeflateFile, std::ios_base::in | std::ios_base::binary); + EXPECT_TRUE(in1.is_open()); - auto* in1 = fopen(kDeflateFile.c_str(), "rb"); - EXPECT_TRUE(in1 != nullptr); - auto* out1 = fopen(kInflateFile.c_str(), "wb"); - EXPECT_TRUE(out1 != nullptr); + std::filebuf out1; + out1.open(kInflateFile, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary); + EXPECT_TRUE(out1.is_open()); EXPECT_TRUE(Inflate(in1, out1)); - fclose(in1); - fclose(out1); + in1.close(); + out1.close(); } TEST_F(TestZlib, FileToBuffCompress) { @@ -97,12 +104,12 @@ TEST_F(TestZlib, FileToBuffCompress) { ByteArray buf_out; EXPECT_TRUE(Deflate(kTestFile, buf_out)); - std::FILE* out_file = nullptr; - Platform::fileopen(&out_file, kInflateFile.c_str(), "wb"); - ASSERT_TRUE(out_file != nullptr); + std::filebuf out_file; + out_file.open(kInflateFile, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary); + ASSERT_TRUE(out_file.is_open()); EXPECT_TRUE(Inflate(buf_out, out_file)); - fclose(out_file); + out_file.close(); } TEST_F(TestZlib, ArrayCompressLarge) { diff --git a/mdflibrary/src/MdfFile.cpp b/mdflibrary/src/MdfFile.cpp index be608af8..afb0b874 100644 --- a/mdflibrary/src/MdfFile.cpp +++ b/mdflibrary/src/MdfFile.cpp @@ -15,7 +15,7 @@ array^ MdfFile::Attachments::get() { } array^ temp_list = gcnew array(static_cast(list.size())); - for (int index = 0; index < list.size(); ++index) { + for (size_t index = 0; index < list.size(); ++index) { auto* temp = const_cast(list[index]); temp_list[static_cast(index)] = gcnew MdfAttachment(temp); } @@ -29,7 +29,7 @@ array^ MdfFile::DataGroups::get() { } array^ temp_list = gcnew array(static_cast(list.size())); - for (int index = 0; index < list.size(); ++index) { + for (size_t index = 0; index < list.size(); ++index) { auto* temp = const_cast(list[index]); temp_list[static_cast(index)] = gcnew MdfDataGroup(temp); } diff --git a/mdflibrary/src/mdflibrary.cpp b/mdflibrary/src/mdflibrary.cpp index ea01c27f..e20ad73a 100644 --- a/mdflibrary/src/mdflibrary.cpp +++ b/mdflibrary/src/mdflibrary.cpp @@ -115,7 +115,9 @@ array^ MdfLibrary::CreateChannelObserverForChannelGroup( String^ MdfLibrary::Utf8Conversion(const std::string& utf8_string) { array^ c_array = gcnew array(static_cast(utf8_string.length())); - for (int i = 0; i < utf8_string.length(); i++) c_array[i] = utf8_string[i]; + for (size_t i = 0; i < utf8_string.length(); i++) { + c_array[static_cast(i)] = utf8_string[i]; + } System::Text::Encoding^ u8enc = System::Text::Encoding::UTF8; return u8enc->GetString(c_array); diff --git a/mdflibrary_test_net/MdfLibraryTest.cs b/mdflibrary_test_net/MdfLibraryTest.cs index 47b4ef54..3ebed378 100644 --- a/mdflibrary_test_net/MdfLibraryTest.cs +++ b/mdflibrary_test_net/MdfLibraryTest.cs @@ -953,6 +953,10 @@ public void TestReader2() Assert.Inconclusive("File doesn't exist."); } var Reader = new MdfReader(TestFile4); + if (!Reader.IsOk) + { + Assert.Inconclusive("Invalid File"); + } Reader.ReadEverythingButData(); var lVersion = Reader.File.MainVersion; diff --git a/script/boost.cmake b/script/boost.cmake index 29b2ca0f..207d8a57 100644 --- a/script/boost.cmake +++ b/script/boost.cmake @@ -9,10 +9,13 @@ if (NOT Boost_FOUND) set(Boost_DEBUG OFF) if (COMP_DIR) + #set(Boost_DIR ${COMP_DIR}/boost/latest/lib/cmake/Boost-1.86.0) set(Boost_ROOT ${COMP_DIR}/boost/latest) endif() - - find_package(Boost REQUIRED COMPONENTS filesystem system locale program_options) + if(POLICY CMP0167) + cmake_policy(SET CMP0167 OLD) + endif() + find_package(Boost REQUIRED COMPONENTS filesystem system locale program_options iostreams) message(STATUS "Boost Found : " ${Boost_FOUND}) message(STATUS "Boost Version: " ${Boost_VERSION_STRING}) message(STATUS "Boost Include Dirs: " ${Boost_INCLUDE_DIRS}) diff --git a/vcpkg.json b/vcpkg.json index e97090c8..50987ebf 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -25,6 +25,7 @@ "description": "Build mdf tests", "dependencies": [ "boost-endian", + "boost-iostreams", "xtensor", "gtest" ]