Flow123d
type_selection.hh
Go to the documentation of this file.
1 /*
2  * type_selection.hh
3  *
4  * Created on: May 1, 2012
5  * Author: jb
6  */
7 
8 #ifndef TYPE_SELECTION_HH_
9 #define TYPE_SELECTION_HH_
10 
11 #include "system/exceptions.hh"
12 
13 #include "system/system.hh"
14 #include "type_base.hh"
15 
16 namespace Input {
17 namespace Type {
18 
19 using std::string;
20 
21 
22 
23 /**
24  * @brief Template for classes storing finite set of named values.
25  *
26  * The primary purpose of this class is initialization of enum variables. Since C++ provides no reflection,
27  * in particular no access to enum identifiers as strings, you has to construct the Selection object consistent with an enum you want to initialize.
28  *
29  * Similarly to Type::Record and Type::AbstractRecord the Selection class is only proxy to the actual data.
30  *
31  * Usage:
32  @code
33  enum Colors { blue, white };
34 
35  Selection colors("Colors");
36  colors.add_value(blue, "blue");
37  colors.add_value(white,"white","White color"); // with optional item description
38  colors.finish();
39  @endcode
40  *
41  *
42  * TODO: We can not guarantee full compatibility of the Selection with corresponding Enum type
43  * the Selection can have fewer values since we can not get number of values in the Enum.
44  * Therefore we either have to move under C++11, where enum classes may provide elementary
45  * reflection or have Selection of simple ints.
46  *
47  * @ingroup input_types
48  */
49 
50 class Selection : public Scalar {
51  friend class OutputBase;
52 
53 public:
54  /*
55  * Exceptions specific to this class.
56  */
57  TYPEDEF_ERR_INFO( EI_Selection, const Selection );
58  TYPEDEF_ERR_INFO( EI_Value, const int);
59  DECLARE_EXCEPTION( ExcSelectionKeyNotFound,
60  << "Key " << EI_KeyName::qval <<" not found in Selection:\n" << EI_Selection::val );
61  DECLARE_EXCEPTION( ExcSelectionValueNotFound,
62  << "Value " << EI_Value::val <<" not found in Selection:\n" << EI_Selection::val );
63 
64  /**
65  * Structure for description of one key in selection
66  */
67  struct Key {
68  unsigned int key_index;
69  string key_;
70  string description_;
71  int value;
72  };
73 
74  /**
75  * Public typedef of constant iterator into array of keys
76  */
78 
79  /**
80  * Default constructor. Empty selection.
81  */
82  Selection();
83 
84 
85  /**
86  * Copy constructor.
87  */
88  Selection(const Selection& other);
89 
90  /**
91  * Creates a handle pointing to the new SelectionData.
92  */
93  Selection(const string &name, const std::string &description = "");
94 
95  /**
96  * Adds one new @p value with name given by @p key to the Selection. The @p description of meaning of the value could be provided.
97  */
98  Selection &add_value(const int value, const std::string &key, const std::string &description = "");
99 
100 
101  /**
102  * Close the Selection, no more values can be added.
103  */
104  const Selection &close() const;
105 
106  /// Implements \p TypeBase::is_finished
107  virtual bool is_finished() const;
108 
109  /// Implements \p TypeBase::type_name
110  virtual string type_name() const;
111 
112  /// Implements \p TypeBase::full_type_name
113  virtual string full_type_name() const;
114 
115  /// Implements \p TypeBase::operator== compare also Selection names.
116  virtual bool operator==(const TypeBase &other) const;
117 
118  /**
119  * Container-like access to the keys of the Record. Returns iterator to the first key.
120  */
121  inline keys_const_iterator begin() const;
122 
123  /**
124  * Container-like access to the keys of the Record. Returns iterator to the last key.
125  */
126  inline keys_const_iterator end() const;
127 
128  /**
129  * Returns iterator to the key struct for given key string.
130  */
131  inline keys_const_iterator key_iterator(const string& key) const;
132 
133  /**
134  * Converts given value name \p key to the value. Throws exception if the value name does not exist.
135  */
136  int name_to_int(const string &key) const;
137 
138  /**
139  * Returns value name for the given \p value. Throws exception if the value does not exist.
140  */
141  string int_to_name(const int &value) const;
142 
143  Selection &copy_values(const Selection &sel);
144 
145  /**
146  * Same as \p Selection::name_to_int, but throws different exception, when string comes from default value.
147  */
148  int from_default(const string &str) const;
149 
150  /// Implements @p Type::TypeBase::valid_defaults.
151  virtual bool valid_default(const string &str) const;
152 
153  /**
154  * Just check if there is a particular name in the Selection.
155  */
156  inline bool has_name(const string &key) const;
157 
158  /**
159  * Check if there is a particular value in the Selection.
160  */
161  inline bool has_value(const int &val) const;
162 
163  /**
164  * Returns number of values in the Selection.
165  */
166  inline unsigned int size() const;
167 
168 
169  bool finish()
170  { close(); return true; }
171 private:
172 
173  /**
174  * Assertion for finished Selection (methods are called in correct order).
175  */
176  void finished_check() const;
177 
178  /**
179  * Used in error messaged, where we can not use desc(), which can lead to infinite loop due to TYPE selection of AbstractRecord.
180  */
181  string key_list() const;
182 
183  /**
184  * Actual Selection data.
185  */
187  public:
188 
189  SelectionData(const string &name)
190  : type_name_(name), /*made_extensive_doc(false),*/ finished(false)
191  {}
192 
193  void add_value(const int value, const std::string &key, const std::string &description);
194 
195 
196  /// Name of the Selection.
197  string type_name_;
198 
199  /// Map : valid value name to index.
202 
203  /// Map : valid value to index.
206 
207  /// Vector of values of the Selection
209 
210  /// Text description of the whole Selection object.
211  std::string description_;
212 
213  /// Indicator of finished Selection.
214  mutable bool finished;
215  };
216 
217  /// Handle to actual Selection data.
218  boost::shared_ptr<SelectionData> data_;
219 
220 };
221 
222 
223 
224 
225 
226 /******************************************************************************
227  * Implementation of inline methods.
228  */
229 
230 inline bool Selection::has_name(const string &key) const {
231  finished_check();
232  KeyHash key_h = key_hash(key);
233  return (data_->key_to_index_.find(key_h) != data_->key_to_index_.end());
234 }
235 
236 
237 
238 inline bool Selection::has_value(const int &val) const {
239  finished_check();
240  return (data_->value_to_index_.find(val) != data_->value_to_index_.end());
241 }
242 
243 
244 
245 inline unsigned int Selection::size() const {
246  finished_check();
247  //ASSERT( data_->keys_.size() == data_->key_to_index_.size(),
248  // "Sizes of Type:Selection doesn't match. (map: %ld vec: %ld)\n", data_->key_to_index_.size(), data_->keys_.size());
249  ASSERT_EQUAL( data_->keys_.size(), data_->key_to_index_.size());
250  return data_->keys_.size();
251 }
252 
253 
254 
255 
256 inline void Selection::finished_check() const {
257  ASSERT(data_->finished, "Accessing unfinished Selection '%s'\n", type_name().c_str() );
258 }
259 
260 
261 
263 {
264  finished_check();
265  return data_->keys_.begin();
266 }
267 
268 
269 
271 {
272  finished_check();
273  return data_->keys_.end();
274 }
275 
276 
278 {
279  finished_check();
280  return begin() + name_to_int(key);
281 }
282 
283 
284 } // closing namespace Type
285 } // closing namespace Input
286 
287 #endif /* TYPE_SELECTION_HH_ */