StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
FwdTrackerConfig.h
1 #ifndef FWD_TRACKER_CONFIG_H
2 #define FWD_TRACKER_CONFIG_H
3 
4 #include "St_base/StMessMgr.h"
5 
6 #include "TXMLEngine.h"
7 #include "TString.h"
8 
9 #include <string>
10 #include <iostream>
11 #include <sstream>
12 #include <vector>
13 #include <map>
14 #include <algorithm>
15 
16 // Class provides an interface for reading configuration from an XML file
18 protected:
19 
20  static const std::string valDNE; // used for nodes that DNE
21  static const std::string pathDelim; // separate node levels
22  static const std::string attrDelim; // separate attributes on nodes
23 
24  bool mErrorParsing = false;
25  // read only map of the config, read with get<> functions
26  std::map<std::string, std::string> mNodes;
27  static std::stringstream sstr; // reused for string to numeric conversion
28 
36  size_t pathCount( const std::string path ){
37  size_t index = 1;
38  std::string p = path + TString::Format( "[%zu]", index ).Data();
39  while ( mNodes.count( p ) ){
40  index ++;
41  p = path + TString::Format( "[%zu]", index ).Data();
42  }
43  return index;
44  }
45 
54  void mapFile(TXMLEngine &xml, XMLNodePointer_t node, Int_t level, std::string path = "") {
55  using namespace std;
56  // add the path delimeter above top level
57  if ( !path.empty() ) path += FwdTrackerConfig::pathDelim;
58 
59  // we skip the root node to maintain consistency with original XmlConfig
60  if ( level > 1)
61  path += xml.GetNodeName(node);
62 
63  // get the node name and content if it exists
64  const string node_name = xml.GetNodeName(node);
65  const string node_content = xml.GetNodeContent(node) != nullptr ? xml.GetNodeContent(node) : FwdTrackerConfig::valDNE;
66 
67  // be careful about repeated nodes
68  if ( mNodes.count( path ) == 0 ) {
69  mNodes[ path ] = node_content;
70  } else { // add an array index if more than one
71  size_t index = pathCount( path );
72  path += TString::Format( "[%zu]", index ).Data();
73  mNodes[ path ] = node_content;
74  }
75 
76  // loop through attributes of this node
77  XMLAttrPointer_t attr = xml.GetFirstAttr(node);
78  while (attr != 0) {
79 
80  // get the attribute name and value if exists
81  const string attr_name = xml.GetAttrName(attr);
82  const string attr_val = xml.GetAttrValue(attr) != nullptr ? xml.GetAttrValue(attr) : FwdTrackerConfig::valDNE;
83 
84  // save attributes with the attribute delim ":"
85  mNodes[ (path + FwdTrackerConfig::attrDelim + attr_name) ] = attr_val;
86  attr = xml.GetNextAttr(attr);
87  }
88 
89  // recursively get child nodes
90  XMLNodePointer_t child = xml.GetChild(node);
91  while (child != 0) {
92  mapFile(xml, child, level + 1, path);
93  child = xml.GetNext(child);
94  }
95  } // mapFile
96 public:
97 
103  static void canonize( std::string &path ) {
104  // remove whitespace
105  path.erase(std::remove_if(path.begin(), path.end(), static_cast<int(*) (int)>(std::isspace)), path.end());
106 
107  // removes "[0]" found in paths, so that the first element in a list can be accessed by index 0 or bare path
108  size_t pos = path.find( "[0]" );
109 
110  // branchless version using ternary op
111  size_t len = (pos != std::string::npos) ? 3 : 0;
112  pos = (pos != std::string::npos) ? pos : 0;
113  path.erase( pos, len ); // does nothing if "[0]" not found
114  return;
115  }
116 
122  std::string dump() const {
123  using namespace std;
124  FwdTrackerConfig::sstr.str("");
125  FwdTrackerConfig::sstr.clear();
126  for ( auto kv : mNodes ){
127  FwdTrackerConfig::sstr << "[" << kv.first << "] = " << kv.second << endl;
128  }
129  return FwdTrackerConfig::sstr.str();
130  }
131 
140  bool exists( std::string path ) const {
142  if ( 0 == mNodes.count( path ) )
143  return false;
144  return true;
145  }
146 
155  template <typename T>
156  T convert( std::string s ) const {
157  T rv;
158  FwdTrackerConfig::sstr.str("");
159  FwdTrackerConfig::sstr.clear();
160  FwdTrackerConfig::sstr << s;
161  FwdTrackerConfig::sstr >> rv;
162  return rv;
163  }
164 
172  template <typename T>
173  std::string convertTo( T v ) const {
174  FwdTrackerConfig::sstr.str("");
175  FwdTrackerConfig::sstr.clear();
176  FwdTrackerConfig::sstr << v;
177  return FwdTrackerConfig::sstr.str();
178  }
179 
180 
189  template <typename T>
190  T get( std::string path, T dv ) const {
191 
192  // return default value if path DNE
193  if ( !exists( path ) )
194  return dv;
195 
197  // convrt from string to type T and return
198  return convert<T>( mNodes.at( path ) );
199  }
200 
208  template <typename T>
209  void set( std::string path, T v ) {
211  // convrt from string to type T and return
212  mNodes[ path ] = convertTo<T>( v );
213  }
214 
223  template <typename T>
224  std::vector<T> getVector( std::string path, std::vector<T> dv ) const {
225  if ( !exists( path ) )
226  return dv;
227 
229  std::string val = mNodes.at( path );
230  // remove whitespace
231  val.erase(std::remove_if(val.begin(), val.end(), static_cast<int(*) (int)>(std::isspace) ), val.end());
232  std::vector<std::string> elems;
233 
234  // split the string by commas
235  [&]() {
236  std::stringstream ss(val);
237  std::string str;
238  while (std::getline(ss, str, ',')) {
239  elems.push_back(str);
240  }
241  }();
242 
243  // for each element, convert to type T and push into vector
244  std::vector<T> result;
245  for ( auto sv : elems ){
246  result.push_back( convert<T>( sv ) );
247  }
248  return result;
249  }
250 
257  std::vector<std::string> childrenOf( std::string path ) const {
258  using namespace std;
259  vector<string> result;
260 
261  canonize(path);
262 
263  // test a path to see if it is an attribute
264  auto is_attribute = [&](string str){
265  return ( str.find( FwdTrackerConfig::attrDelim ) != string::npos );
266  };
267 
268  for ( auto kv : mNodes ){
269  // get the first n characters of this path
270  string parent = (kv.first).substr( 0, path.length() );
271 
272  // dont add self as a child
273  if ( parent == kv.first ) continue;
274 
275  // if parent path matches query path then it is a child.
276  if ( parent == path && !is_attribute( kv.first )){
277  result.push_back( kv.first );
278  }
279  } // loop over all nodes
280 
281  return result;
282  }
283 
289 
295  FwdTrackerConfig(std::string filename) {
296  load( filename );
297  }
298 
305  void load( std::string filename, bool asString = false ) {
306  using namespace std;
307 
308  // empty the map of mNodes
309  mNodes.clear();
310 
311  // Create XML engine for parsing file
312  TXMLEngine xml;
313 
314  // Now try to parse xml file
315  XMLDocPointer_t xmldoc;
316  if (asString)
317  xmldoc = xml.ParseString(filename.c_str());
318  else
319  xmldoc = xml.ParseFile(filename.c_str());
320 
321  if (!xmldoc) { // parse failed, TODO inform of error
322  mErrorParsing = true;
323  return;
324  }
325 
326  // access to root node (should be "config")
327  XMLNodePointer_t root_node = xml.DocGetRootElement(xmldoc);
328  // build the file map for config access
329  mapFile(xml, root_node, 1);
330 
331  // Release memory before finishing
332  xml.FreeDoc(xmldoc);
333  }
334 };
335 
336 // Forward declare the templates, otherwise undefined behavior in Release builds
337 template <>
338 std::string FwdTrackerConfig::convert( std::string str ) const;
339 template <>
340 bool FwdTrackerConfig::convert( std::string str ) const;
341 template <>
342 TString FwdTrackerConfig::convert(std::string str) const;
343 template <>
344 std::string FwdTrackerConfig::get( std::string path, std::string dv ) const;
345 template <>
346 void FwdTrackerConfig::set( std::string path, std::string v );
347 template <>
348 void FwdTrackerConfig::set( std::string path, bool bv );
349 
350 #endif
FwdTrackerConfig(std::string filename)
Construct a new Fwd Tracker Config object and load a file.
std::string convertTo(T v) const
Generic conversion of type T to a string.
std::vector< std::string > childrenOf(std::string path) const
list the paths of children nodes for a given node
FwdTrackerConfig()
Constructor is noop, use load(...)
bool exists(std::string path) const
returns whether or not a path exist Either node or attribute - used to determine if default value is ...
T convert(std::string s) const
Generic conversion of type T from string override this for special conversions.
std::string dump() const
dump config to a basic string representation - mostly for debugging
std::vector< T > getVector(std::string path, std::vector< T > dv) const
Get a Vector object from config.
void load(std::string filename, bool asString=false)
Main setup routine Loads the given XML file (or string) and maps it.
void set(std::string path, T v)
Writes a value of type T to the map Uses convertTo&lt;T&gt; to convert type T to a string rep...
size_t pathCount(const std::string path)
get lowest non-existing path index assumes bare path and adds [i] until DNE starts at 1 since 0 is ch...
void mapFile(TXMLEngine &xml, XMLNodePointer_t node, Int_t level, std::string path="")
Reads an xml document and writes it into map.
T get(std::string path, T dv) const
template function for getting any type that can be converted from string via stringstream ...
static void canonize(std::string &path)
Returns a path in its cannonical form.