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