CPP-snippets 0.0.1
A silly C++ project to use for demonstrating code integration
Loading...
Searching...
No Matches
interface.hpp
1#pragma once
2
3#include <string>
4#include <filesystem>
5#include <iostream>
6
7#include <toml++/toml.hpp>
8#include <Eigen/Dense>
9
10/**
11 * @brief
12 *
13 * @param m_output_dir Output directory based on toml input
14 */
16public:
17 toml::table m_input;
18
19 /**
20 * @brief Construct a new Interface and load the TOML configuration file.
21 *
22 * Expects the first command-line argument (argv[1]) to be the path
23 * to the TOML configuration file.
24 *
25 * @param argc Number of command-line arguments.
26 * @param argv Command-line argument array.
27 */
28 explicit IOInterface(int argc, char* argv[]);
29 ~IOInterface(); // add destructor
30
31 /**
32 * @brief Write a matrix to a CSV file in scientific notation.
33 *
34 * This method exports the content of an Eigen::MatrixXd to a CSV-formatted
35 * text file. Each row of the matrix is written as a line in the file, with
36 * values formatted using scientific notation. The output file will be
37 * overwritten if it already exists.
38 *
39 * @param filename
40 * The path and name of the output CSV file.
41 *
42 * @param matrix_data
43 * The matrix whose contents will be written to the file. Each row
44 * is written sequentially as a separate line.
45 *
46 * @note
47 * - Values are written using `std::scientific` formatting.
48 * - No header row is included in the output.
49 * - Elements in each row are written using Eigen’s default stream operator,
50 * which separates values with spaces rather than commas unless customized.
51 *
52 * @see Eigen::MatrixXd
53 */
54 template <typename Derived>
55 void write2csv(const std::string& filename,
56 const Eigen::MatrixBase<Derived>& mat_data,
57 const std::string& comment) const {
58
59 std::filesystem::path output_dir = m_input.get("output")->value_or("");
60
61 std::cout << " Writing " << filename << std::endl;
62
63 std::ofstream output_stream(output_dir / filename);
64 if (!output_stream.is_open()) {
65 throw std::runtime_error("Cannot open file: " +
66 (output_dir / filename).string());
67 }
68
69 output_stream << std::scientific;
70 const int rows = mat_data.rows();
71 const int cols = mat_data.cols();
72 output_stream << "# Data size (" << rows << ", " << cols << ")" << comment << std::endl;
73
74 for (int i = 0; i < rows; ++i) {
75 for (int j = 0; j < cols; ++j) {
76 output_stream << mat_data(i, j);
77 if (j < cols - 1) output_stream << ' '; // single whitespace
78 }
79 output_stream << '\n';
80 }
81 }
82 void write2csv(const std::string& filename, Eigen::VectorXd& vector_data, const std::string& comment) const;
83
84 template <typename VecT>
85 VecT load_vector(const std::string& toml_path) const
86 {
87 using Scalar = typename VecT::Scalar;
88
89 // Access array in TOML
90 auto arr = m_input.at_path(toml_path).as_array();
91 if (!arr) {
92 throw std::runtime_error("Missing " + toml_path + " array in TOML file.");
93 }
94
95 const std::size_t toml_size = arr->size();
96 // Create resulting vector
97 VecT vec;
98
99 // Handle fixed-size vs dynamic-size
100 if constexpr (VecT::SizeAtCompileTime == Eigen::Dynamic) {
101 vec.resize(toml_size);
102 } else {
103 if (toml_size != VecT::SizeAtCompileTime) {
104 throw std::runtime_error(
105 "Size mismatch for " + toml_path +
106 ": expected " + std::to_string(VecT::SizeAtCompileTime) +
107 ", got " + std::to_string(toml_size)
108 );
109 }
110 }
111
112 // Fill vector
113 for (std::size_t i = 0; i < toml_size; ++i) {
114 vec(i) = static_cast<Scalar>(arr->at(i).value_or(Scalar{}));
115 }
116
117 return vec;
118 }
119
120 /**
121 * @brief Load a scalar value from the TOML input file using a dotted path.
122 *
123 * This function loads a single scalar value (int, double, bool, string, …)
124 * from the TOML configuration. The path is resolved using toml::node::at_path().
125 *
126 * @tparam T The C++ type to convert the TOML value into.
127 * @param toml_path Dotted path to the value in the TOML configuration.
128 *
129 * @return The loaded value, converted to type T.
130 *
131 * @throws std::runtime_error if the path does not exist or cannot be converted.
132 */
133 template <typename T>
134 T load_scalar(const std::string& toml_path) const
135 {
136 // Try to access the node at the given path
137 auto node = m_input.at_path(toml_path);
138
139 if (!node) {
140 throw std::runtime_error("Missing scalar value at path: " + toml_path);
141 }
142
143 // Extract the value and convert
144 auto val = node.value<T>();
145 if (!val.has_value()) {
146 throw std::runtime_error(
147 "Type mismatch or invalid value at path: " + toml_path
148 );
149 }
150
151 return *val;
152 }
153
154};
T load_scalar(const std::string &toml_path) const
Load a scalar value from the TOML input file using a dotted path.
IOInterface(int argc, char *argv[])
Construct a new Interface and load the TOML configuration file.
Definition interface.cpp:6
void write2csv(const std::string &filename, const Eigen::MatrixBase< Derived > &mat_data, const std::string &comment) const
Write a matrix to a CSV file in scientific notation.
Definition interface.hpp:55