LHAPDF  6.5.5
Info.h
1 // -*- C++ -*-
2 //
3 // This file is part of LHAPDF
4 // Copyright (C) 2012-2024 The LHAPDF collaboration (see AUTHORS for details)
5 //
6 #pragma once
7 #ifndef LHAPDF_Info_H
8 #define LHAPDF_Info_H
9 
10 #include "LHAPDF/Utils.h"
11 #include "LHAPDF/Paths.h"
12 #include "LHAPDF/Exceptions.h"
13 
14 namespace LHAPDF {
15 
16 
17  /// Get the singleton global configuration object
18  ///
19  /// @todo Move this out of Info. To Factories.h or SystemConfig.h?
20  ///
21  /// The global config is populated by reading from lhapdf.conf if it is
22  /// found in the search paths.
23  // class Info;
24  // Info& config();
25 
26 
27 
28  /// Metadata base class for PDFs, PDF sets, or global configuration
29  class Info {
30  public:
31 
32  /// Default constructor
33  Info() { }
34 
35  /// Constructor
36  Info(const std::string& path) {
37  load(path);
38  }
39 
40  /// Virtual destructor to allow inheritance
41  virtual ~Info() { }
42 
43 
44  /// @name Loading info from YAML files
45  ///@{
46 
47  /// Populate this info object from the specified YAML file path.
48  ///
49  /// This function may be called several times to read metadata from several
50  /// YAML source files. Values for existing keys will be overwritten.
51  void load(const std::string& filepath);
52 
53  ///@}
54 
55 
56  /// @name General metadata accessors
57  ///@{
58 
59  // /// Get all metadata as a map
60  // const std::map<std::string, std::string>& metadata() const {
61  // return _metadict;
62  // }
63 
64  // /// Get all metadata as a map (non-const)
65  // std::map<std::string, std::string>& metadata() {
66  // return _metadict;
67  // }
68 
69  /// Get the keys defined on this specific object
71  std::vector<std::string> rtn;
72  rtn.reserve(_metadict.size());
73  for (const auto& kv : _metadict) rtn.push_back(kv.first);
74  return rtn;
75  }
76 
77  /// Get the keys defined on this object or cascaded into it
78  ///
79  /// The default implementation is equivalent to keys_local(). This is
80  /// appropriate for Config, but should be overridden for more specific info
81  /// types.
82  std::vector<std::string> keys() const {
83  return keys_local();
84  }
85 
86  /// Is a value defined for the given key on this specific object?
87  bool has_key_local(const std::string& key) const {
88  return _metadict.find(key) != _metadict.end();
89  }
90 
91  /// Can this object return a value for the given key?
92  ///
93  /// The given key may be defined non-locally, in which case the cascading
94  /// member -> set -> config info lookup is needed. These are implemented
95  /// using has_key_local() and metadata_local().
96  ///
97  /// The default implementation is equivalent to has_key_local(). This is
98  /// appropriate for Config, but should be overridden for more specific info
99  /// types.
100  virtual bool has_key(const std::string& key) const {
101  return has_key_local(key);
102  }
103 
104 
105  /// Retrieve a metadata string by key name, as defined on this specific object
106  const std::string& get_entry_local(const std::string& key) const {
107  if (has_key_local(key)) return _metadict.find(key)->second;
108  throw MetadataError("Metadata for key: " + key + " not found.");
109  }
110 
111  /// Retrieve a metadata string by key name
112  ///
113  /// The given key may be defined non-locally, in which case the cascading
114  /// member -> set -> config info lookup is needed. These are implemented
115  /// using has_key_local() and get_entry_local().
116  ///
117  /// The default implementation is equivalent to get_entry_local(). This is
118  /// appropriate for Config, but should be overridden for more specific info types.
119  virtual const std::string& get_entry(const std::string& key) const {
120  return get_entry_local(key);
121  }
122 
123 
124  /// Retrieve a metadata string by key name, with a default fallback
125  virtual const std::string& get_entry(const std::string& key, const std::string& fallback) const {
126  try {
127  return get_entry(key);
128  } catch (...) {
129  return fallback;
130  }
131  }
132 
133 
134  /// Retrieve a metadata entry by key name, with an inline type cast
135  ///
136  /// Specialisations are defined below for unpacking of comma-separated lists
137  /// of strings, ints, and doubles.
138  template <typename T>
139  T get_entry_as(const std::string& key) const {
140  const string& s = get_entry(key);
141  return lexical_cast<T>(s);
142  }
143 
144 
145  /// Retrieve a metadata entry by key name, with an inline type cast and default fallback
146  template <typename T>
147  T get_entry_as(const std::string& key, const T& fallback) const {
148  try {
149  return get_entry_as<T>(key);
150  } catch (...) {
151  return fallback;
152  }
153  }
154 
155 
156  /// Set a keyed value entry
157  template <typename T>
158  void set_entry(const std::string& key, const T& val) {
159  _metadict[key] = to_str(val);
160  }
161 
162  ///@}
163 
164 
165  protected:
166 
167  /// The string -> string native metadata storage container
169 
170  };
171 
172 
173 
174  /// @name Info metadata function template specialisations
175  ///@{
176 
177  template <>
178  inline bool Info::get_entry_as(const std::string& key) const {
179  const string& s = get_entry(key);
180  try {
181  bool rtn = lexical_cast<bool>(s);
182  return rtn;
183  } catch (...) {
184  if (s == "true" || s == "on" || s == "yes") return true;
185  if (s == "false" || s == "off" || s == "no") return false;
186  }
187  throw MetadataError("'" + s + "' is not a valid string for conversion to bool type");
188  }
189 
190  template <>
191  inline std::vector<std::string> Info::get_entry_as(const std::string& key) const {
192  static const string delim = ",";
193  string strval = trim(get_entry(key));
194  // cout << "@@ " << strval << endl;
195  if (startswith(strval, "[")) strval = strval.substr(1, strval.size()-1);
196  if (endswith(strval, "]")) strval = strval.substr(0, strval.size()-1);
197  // cout << "## " << strval << endl;
198  return split(strval, delim);
199  }
200 
201  template <>
202  inline std::vector<int> Info::get_entry_as(const std::string& key) const {
203  const vector<string> strs = get_entry_as< vector<string> >(key);
204  vector<int> rtn;
205  rtn.reserve(strs.size());
206  for (const string& s : strs) rtn.push_back( lexical_cast<int>(s) );
207  assert(rtn.size() == strs.size());
208  return rtn;
209  }
210 
211  template <>
212  inline std::vector<double> Info::get_entry_as(const std::string& key) const {
213  const vector<string> strs = get_entry_as< vector<string> >(key);
214  vector<double> rtn;
215  rtn.reserve(strs.size());
216  for (const string& s : strs) rtn.push_back( lexical_cast<double>(s) );
217  assert(rtn.size() == strs.size());
218  return rtn;
219  }
220 
221  ///@}
222 
223 
224 }
225 #endif