JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwParameterFile.h
Go to the documentation of this file.
1/*!
2 * \file QwParameterFile.h
3 * \brief Parameter file parsing and management
4 * \author P. M. King
5 * \date 2007-05-08
6 */
7
8#pragma once
9
10// System headers
11#include <vector>
12#include <iostream>
13#include <sstream>
14#include <fstream>
15#include <memory>
16#include <string>
17#include <map>
18#include <set>
19#include <filesystem>
20namespace fs = std::filesystem;
21
22// ROOT headers
23#include "Rtypes.h"
24#include "TString.h"
25#include "TRegexp.h"
26#include "TObjArray.h"
27#include "TObjString.h"
28#include "TMacro.h"
29#include "TList.h"
30
31// Boost headers
32#include "boost/lexical_cast.hpp"
33using boost::lexical_cast;
34
35// Qweak headers
36#include "QwLog.h"
37
38/**
39 * \class QwParameterFile
40 * \ingroup QwAnalysis
41 * \brief Configuration file parser with flexible tokenization and search capabilities
42 *
43 * Provides parsing of configuration files with support for comments, section
44 * headers, variable substitution, file inclusion (append), and configurable
45 * token separators. Includes search path management and run-number-based
46 * parameter file selection. Used throughout the framework for loading
47 * detector maps, cut parameters, and subsystem configurations.
48 */
50
51 public:
52
53 static UInt_t GetUInt(const TString &varvalue);
54
55 public:
56
57 QwParameterFile(const std::string& filename);
58 QwParameterFile(const std::stringstream& stream);
59 virtual ~QwParameterFile() { };
60
61 /// Access the streambuf pointer in the same way as on a std::ifstream
62 std::streambuf* rdbuf() const {return fStream.rdbuf(); };
63
64 /// Add a directory to the search path
65 static void AppendToSearchPath(const TString& searchdir);
66
67 /// Set the current run number for looking up the appropriate parameter file
68 static void SetCurrentRunNumber(const UInt_t runnumber) { fCurrentRunNumber = runnumber; };
69
70 /// Set various sets of special characters
71 void SetCommentChars(const std::string value) { fCommentChars = value; };
72 void SetWhitespaceChars(const std::string value) { fWhitespaceChars = value; };
73 void SetTokenSepChars(const std::string value) { fTokenSepChars = value; };
74 void SetSectionChars(const std::string value) { fSectionChars = value; };
75 void SetModuleChars(const std::string value) { fModuleChars = value; };
76
77 Bool_t ReadNextLine() {
78 fCurrentPos = 0;
79 std::string tmp;
80 return ReadNextLine(tmp);
81 };
82 Bool_t ReadNextLine(std::string &varvalue) {
83 Bool_t status = kFALSE;
84 if (fBeGreedy) status = ReadNextLine_Greedy(varvalue);
85 else status = ReadNextLine_Single(varvalue);
86 return status;
87 }
88 Bool_t ReadNextLine_Greedy(std::string &varvalue);
89 Bool_t ReadNextLine_Single(std::string &varvalue) {
90 fCurrentPos = 0;
91 if (! getline(fStream, fLine))
92 // No next line
93 return 0;
94 else {
95 // Copy next line
96 varvalue = fLine;
97 // Allow 'append'
98 std::string tmpname, tmpvalue;
99 if (HasVariablePair(" ",tmpname,tmpvalue)) {
100 if (tmpname == "append") {
101 // Test for recursion in file nesting
102 static int nested_depth = 0;
103 if (nested_depth++ > 5) {
104 std::cout << "Parameter file recursion not allowed!" << std::endl;
105 return 0;
106 }
107 // Stream nested file into this file
108 QwParameterFile nested_file(tmpvalue.c_str());
109 fStream << nested_file.rdbuf();
110 // Read line from appended file
111 return ReadNextLine(varvalue);
112 }
113 }
114 return 1;
115 }
116 };
117
118 void TrimWhitespace(TString::EStripType head_tail = TString::kBoth);
119 void TrimComment(const char commentchar);
120 void TrimComment(const std::string& commentchars);
122 void TrimSectionHeader();
123 void TrimModuleHeader();
124
125 TString LastString(TString in, char* delim);
126 TString GetParameterFileContents();
127
128 Bool_t LineIsEmpty(){return fLine.empty();};
129 Bool_t IsEOF(){ return fStream.eof();};
130
131 /// \brief Get next token as a string
132 std::string GetNextToken(const std::string& separatorchars);
133 std::string GetNextToken() { return GetNextToken(fTokenSepChars); };
134
135 /// Get next token into specific type
136 template <typename T>
140
141 std::string GetLine() { return fLine; };
142 void AddLine(const std::string& line) { fStream << line << std::endl; };
143
144 void RewindToFileStart() { fStream.clear(); fStream.seekg(0, std::ios::beg); };
146
147 Bool_t HasValue(TString& vname);
148
149 Bool_t HasVariablePair(const std::string& separatorchars, std::string& varname, std::string& varvalue);
150 Bool_t HasVariablePair(const std::string& separatorchars, TString& varname, TString& varvalue);
151
152 Bool_t FileHasVariablePair(const std::string& separatorchars, const std::string& varname, std::string& varvalue);
153 Bool_t FileHasVariablePair(const std::string& separatorchars, const TString& varname, TString& varvalue);
154 template <typename T>
155 Bool_t FileHasVariablePair(const std::string& separatorchars, const std::string& varname, T& varvalue) {
156 std::string strvalue;
157 Bool_t status = FileHasVariablePair(separatorchars, varname, strvalue);
158 if (status){
159 varvalue = ConvertValue<T>(strvalue);
160 }
161 return status;
162 }
163
164 Bool_t LineHasSectionHeader();
165 Bool_t LineHasSectionHeader(std::string& secname);
166 Bool_t LineHasSectionHeader(TString& secname);
167
168 Bool_t LineHasModuleHeader();
169 Bool_t LineHasModuleHeader(std::string& secname);
170 Bool_t LineHasModuleHeader(TString& secname);
171
172 Bool_t FileHasSectionHeader(const std::string& secname);
173 Bool_t FileHasSectionHeader(const TString& secname);
174
175 Bool_t FileHasModuleHeader(const std::string& secname);
176 Bool_t FileHasModuleHeader(const TString& secname);
177
178 /// \brief Skips from the beginning of the section
179 /// 'secname' until the first section that does not
180 /// have that name.
181 Bool_t SkipSection(std::string secname);
182
183 /// \brief Rewinds to the start and read until it finds next section header
184 std::unique_ptr<QwParameterFile> ReadSectionPreamble();
185 std::unique_ptr<QwParameterFile> ReadUntilNextSection(const bool add_current_line = false);
186 std::unique_ptr<QwParameterFile> ReadNextSection(std::string &secname, const bool keep_header = false);
187 std::unique_ptr<QwParameterFile> ReadNextSection(TString &secname, const bool keep_header = false);
188 std::unique_ptr<QwParameterFile> ReadNextSection(const bool keep_header = false) {
189 std::string dummy;
190 return ReadNextSection(dummy, keep_header);
191 };
192
193 /// \brief Rewinds to the start and read until it finds next module header
194 std::unique_ptr<QwParameterFile> ReadModulePreamble();
195 std::unique_ptr<QwParameterFile> ReadUntilNextModule(const bool add_current_line = false);
196 std::unique_ptr<QwParameterFile> ReadNextModule(std::string &secname, const bool keep_header = false);
197 std::unique_ptr<QwParameterFile> ReadNextModule(TString &secname, const bool keep_header = false);
198 std::unique_ptr<QwParameterFile> ReadNextModule(const bool keep_header = false) {
199 std::string dummy;
200 return ReadNextModule(dummy, keep_header);
201 };
202
203 friend std::ostream& operator<< (std::ostream& stream, const QwParameterFile& file);
204
205
206 const TString GetParamFilename() {return fBestParamFileName;};
208
209 const std::pair<TString, TString> GetParamFileNameContents() {
210 return std::pair<TString, TString>(GetParamFilename(), GetParameterFileContents());
211 };
212
213 void SetParamFilename();
214
217
218 void AddBreakpointKeyword(std::string keyname);
219
220 void Close() { fFile.close();};
221
222 Bool_t HasNewPairs(){
223 Bool_t status = fHasNewPairs;
224 if (fHasNewPairs) fHasNewPairs=kFALSE;
225 return status;
226 };
227
228 template <typename T>
229 Bool_t ReturnValue(const std::string keyname, T &retvalue){
230 std::string value;
231 Bool_t status = GetKeyValue(keyname, value);
232 if (status){
233 retvalue = ConvertValue<T>(value);
234 }
235 return status;
236 }
237 template <typename T>
238 Bool_t PopValue(const std::string keyname, T &retvalue){
239 std::string value;
240 Bool_t status = GetKeyValue(keyname, value, kTRUE);
241 if (status){
242 retvalue = ConvertValue<T>(value);
243 }
244 return status;
245 };
246
247
248
249 protected:
250 void Trim(const std::string& chars, std::string& token, TString::EStripType head_tail = TString::kBoth);
251 void TrimWhitespace(std::string &token, TString::EStripType head_tail);
252
253 public:
254 /// Convert string value into specific type
255 template <typename T>
256 T ConvertValue(const std::string& value) {
257 T retvalue;
258 if (value.size() == 0) {
259 retvalue = 0; // and pray
260 } else {
261 std::istringstream stream1;
262 stream1.str(value);
263 stream1 >> retvalue;
264 }
265 return retvalue;
266 }
267
268 private:
269
270 /// Find the first file in a directory that conforms to the run label
271 int FindFile(const fs::path& dir_path, // in this directory,
272 const std::string& file_stem, // search for this stem,
273 const std::string& file_ext, // search for this extension,
274 fs::path& path_found); // placing path here if found
275
276 /// Open a file
277 bool OpenFile(const fs::path& path_found);
278 // TString fCurrentSecName; // Stores the name of the current section read
279 // TString fCurrentModuleName; // Stores the name of the current module read
282
283 public:
284
285 /// \brief Parse a range of integers as #:# where either can be missing
286 static std::pair<int,int> ParseIntRange(const std::string& separatorchars, const std::string& range);
287
288 /// \brief Parse an integer as #[kM] with optional metric scale factor
289 static int ParseInt(const std::string& value);
290
291 protected:
292
293 // List of search paths
294 static std::vector<fs::path> fSearchPaths;
295
296 // Current run number
297 static UInt_t fCurrentRunNumber;
298
299 // Default comment, whitespace, section, module characters
300 static const std::string kDefaultCommentChars;
301 static const std::string kDefaultWhitespaceChars;
302 static const std::string kDefaultTokenSepChars;
303 static const std::string kDefaultSectionChars;
304 static const std::string kDefaultModuleChars;
305
306 // Local comment, whitespace, section, module characters
307 std::string fCommentChars;
308 std::string fWhitespaceChars;
309 std::string fTokenSepChars;
310 std::string fSectionChars;
311 std::string fModuleChars;
312
313
314 // File and stream
315 const std::string fFilename;
316 std::ifstream fFile;
317 std::stringstream fStream;
318
319 // Current line and position
320 std::string fLine; /// Internal line storage
321 size_t fCurrentPos; /// Current position in the line
322
323 protected:
324
325 Bool_t GetKeyValue(const std::string keyname, std::string &retvalue,
326 Bool_t should_erase = kFALSE){
327 Bool_t status = kFALSE;
328 std::map<std::string,std::string>::iterator it;
329 it = fKeyValuePair.find(keyname);
330 if (it != fKeyValuePair.end()) {
331 status = kTRUE;
332 retvalue = (*it).second;
333 if (should_erase){
334 fKeyValuePair.erase(it);
335 }
336 }
337 return status;
338 }
339
340
341 Bool_t fBeGreedy;
342 std::set<std::string> fBreakpointWords;
343 std::map<std::string, std::string> fKeyValuePair;
345
346 private:
347
348 // Private constructor
360
361 // Private copy constructor
373
374 // Set to end of file
375 void SetEOF() { fStream.setstate(std::ios::eofbit); };
376
377}; // class QwParameterFile
378
379
380template <>
382 return GetNextToken();
383}
384
385template <>
386inline UInt_t QwParameterFile::ConvertValue<UInt_t>(const std::string& value) {
387 return GetUInt(value);
388}
389
390template <>
391inline std::string QwParameterFile::ConvertValue<std::string>(const std::string& value) {
392 return value;
393}
394
395template <>
396inline bool QwParameterFile::ConvertValue<bool>(const std::string& value) {
397 bool retvalue;
398 std::string str(value);
399 std::transform(str.begin(), str.end(), str.begin(), ::tolower);
400 std::istringstream stream1(str);
401 if (isalpha(str[0]))
402 stream1 >> std::boolalpha >> retvalue;
403 else
404 stream1 >> retvalue;
405 return retvalue;
406}
407
408template <>
409inline TString QwParameterFile::ConvertValue<TString>(const std::string& value) {
410 return TString(value.c_str());
411}
A logfile class, based on an identical class in the Hermes analyzer.
Configuration file parser with flexible tokenization and search capabilities.
size_t fCurrentPos
Internal line storage.
Bool_t LineHasSectionHeader()
void SetWhitespaceChars(const std::string value)
const TString GetParamFilenameAndPath()
static const std::string kDefaultWhitespaceChars
const TString GetParamFilename()
void SetTokenSepChars(const std::string value)
Bool_t ReadNextLine_Single(std::string &varvalue)
std::string GetNextToken()
std::map< std::string, std::string > fKeyValuePair
std::unique_ptr< QwParameterFile > ReadNextSection(const bool keep_header=false)
static int ParseInt(const std::string &value)
Parse an integer as #[kM] with optional metric scale factor.
std::stringstream fStream
static const std::string kDefaultTokenSepChars
Bool_t LineHasModuleHeader()
static void AppendToSearchPath(const TString &searchdir)
Add a directory to the search path.
T GetTypedNextToken()
Get next token into specific type.
TString GetParameterFileContents()
bool OpenFile(const fs::path &path_found)
Open a file.
virtual ~QwParameterFile()
Bool_t HasValue(TString &vname)
void SetModuleChars(const std::string value)
std::unique_ptr< QwParameterFile > ReadUntilNextModule(const bool add_current_line=false)
static void SetCurrentRunNumber(const UInt_t runnumber)
Set the current run number for looking up the appropriate parameter file.
Bool_t PopValue(const std::string keyname, T &retvalue)
static const std::string kDefaultSectionChars
QwParameterFile(const QwParameterFile &input)
Bool_t ReadNextLine_Greedy(std::string &varvalue)
std::unique_ptr< QwParameterFile > ReadNextModule(std::string &secname, const bool keep_header=false)
void SetSectionChars(const std::string value)
Bool_t FileHasSectionHeader(const std::string &secname)
void TrimWhitespace(TString::EStripType head_tail=TString::kBoth)
Bool_t HasVariablePair(const std::string &separatorchars, std::string &varname, std::string &varvalue)
std::string fModuleChars
std::set< std::string > fBreakpointWords
int FindFile(const fs::path &dir_path, const std::string &file_stem, const std::string &file_ext, fs::path &path_found)
Find the first file in a directory that conforms to the run label.
void SetCommentChars(const std::string value)
Set various sets of special characters.
TString LastString(TString in, char *delim)
std::streambuf * rdbuf() const
Access the streambuf pointer in the same way as on a std::ifstream.
Bool_t SkipSection(std::string secname)
Skips from the beginning of the section 'secname' until the first section that does not have that nam...
std::string GetLine()
void AddLine(const std::string &line)
static std::pair< int, int > ParseIntRange(const std::string &separatorchars, const std::string &range)
Parse a range of integers as #:# where either can be missing.
std::string fSectionChars
std::string fWhitespaceChars
void AddBreakpointKeyword(std::string keyname)
std::ifstream fFile
QwParameterFile(const std::string &filename)
static UInt_t fCurrentRunNumber
static const std::string kDefaultCommentChars
TString fBestParamFileNameAndPath
static UInt_t GetUInt(const TString &varvalue)
const std::pair< TString, TString > GetParamFileNameContents()
friend std::ostream & operator<<(std::ostream &stream, const QwParameterFile &file)
Bool_t FileHasModuleHeader(const std::string &secname)
std::string fTokenSepChars
const std::string fFilename
std::unique_ptr< QwParameterFile > ReadModulePreamble()
Rewinds to the start and read until it finds next module header.
std::unique_ptr< QwParameterFile > ReadNextModule(const bool keep_header=false)
Bool_t FileHasVariablePair(const std::string &separatorchars, const std::string &varname, T &varvalue)
Bool_t ReadNextLine(std::string &varvalue)
void Trim(const std::string &chars, std::string &token, TString::EStripType head_tail=TString::kBoth)
std::string fCommentChars
std::unique_ptr< QwParameterFile > ReadUntilNextSection(const bool add_current_line=false)
Bool_t ReturnValue(const std::string keyname, T &retvalue)
T ConvertValue(const std::string &value)
Convert string value into specific type.
Bool_t GetKeyValue(const std::string keyname, std::string &retvalue, Bool_t should_erase=kFALSE)
Current position in the line.
static const std::string kDefaultModuleChars
std::unique_ptr< QwParameterFile > ReadSectionPreamble()
Rewinds to the start and read until it finds next section header.
Bool_t FileHasVariablePair(const std::string &separatorchars, const std::string &varname, std::string &varvalue)
static std::vector< fs::path > fSearchPaths
std::unique_ptr< QwParameterFile > ReadNextSection(std::string &secname, const bool keep_header=false)