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