GRSISort "v4.0.0.5"
An extension of the ROOT analysis Framework
Loading...
Searching...
No Matches
TUserSettings.cxx
Go to the documentation of this file.
1#include "TUserSettings.h"
2
3#include <iostream>
4#include <fstream>
5#include <sstream>
6#include <type_traits>
7#include <algorithm>
8#include <iomanip>
9
10#include "TGRSIUtilities.h"
11
12bool TUserSettings::ReadSettings(const std::string& settingsFile)
13{
14 /// Read user settings from text file.
15 /// The file is expected to have the format
16 /// parameter name: value
17 /// where parameter name is a string w/o whitespace and value is the value of the parameter
18 /// the type of the value (bool, int, double, std::string, or vectors of these types) will be determined automatically
19 /// vectors are comma separated values of one type
20 /// the default type will be std::string
21 /// any lines starting with '#' or '//' or without a colon will be ignored
22 SetName("UserSettings");
23 fSettingsFiles.push_back(settingsFile);
24
25 std::ifstream settings(settingsFile);
26
27 if(!settings.is_open()) {
28 std::cerr << "Failed to open user settings file '" << settingsFile << "'!" << std::endl;
29 return false;
30 }
31
32 std::string line;
33 while(std::getline(settings, line)) {
34 // skip lines with too few character, starting with '#' or "//", or w/o colon
35 if(line.length() < 3) { continue; } // need at least three characters
36 if(line[0] == '#') { continue; }
37 if(line[0] == '/' && line[1] == '/') { continue; }
38 auto colon = line.find(':');
39 if(colon == std::string::npos) { continue; }
40 // split line at colon
41 auto name = line.substr(0, colon);
42 auto value = line.substr(colon + 1);
43 // remove leading and trailing whitespace
44 trim(value);
45
46 // check if this is a comma separated list of values
47 if(value.find(',') != std::string::npos) {
48 std::istringstream valueStream(value);
49 while(std::getline(valueStream, line, ',')) {
50 trim(line);
51 ParseValue(name, line, true);
52 }
53 } else {
54 ParseValue(name, value, false);
55 }
56 }
57
58 return true;
59}
60
61void TUserSettings::ParseValue(const std::string& name, const std::string& value, bool vector)
62{
63 // try and parse as integer, if pos is equal to the length of the string we were successful:
64 // add it to the map and go to the next line
65 size_t pos = 0;
66 try {
67 auto intVal = std::stoi(value, &pos);
68 if(pos == value.length()) {
69 if(!vector) {
70 fInt[name] = intVal;
71 } else {
72 fIntVector[name].push_back(intVal);
73 }
74 return;
75 }
76 } catch(std::invalid_argument& e) {
77 // do nothing, we failed to parse the input as integer, just go on to the next type
78 }
79
80 // try and parse as double, if pos is equal to the length of the string we were successful:
81 // add it to the map and go to the next line
82 try {
83 auto doubleVal = std::stod(value, &pos);
84 if(pos == value.length()) {
85 if(!vector) {
86 fDouble[name] = doubleVal;
87 } else {
88 fDoubleVector[name].push_back(doubleVal);
89 }
90 return;
91 }
92 } catch(std::invalid_argument& e) {
93 // do nothing, we failed to parse the input as double, just go on to the next type
94 }
95
96 // try and parse as bool: convert a copy to lower case and use stringstream with std::boolalpha
97 std::string copy = value;
98 std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower);
99 bool boolVal = false;
100 std::istringstream str(copy);
101 str >> std::boolalpha >> boolVal;
102 if(str.good()) {
103 if(!vector) {
104 fBool[name] = boolVal;
105 } else {
106 fBoolVector[name].push_back(boolVal);
107 }
108 return;
109 }
110
111 // trying to parse as integer, double, or bool failed, so we assume it's a string and just add it to the map
112 if(!vector) {
113 fString[name] = value;
114 } else {
115 fStringVector[name].push_back(value);
116 }
117}
118
119bool TUserSettings::GetBool(const std::string& parameter, bool quiet) const
120{
121 try {
122 return fBool.at(parameter);
123 } catch(std::out_of_range& e) {
124 if(!quiet) {
125 std::cout << "Failed to find \"" << parameter << "\" in boolean map" << std::endl;
126 Print();
127 }
128 throw e;
129 }
130}
131
132int TUserSettings::GetInt(const std::string& parameter, bool quiet) const
133{
134 try {
135 return fInt.at(parameter);
136 } catch(std::out_of_range& e) {
137 if(!quiet) {
138 std::cout << "Failed to find \"" << parameter << "\" in integer map" << std::endl;
139 Print();
140 }
141 throw e;
142 }
143}
144
145double TUserSettings::GetDouble(const std::string& parameter, bool quiet) const
146{
147 try {
148 return fDouble.at(parameter);
149 } catch(std::out_of_range& e) {
150 if(!quiet) {
151 std::cout << "Failed to find \"" << parameter << "\" in double map" << std::endl;
152 Print();
153 }
154 throw e;
155 }
156}
157
158std::string TUserSettings::GetString(const std::string& parameter, bool quiet) const
159{
160 try {
161 return fString.at(parameter);
162 } catch(std::out_of_range& e) {
163 if(!quiet) {
164 std::cout << "Failed to find \"" << parameter << "\" in string map" << std::endl;
165 Print();
166 }
167 throw e;
168 }
169}
170
171std::vector<bool> TUserSettings::GetBoolVector(const std::string& parameter, bool quiet) const
172{
173 try {
174 return fBoolVector.at(parameter);
175 } catch(std::out_of_range& e) {
176 if(!quiet) {
177 std::cout << "Failed to find \"" << parameter << "\" in boolean vector map" << std::endl;
178 Print();
179 }
180 throw e;
181 }
182}
183
184std::vector<int> TUserSettings::GetIntVector(const std::string& parameter, bool quiet) const
185{
186 try {
187 return fIntVector.at(parameter);
188 } catch(std::out_of_range& e) {
189 if(!quiet) {
190 std::cout << "Failed to find \"" << parameter << "\" in integer vector map" << std::endl;
191 Print();
192 }
193 throw e;
194 }
195}
196
197std::vector<double> TUserSettings::GetDoubleVector(const std::string& parameter, bool quiet) const
198{
199 try {
200 return fDoubleVector.at(parameter);
201 } catch(std::out_of_range& e) {
202 if(!quiet) {
203 std::cout << "Failed to find \"" << parameter << "\" in double vector map" << std::endl;
204 Print();
205 }
206 throw e;
207 }
208}
209
210std::vector<std::string> TUserSettings::GetStringVector(const std::string& parameter, bool quiet) const
211{
212 try {
213 return fStringVector.at(parameter);
214 } catch(std::out_of_range& e) {
215 if(!quiet) {
216 std::cout << "Failed to find \"" << parameter << "\" in string vector map" << std::endl;
217 Print();
218 }
219 throw e;
220 }
221}
222
223void TUserSettings::Print(Option_t*) const
224{
225 std::cout << "Settings read from";
226 for(const auto& file : fSettingsFiles) { std::cout << " " << file; }
227 std::cout << ":" << std::endl;
228 if(!fBool.empty()) { std::cout << "---------- booleans ----------" << std::endl; }
229 for(const auto& val : fBool) {
230 std::cout << std::boolalpha << val.first << ": " << val.second << std::endl;
231 }
232 if(!fInt.empty()) { std::cout << "---------- integers ----------" << std::endl; }
233 for(const auto& val : fInt) {
234 std::cout << val.first << ": " << val.second << std::endl;
235 }
236 if(!fDouble.empty()) { std::cout << "---------- doubles ----------" << std::endl; }
237 for(const auto& val : fDouble) {
238 std::cout << val.first << ": " << val.second << std::endl;
239 }
240 if(!fString.empty()) { std::cout << "---------- strings ----------" << std::endl; }
241 for(const auto& val : fString) {
242 std::cout << val.first << ": " << val.second << std::endl;
243 }
244 if(!fBoolVector.empty()) { std::cout << "---------- boolean vectors ----------" << std::endl; }
245 for(const auto& val : fBoolVector) {
246 std::cout << std::boolalpha << val.first << ": ";
247 for(const auto& item : val.second) {
248 std::cout << item << " ";
249 }
250 std::cout << std::endl;
251 }
252 if(!fIntVector.empty()) { std::cout << "---------- integer vectors ----------" << std::endl; }
253 for(const auto& val : fIntVector) {
254 std::cout << val.first << ": ";
255 for(const auto& item : val.second) {
256 std::cout << item << " ";
257 }
258 std::cout << std::endl;
259 }
260 if(!fDoubleVector.empty()) { std::cout << "---------- double vectors ----------" << std::endl; }
261 for(const auto& val : fDoubleVector) {
262 std::cout << val.first << ": ";
263 for(const auto& item : val.second) {
264 std::cout << item << " ";
265 }
266 std::cout << std::endl;
267 }
268 if(!fStringVector.empty()) { std::cout << "---------- string vectors ----------" << std::endl; }
269 for(const auto& val : fStringVector) {
270 std::cout << val.first << ": ";
271 for(const auto& item : val.second) {
272 std::cout << item << " ";
273 }
274 std::cout << std::endl;
275 }
276}
void trim(std::string &line, const std::string &trimChars=" \f\n\r\t\v")
void Print(Option_t *opt="") const override
std::map< std::string, double > fDouble
std::map< std::string, std::vector< bool > > fBoolVector
std::vector< double > GetDoubleVector(const std::string &parameter, bool quiet=false) const
std::string GetString(const std::string &parameter, bool quiet=false) const
std::vector< std::string > GetStringVector(const std::string &parameter, bool quiet=false) const
std::map< std::string, int > fInt
bool GetBool(const std::string &parameter, bool quiet=false) const
std::vector< bool > GetBoolVector(const std::string &parameter, bool quiet=false) const
std::vector< int > GetIntVector(const std::string &parameter, bool quiet=false) const
std::map< std::string, std::vector< std::string > > fStringVector
std::map< std::string, bool > fBool
std::vector< std::string > fSettingsFiles
std::map< std::string, std::vector< int > > fIntVector
std::map< std::string, std::vector< double > > fDoubleVector
int GetInt(const std::string &parameter, bool quiet=false) const
std::map< std::string, std::string > fString
double GetDouble(const std::string &parameter, bool quiet=false) const
bool ReadSettings(const std::string &settingsFile)
void ParseValue(const std::string &name, const std::string &value, bool vector)