ampsci
High-precision calculations for one- and two-valence atomic systems
FRW_fileReadWrite.hpp
1#pragma once
2#include <algorithm>
3#include <fstream>
4#include <iostream>
5#include <sstream>
6#include <string>
7#include <tuple>
8#include <type_traits>
9#include <utility>
10#include <vector>
11/*!
12 @brief File read/write utilities: text parsing and binary I/O.
13 @details
14 Low-level helpers for reading and writing text and binary files. Includes
15 functions for parsing space- or line-separated input files (with comment
16 stripping), reading (x, y) data, and variadic binary read/write for PoD types,
17 vectors, and strings.
18
19 @warning Many functions in this namespace are old and some are obsolete.
20 Use sparingly and with caution -- prefer higher-level IO interfaces where
21 available.
22*/
23namespace IO::FRW {
24
25//------------------------------------------------------------------------------
26//! Reads (x, y) pairs from a file; returns a pair of vectors {xs, ys}.
27//! Lines beginning with '#', '!', or '//' are skipped.
28inline std::pair<std::vector<double>, std::vector<double>>
29readFile_xy_PoV(const std::string &fname) {
30 std::pair<std::vector<double>, std::vector<double>> out_list;
31 std::ifstream file(fname);
32 std::string line = "";
33 while (getline(file, line) && (file.is_open())) { // redundant?
34 if (line == "")
35 continue;
36 if (line.at(0) == '!' || line.at(0) == '#')
37 continue;
38 if (line.size() >= 2 && line.at(0) == '/' && line.at(1) == '/')
39 continue;
40 std::stringstream ss(line);
41 double x, y;
42 ss >> x >> y;
43 out_list.first.push_back(x);
44 out_list.second.push_back(y);
45 }
46 return out_list;
47}
48
49//==============================================================================
50//! Removes C-style block comments (/* ... */) from a string in-place.
51inline void removeBlockComments(std::string &input) {
52 for (auto posi = input.find("/*"); posi != std::string::npos;
53 posi = input.find("/*")) {
54 auto posf = input.find("*/");
55 if (posf != std::string::npos) {
56 input = input.substr(0, posi) + input.substr(posf + 2);
57 } else {
58 input = input.substr(0, posi);
59 }
60 }
61}
62//==============================================================================
63//! Strips comments (#, !, //, /* */), spaces, tabs, and quote characters.
64//! Lines are squashed together; semicolons are preserved as delimiters.
65inline std::string removeCommentsAndSpaces(const std::string &input) {
66 std::string lines = "";
67 {
68 std::string line;
69 std::stringstream stream1(input);
70 while (std::getline(stream1, line, '\n')) {
71 auto comm1 = line.find('!'); // nb: char, NOT string literal!
72 auto comm2 = line.find('#');
73 auto comm3 = line.find("//"); // str literal here
74 auto comm = std::min(comm1, std::min(comm2, comm3));
75 lines += line.substr(0, comm);
76 }
77 }
78
80
81 // remove spaces
82 lines.erase(std::remove_if(lines.begin(), lines.end(),
83 [](unsigned char x) { return x == ' '; }),
84 lines.end());
85 // remove tabs
86 lines.erase(std::remove_if(lines.begin(), lines.end(),
87 [](unsigned char x) { return x == '\t'; }),
88 lines.end());
89
90 // remove ' and "
91 lines.erase(std::remove_if(lines.begin(), lines.end(),
92 [](unsigned char x) { return x == '\''; }),
93 lines.end());
94 lines.erase(std::remove_if(lines.begin(), lines.end(),
95 [](unsigned char x) { return x == '\"'; }),
96 lines.end());
97
98 return lines;
99}
100
101//==============================================================================
102enum RoW { read, write };
103
104// XXX Wrap these into a class. AND make explicit which types are/aren't
105// allowed!
106
107//! Opens a binary fstream for reading or writing according to @p row.
108inline void open_binary(std::fstream &stream, const std::string &fname,
109 RoW row) {
110 switch (row) {
111 case write:
112 stream.open(fname, std::ios_base::out | std::ios_base::binary);
113 break;
114 case read:
115 stream.open(fname, std::ios_base::in | std::ios_base::binary);
116 break;
117 default:
118 std::cout << "\nFAIL 16 in FRW\n";
119 }
120}
121
122//! Returns true if the file at @p fileName exists and can be opened.
123inline bool file_exists(const std::string &fileName) {
124 if (fileName == "")
125 return false;
126 std::ifstream infile(fileName);
127 return infile.good();
128}
129
130//! Function (variadic): reads/writes data from/to binary file. Works for
131//! trivial (PoD) types, and std::string only (but not checked)
132//! Overload for vectors
133template <typename T, typename... Types>
134void rw_binary(std::fstream &stream, RoW row, std::vector<T> &value,
135 Types &...values) {
136 binary_rw_vec(stream, value, row);
137 if constexpr (sizeof...(values) != 0)
138 rw_binary(stream, row, values...);
139}
140
141//! Function (variadic): reads/writes data from/to binary file. Works for
142//! trivial (PoD) types, and std::string only (but not checked)
143template <typename T, typename... Types>
144void rw_binary(std::fstream &stream, RoW row, T &value, Types &...values) {
145 if constexpr (std::is_same_v<T, std::string>)
146 binary_str_rw(stream, value, row);
147 else
148 binary_rw(stream, value, row);
149 if constexpr (sizeof...(values) != 0)
150 rw_binary(stream, row, values...);
151}
152
153// make "private" behind 'helper' namespace: used in old code still
154template <typename T>
155void binary_rw(std::fstream &stream, T &value, RoW row) {
156 switch (row) {
157 case write:
158 stream.write(reinterpret_cast<const char *>(&value), sizeof(T));
159 break;
160 case read:
161 stream.read(reinterpret_cast<char *>(&value), sizeof(T));
162 break;
163 default:
164 std::cout << "\nFAIL 32 in FRW\n";
165 }
166}
167
168// For vector. {works with Vector of vectors also}
169template <typename T>
170void binary_rw_vec(std::fstream &stream, std::vector<T> &value, RoW row) {
171 std::size_t size = value.size();
172 binary_rw(stream, size, row);
173 if (row == read)
174 value.resize(size);
175 for (auto &x : value) {
176 rw_binary(stream, row, x);
177 }
178}
179
180// make "private" behind 'helper' namespace: used in old code still
181inline void binary_str_rw(std::fstream &stream, std::string &value, RoW row) {
182 if (row == write) {
183 std::size_t temp_len = value.length();
184 stream.write(reinterpret_cast<const char *>(&temp_len),
185 sizeof(std::size_t));
186 stream.write(value.c_str(), long(value.length()));
187 } else if (row == read) {
188 std::size_t temp_len;
189 stream.read(reinterpret_cast<char *>(&temp_len), sizeof(std::size_t));
190 char *tvalue = new char[temp_len + 1];
191 stream.read(tvalue, long(temp_len));
192 tvalue[temp_len] = '\0'; // null 'end of string' character
193 value = tvalue;
194 delete[] tvalue;
195 } else {
196 std::cout << "\nFAIL 55 in FRW\n";
197 }
198}
199
200} // namespace IO::FRW
File read/write utilities: text parsing and binary I/O.
Definition FRW_fileReadWrite.hpp:23
std::pair< std::vector< double >, std::vector< double > > readFile_xy_PoV(const std::string &fname)
Reads (x, y) pairs from a file; returns a pair of vectors {xs, ys}. Lines beginning with '#',...
Definition FRW_fileReadWrite.hpp:29
void rw_binary(std::fstream &stream, RoW row, std::vector< T > &value, Types &...values)
Function (variadic): reads/writes data from/to binary file. Works for trivial (PoD) types,...
Definition FRW_fileReadWrite.hpp:134
void open_binary(std::fstream &stream, const std::string &fname, RoW row)
Opens a binary fstream for reading or writing according to row.
Definition FRW_fileReadWrite.hpp:108
bool file_exists(const std::string &fileName)
Returns true if the file at fileName exists and can be opened.
Definition FRW_fileReadWrite.hpp:123
std::string removeCommentsAndSpaces(const std::string &input)
Strips comments (#, !, //, /* *‍/), spaces, tabs, and quote characters. Lines are squashed together; ...
Definition FRW_fileReadWrite.hpp:65
void removeBlockComments(std::string &input)
Removes C-style block comments (/* ... *‍/) from a string in-place.
Definition FRW_fileReadWrite.hpp:51