NameSelector.h
Go to the documentation of this file.
1 /**
2  * @file NameSelector.h
3  * @brief A class providing a selection list
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date July 24, 2015
6  * @see NameSelector.cxx
7  */
8 
9 #ifndef TEST_GEOMETRY_NAMESELECTOR_H
10 #define TEST_GEOMETRY_NAMESELECTOR_H 1
11 
12 // C/C++ standard library
13 #include <string>
14 #include <set>
15 #include <map>
16 #include <ostream>
17 #include <initializer_list>
18 
19 // ... and more in the template implementation section below
20 
21 namespace testing {
22 
23  /**
24  * @brief Manages a set of names
25  *
26  * This class contains a set of names to be "accepted" and a set of names
27  * to be "rejected". Queries on unknown names will generate a default
28  * answer that can be acceptance, rejection or an exception.
29  *
30  * The class is initialized by a list of strings following the convention
31  * detailed in ProcessItem().
32  * The default answer is set on construction, but it can be overridden to
33  * a "reject by default" using a specific identifier.
34  *
35  */
36  class NameSelector {
37 
38  public:
39  using Name_t = std::string; ///< type representing a name
40  using Names_t = std::set<Name_t>; ///< list of names
41 
42  /// Possible responses
43  typedef enum {
44  rsRejected, ///< rejected
45  rsAccepted, ///< accepted
46  rsThrow, ///< throw art::Exception (art::errors::Configuration)
48  } Response_t;
49 
50 
51  using NameList = std::initializer_list<Name_t>;
52 
53 
54  /// Constructor: an empty selector with a default answer for unknown names
55  NameSelector(Response_t default_answer = rsDefault)
56  { SetDefaultResponse(default_answer); }
57 
58  /// Constructor: Parse()s the specified items
59  template <typename LIST>
60  NameSelector(LIST const& items, Response_t default_answer = rsDefault)
61  : NameSelector(default_answer)
62  { Parse(items); }
63 
64  /// Sets the default answer for names that are not registered
65  void SetDefaultResponse(Response_t default_answer)
66  { known_names[DefaultName] = { default_answer }; }
67 
68  /**
69  * @brief Parses the names in the list and adds them to the selector
70  * @tparam LIST type of list of strings
71  * @param items the definitions to be used
72  *
73  * Specified items are processed with ProcessItem() and the current set is
74  * modified.
75  */
76  template <typename LIST>
77  void Parse(LIST const& items) { BuildNameSet(known_names, items); }
78 
79 
80  /**
81  * @brief Parses a name and adds it to the selector
82  * @param name name specification to be parsed
83  *
84  * The name is processed with ProcessItem() and the current set is modified.
85  */
86  void ParseName(Name_t name);
87 
88  /**
89  * @brief Parses a list of names and adds them to the selector
90  * @tparam NAMES Name_t-compatible types
91  * @param names the definitions to be used
92  *
93  * Specified items are processed with ProcessItem() and modify the current
94  * set.
95  */
96  template <typename... NAMES>
97  void ParseNames(NAMES... names) { AddFirstName(known_names, names...); }
98 
99  /// Erases all the names in the selector (default answer is unchanged)
101 
102  /**
103  * @brief Defines a set
104  * @tparam LIST type of list of strings
105  * @param set_name name of the set to be defined
106  * @param items the definitions to be used
107  *
108  * Specified items are processed with BuildSet(); the result is stored as
109  * a set with the specified name.
110  * If a set with that name already exists, it's replaced and the old one
111  * is lost.
112  */
113  template <typename LIST>
114  void Define(std::string set_name, LIST const& items);
115 
116  /**
117  * @brief Parses a list of names and add them to the specified definition
118  * @tparam NAMES Name_t-compatible types
119  * @param set_name name of the set to be defined
120  * @param names the definitions to be used
121  *
122  * Specified items are processed with ProcessItem(); the result is added to
123  * the set with the specified name.
124  * If a set with that name does not exist, it's created empty.
125  */
126  template <typename... NAMES>
127  void AddToDefinition(std::string set_name, NAMES... names)
128  { AddFirstName(definitions[set_name], names...); }
129 
130  /// Returns the response for the specified name (does not throw)
131  Response_t Query(Name_t name) const;
132 
133  /// Returns whether the name is accepted as good
134  bool Accepted(Name_t name) const;
135 
136  /// Returns whether the name is rejected as bad
137  bool Rejected(Name_t name) const { return !Accepted(name); }
138 
139  /// Returns the default answer for names that are not registered
140  Response_t DefaultResponse() const
141  { return known_names.find(DefaultName)->second.response; }
142 
143  /// Returns whether the name is accepted as good (alias for accept())
144  bool operator() (Name_t name) const { return Accepted(name); }
145 
146  /// Prints the configuration into a stream
147  void PrintConfiguration(std::ostream&) const;
148 
149  /// Returns a list of names that were accepted
151 
152  /// Returns a list of names that were rejected
154 
155  /// Reests the query registry
156  void ClearQueryRegistry() { query_registry.clear(); }
157 
158  //@{
159  /// Checks that no known element with valid response was left unqueried
160  bool CheckQueryRegistry() const { return DoCheckQueryRegistry(); }
161  bool CheckQueryRegistry(std::ostream& out) const
162  { return DoCheckQueryRegistry(&out); }
163  //@}
164 
165 
166  static Name_t const DefaultName; ///< name representing the default
167  static Name_t const ClearAllName; ///< name instructing to delete all names
168 
169  protected:
170 
171  /// A data structure containing how to react to a name
172  typedef struct {
173  Response_t response; ///< the response
174  } NameResponse_t;
175 
176  /// Information about known names
177  using KnownNames_t = std::map<Name_t, NameResponse_t>;
178 
179  /// Type of list of definitions
180  using Definitions_t = std::map<Name_t, KnownNames_t>;
181 
182  /// Type of query counters
183  using QueryRegistry_t = std::map<Name_t, size_t>;
184 
185  KnownNames_t known_names; ///< list of known names, with category
186 
187  Definitions_t definitions; ///< a set of definitions
188 
189  mutable QueryRegistry_t query_registry; ///< record of all the queries
190 
191  /// Returns the response for the specified name (does not register query)
192  Response_t LookupResponse(Name_t name) const;
193 
194  /**
195  * @brief Fills name_set with a list of items
196  * @tparam LIST type of container of name directives
197  * @param name_set set to be modified
198  * @param items name directives
199  *
200  * A name set is modified according to the instructions in each of the
201  * items. The items are parsed sequentially, and their order matters
202  * for the final result.
203  * Each item is processed through ProcessItem().
204  */
205  template <typename LIST>
206  void BuildNameSet(KnownNames_t& name_set, LIST const& items) const;
207 
208  /// Parses the first of the provided names, and recurs
209  template <typename... NAMES>
210  void AddFirstName
211  (KnownNames_t& name_set, Name_t name, NAMES... other_names);
212 
213  /// Adds an item to the name set, working in specified mode
214  void InsertItem
215  (KnownNames_t& name_set, Name_t item, Response_t response) const;
216 
217  /// Adds an item with response to the name set, working in specified mode
218  void InsertItem(
219  KnownNames_t& name_set, KnownNames_t::value_type item,
220  Response_t response
221  ) const;
222 
223  /**
224  * @brief Fills name_set with an item
225  * @param name_set set to be modified
226  * @param item name directive
227  *
228  * A name set is modified according to the instruction in the items.
229  * An identifier may represent either a single literal item or a set name;
230  * it can appear in two forms:
231  * - "\@identifier": always denotes a set named "identifier"
232  * - "identifier": if a set named "identifier" exists, the name
233  * represents that set; otherwise, it represents a literal item
234  * named "identifier"
235  *
236  * The directives in items are:
237  * - "identifier": the element or elements represented by the identifier
238  * replace the content of the current set
239  * - "+identifier": the element or elements represented by the identifier
240  * are added to the current set; if the identifier is a predefined set,
241  * the elements accepted in the set are added as accepted here, the ones
242  * rejected are added as rejected here
243  * - "-identifier": the element or elements represented by the identifier;
244  * if the identifier is a predefined set, the elements accepted in the
245  * set are added as rejected here, the ones rejected are added as
246  * accepted here
247  *
248  */
249  void ProcessItem(KnownNames_t& name_set, Name_t item) const;
250 
251  /// Strips set specifier and returns iterator to the definition, or end()
253 
254  /// Erases all the names in the selector (default answer is unchanged)
255  void ClearNameSet(KnownNames_t& name_set) const;
256 
257  /// Returns the list of queried names whose response is answer
258  Names_t QueriedWithStatus(Response_t answer) const;
259 
260  // Performs the actual registry check, optionally printing a message
261  bool DoCheckQueryRegistry(std::ostream* out = nullptr) const;
262 
263  /// Strips the mode specifier from item and returns the insertion mode
264  static Response_t ParseMode
265  (Name_t& item, Response_t default_answer = rsAccepted);
266 
267  }; // class NameSelector
268 
269 } // namespace testing
270 
271 
272 //------------------------------------------------------------------------------
273 //--- Template implementation
274 //---
275 
276 // C/C++ standard library
277 #include <utility> // std::move()
278 
279 //------------------------------------------------------------------------------
280 template <typename LIST>
281 void testing::NameSelector::Define(std::string set_name, LIST const& items) {
282  KnownNames_t name_set;
283  BuildNameSet(name_set, items);
284  definitions[set_name] = std::move(name_set);
285 } // testing::NameSelector::Define()
286 
287 
288 //------------------------------------------------------------------------------
289 template <typename LIST>
291  (KnownNames_t& name_set, LIST const& items) const
292 {
293  for (Name_t item: items) ProcessItem(name_set, item);
294 } // testing::NameSelector::BuildNameSet()
295 
296 
297 //------------------------------------------------------------------------------
298 namespace testing {
299  // forward declaration of specialization
300  template <>
301  void NameSelector::AddFirstName<>(KnownNames_t& name_set, Name_t name);
302 } // namespace testing
303 
304 template <typename... NAMES>
306  (KnownNames_t& name_set, Name_t name, NAMES... other_names)
307 {
308  AddFirstName(name_set, name);
309  AddFirstName(name_set, other_names...);
310 } // testing::NameSelector::AddFirstName()
311 
312 
313 //------------------------------------------------------------------------------
314 
315 #endif // TEST_GEOMETRY_NAMESELECTOR_H
static QCString name
Definition: declinfo.cpp:673
void Define(std::string set_name, LIST const &items)
Defines a set.
Definition: NameSelector.h:281
LArSoft test utilities.
std::set< Name_t > Names_t
list of names
Definition: NameSelector.h:40
bool DoCheckQueryRegistry(std::ostream *out=nullptr) const
static Response_t ParseMode(Name_t &item, Response_t default_answer=rsAccepted)
Strips the mode specifier from item and returns the insertion mode.
Definitions_t::const_iterator FindDefinition(Name_t &item) const
Strips set specifier and returns iterator to the definition, or end()
std::map< Name_t, NameResponse_t > KnownNames_t
Information about known names.
Definition: NameSelector.h:177
std::string string
Definition: nybbler.cc:12
void AddToDefinition(std::string set_name, NAMES...names)
Parses a list of names and add them to the specified definition.
Definition: NameSelector.h:127
Response_t DefaultResponse() const
Returns the default answer for names that are not registered.
Definition: NameSelector.h:140
Names_t RejectedNames() const
Returns a list of names that were rejected.
Definition: NameSelector.h:153
void BuildNameSet(KnownNames_t &name_set, LIST const &items) const
Fills name_set with a list of items.
Definition: NameSelector.h:291
bool Accepted(Name_t name) const
Returns whether the name is accepted as good.
intermediate_table::const_iterator const_iterator
void ParseNames(NAMES...names)
Parses a list of names and adds them to the selector.
Definition: NameSelector.h:97
void PrintConfiguration(std::ostream &) const
Prints the configuration into a stream.
bool operator()(Name_t name) const
Returns whether the name is accepted as good (alias for accept())
Definition: NameSelector.h:144
Response_t LookupResponse(Name_t name) const
Returns the response for the specified name (does not register query)
void AddFirstName(KnownNames_t &name_set, Name_t name, NAMES...other_names)
Parses the first of the provided names, and recurs.
Definition: NameSelector.h:306
NameSelector(LIST const &items, Response_t default_answer=rsDefault)
Constructor: Parse()s the specified items.
Definition: NameSelector.h:60
void ParseName(Name_t name)
Parses a name and adds it to the selector.
Manages a set of names.
Definition: NameSelector.h:36
A data structure containing how to react to a name.
Definition: NameSelector.h:172
Definitions_t definitions
a set of definitions
Definition: NameSelector.h:187
bool Rejected(Name_t name) const
Returns whether the name is rejected as bad.
Definition: NameSelector.h:137
Names_t AcceptedNames() const
Returns a list of names that were accepted.
Definition: NameSelector.h:150
void ProcessItem(KnownNames_t &name_set, Name_t item) const
Fills name_set with an item.
NameSelector(Response_t default_answer=rsDefault)
Constructor: an empty selector with a default answer for unknown names.
Definition: NameSelector.h:55
Response_t
Possible responses.
Definition: NameSelector.h:43
std::initializer_list< Name_t > NameList
Definition: NameSelector.h:51
std::map< Name_t, KnownNames_t > Definitions_t
Type of list of definitions.
Definition: NameSelector.h:180
void Parse(LIST const &items)
Parses the names in the list and adds them to the selector.
Definition: NameSelector.h:77
std::map< Name_t, size_t > QueryRegistry_t
Type of query counters.
Definition: NameSelector.h:183
def move(depos, offset)
Definition: depos.py:107
bool CheckQueryRegistry() const
Checks that no known element with valid response was left unqueried.
Definition: NameSelector.h:160
static Name_t const DefaultName
name representing the default
Definition: NameSelector.h:166
void ClearQueryRegistry()
Reests the query registry.
Definition: NameSelector.h:156
throw art::Exception (art::errors::Configuration)
Definition: NameSelector.h:46
KnownNames_t known_names
list of known names, with category
Definition: NameSelector.h:185
Response_t response
the response
Definition: NameSelector.h:173
Names_t QueriedWithStatus(Response_t answer) const
Returns the list of queried names whose response is answer.
void Clear()
Erases all the names in the selector (default answer is unchanged)
Definition: NameSelector.h:100
void ClearNameSet(KnownNames_t &name_set) const
Erases all the names in the selector (default answer is unchanged)
QueryRegistry_t query_registry
record of all the queries
Definition: NameSelector.h:189
static Name_t const ClearAllName
name instructing to delete all names
Definition: NameSelector.h:167
static std::vector< std::string > const names
Definition: FragmentType.hh:8
bool CheckQueryRegistry(std::ostream &out) const
Definition: NameSelector.h:161
void InsertItem(KnownNames_t &name_set, Name_t item, Response_t response) const
Adds an item to the name set, working in specified mode.
std::string Name_t
type representing a name
Definition: NameSelector.h:39
void SetDefaultResponse(Response_t default_answer)
Sets the default answer for names that are not registered.
Definition: NameSelector.h:65
Response_t Query(Name_t name) const
Returns the response for the specified name (does not throw)