diff --git a/BaseLib/FileTools.cpp b/BaseLib/FileTools.cpp index c37c482884c913c136d0e60aa747e9131a90d294..921989744c62b2bf145631a3a3c7ac2c87ab5fc7 100644 --- a/BaseLib/FileTools.cpp +++ b/BaseLib/FileTools.cpp @@ -17,6 +17,7 @@ #include <spdlog/fmt/bundled/core.h> #include <boost/algorithm/string/predicate.hpp> +#include <boost/endian/conversion.hpp> #include <filesystem> #include <fstream> #include <typeindex> @@ -332,6 +333,53 @@ std::vector<T> readBinaryArray(std::string const& filename, std::size_t const n) template std::vector<float> readBinaryArray<float>(std::string const&, std::size_t const); +template <typename T> +std::vector<T> readBinaryVector(std::string const& filename) +{ + std::ifstream file(filename, std::ios::binary); + if (!file) + { + OGS_FATAL("File {:s} for curve definition not found", filename); + } + + // Determine file size + file.seekg(0, std::ios::end); + std::streamsize size = file.tellg(); + file.seekg(0, std::ios::beg); + + size_t num_elements = size / sizeof(T); + + // Initialize vector with the right size + std::vector<T> result(num_elements); + + // Read data directly into the vector + if (!file.read(reinterpret_cast<char*>(result.data()), size)) + { + OGS_FATAL("Could not read data from file {:s}.", filename); + } + + if constexpr (std::endian::native != std::endian::little) + { + boost::endian::endian_reverse_inplace(result); + } + + std::streamsize bytes_read = file.gcount(); + + if (bytes_read != size) + { + OGS_FATAL( + "Incomplete read: Expected {:d} bytes, but read {:d} bytes " + "from " + "file {:s}.", + size, bytes_read, filename); + } + return result; +} + +// explicit template instantiation +template std::vector<float> readBinaryVector<float>(std::string const&); +template std::vector<double> readBinaryVector<double>(std::string const&); + template <typename T> void writeValueBinary(std::ostream& out, T const& val) { diff --git a/BaseLib/FileTools.h b/BaseLib/FileTools.h index 216c40afa8de71a8923e6ab3f6f4cb624f6fca7a..5d5ee6b59742e0c01661ecfefb05b1978a610d8a 100644 --- a/BaseLib/FileTools.h +++ b/BaseLib/FileTools.h @@ -92,6 +92,9 @@ template <typename T> std::vector<T> readBinaryArray(std::string const& filename, std::size_t const n); +template <typename T> +std::vector<T> readBinaryVector(std::string const& filename); + /** * Extracts basename from given pathname with extension. * diff --git a/MathLib/Curve/CreatePiecewiseLinearCurve.cpp b/MathLib/Curve/CreatePiecewiseLinearCurve.cpp index b7cc4950de6b1e70f1e854c751ff42413b86ae3c..95d2bbce89c5f7194d6595b228da928617b1577f 100644 --- a/MathLib/Curve/CreatePiecewiseLinearCurve.cpp +++ b/MathLib/Curve/CreatePiecewiseLinearCurve.cpp @@ -29,41 +29,15 @@ std::vector<double> readDoublesFromBinaryFile(const std::string& filename) { auto prj_dir = BaseLib::getProjectDirectory(); std::string path_to_file = BaseLib::joinPaths(prj_dir, filename); - - std::ifstream file(path_to_file, std::ios::binary); - if (!file) - { - OGS_FATAL("File {:s} at path {:s} for curve definition not found", - filename, prj_dir); - } - - // Determine file size - file.seekg(0, std::ios::end); - std::streamsize size = file.tellg(); - file.seekg(0, std::ios::beg); - - // Initialize vector with the right size - std::vector<double> result(size / sizeof(double)); - - // read data directly into the vector - if (!file.read(reinterpret_cast<char*>(result.data()), size)) + std::string file_extension = BaseLib::getFileExtension(filename); + if (file_extension != ".bin") { - OGS_FATAL("Could not read curve definition from file {:s}.", filename); - } - - if constexpr (std::endian::native != std::endian::little) - { - // swap endians if needed - std::transform( - result.begin(), result.end(), result.begin(), - [](double value) - { - return std::bit_cast<double>(boost::endian::endian_reverse( - std::bit_cast<uint64_t>(value))); - }); + OGS_FATAL( + "Currently only binary files with extension '.bin' supported. The " + "specified file has extension {:s}.", + file_extension) } - - return result; + return BaseLib::readBinaryVector<double>(path_to_file); } PiecewiseLinearCurveConfig parsePiecewiseLinearCurveConfig( @@ -80,6 +54,7 @@ PiecewiseLinearCurveConfig parsePiecewiseLinearCurveConfig( auto const coords_file_name = //! \ogs_file_param{curve__coords} config.getConfigParameter<std::string>("coords"); + auto const values_file_name = //! \ogs_file_param{curve__values} config.getConfigParameter<std::string>("values");