Flow123d
type_base.hh
Go to the documentation of this file.
1 /*
2  * type_base.hh
3  *
4  * Created on: May 1, 2012
5  * Author: jb
6  */
7 
8 #ifndef TYPE_BASE_HH_
9 #define TYPE_BASE_HH_
10 
11 #include <limits>
12 #include <ios>
13 #include <set>
14 #include <map>
15 #include <vector>
16 #include <string>
17 #include <iomanip>
18 
19 #include <boost/type_traits.hpp>
20 #include <boost/tokenizer.hpp>
21 #include <boost/shared_ptr.hpp>
22 #include <boost/make_shared.hpp>
23 #include <boost/algorithm/string.hpp>
24 
25 #include "system/global_defs.h"
26 #include "system/system.hh"
27 #include "system/exceptions.hh"
28 #include "system/file_path.hh"
29 
30 
31 
32 
33 namespace Input {
34 
35 namespace Type {
36 
37 
38 
39 using namespace std;
40 
41 /**
42  * Declaration of common exceptions and error info types.
43  */
44 TYPEDEF_ERR_INFO( EI_KeyName, const string );
45 
46 TYPEDEF_ERR_INFO( EI_DefaultStr, const string);
47 TYPEDEF_ERR_INFO( EI_TypeName, const string);
48 DECLARE_EXCEPTION( ExcWrongDefault, << "Default value " << EI_DefaultStr::qval
49  << " do not match type: " << EI_TypeName::qval << ";\n"
50  << "During declaration of the key: " << EI_KeyName::qval );
51 
52 
53 
54 
55 /**
56  * @brief Base of classes for declaring structure of the input data.
57  *
58  * Provides methods common to all types. Namely, the type name, finished status (nontrivial only for types with complex initialization - Record, AbstractRecosd, Selection)
59  * and output of the documentation.
60  *
61  * @ingroup input_types
62  */
63 class TypeBase {
64 public:
65  /**
66  * Returns true if the type is fully specified and ready for read access. For Record and Array types
67  * this say nothing about child types referenced in particular type object.
68  * In particular for Record and Selection, it returns true after @p finish() method is called.
69  *
70  */
71  virtual bool is_finished() const
72  {return true;}
73 
74  /// Returns an identification of the type. Useful for error messages.
75  virtual string type_name() const { return "TypeBase"; }
76 
77  /// Returns an identification of the type in format "type_name():parent->type_name()".
78  virtual string full_type_name() const { return "TypeBase"; }
79 
80  /**
81  * Returns string with Type extensive documentation. We need this to pass Type description at
82  * throw points since the Type object can be deallocated during stack unrolling so it is not good idea to pass
83  * pointer. Maybe we can pass smart pointers. Actually this method is used in various exceptions in json_to_storage.
84  *
85  * Some old note on this topic:
86  * !!! how to pass instance of descendant of TypeBase through EI -
87  * - can not pass it directly since TypeBase is not copyconstructable
88  * - can not use shared_ptr for same reason
89  * - can not use C pointers since the refered object can be temporary
90  * solutions:
91  * - consistently move TypeBase to Pimpl design
92  * - provide virtual function make_copy, that returns valid shared_ptr
93  *
94  */
95  string desc() const;
96 
97 
98 
99  /**
100  * Comparison of types. It compares kind of type (Integer, Double, String, Record, ..), for complex types
101  * it also compares names. For arrays compare subtypes.
102  */
103  virtual bool operator==(const TypeBase &other) const
104  { return typeid(*this) == typeid(other); }
105 
106  /// Comparison of types.
107  bool operator!=(const TypeBase & other) const
108  { return ! (*this == other); }
109 
110  /**
111  * Destructor removes type object from lazy_object_set.
112  */
113  virtual ~TypeBase();
114 
115 
116 
117  /// Finishes all registered lazy types.
118  static void lazy_finish();
119 
120 
121  /**
122  * Finish method. Finalize construction of "Lazy types": Record, Selection, AbstractRecord, and Array.
123  * These input types are typically defined by means
124  * of static variables, whose order of initialization is not known a priori. Since e.g. a Record can link to other
125  * input types through its keys, these input types cannot be accessed directly at the initialization phase.
126  * The remaining part of initialization can be done later, typically from main(), by calling the method finish().
127  *
128  * Finish try to convert all raw pointers pointing to lazy types into smart pointers to valid objects. If there
129  * are still raw pointers to not constructed objects the method returns false.
130  */
131  virtual bool finish()
132  { return true; };
133 
134  /**
135  * For types that can be initialized from a default string, this method check
136  * validity of the default string. For invalid string an exception is thrown.
137  *
138  * Return false if the validity can not be decided due to presence of unconstructed types (Record, Selection)
139  */
140  virtual bool valid_default(const string &str) const =0;
141 
142 protected:
143 
144  /**
145  * Default constructor. Register type object into lazy_object_set.
146  */
147  TypeBase();
148 
149  /**
150  * Copy constructor. Register type object into lazy_object_set.
151  */
152  TypeBase(const TypeBase& other);
153 
154  /**
155  * Type of hash values used in associative array that translates key names to indices in Record and Selection.
156  *
157  * For simplicity, we currently use whole strings as "hash".
158  */
159  typedef string KeyHash;
160 
161  /// Hash function.
162  inline static KeyHash key_hash(const string &str) {
163  return (str);
164  }
165 
166  /**
167  * Check that a @p key is valid identifier, i.e. consists only of valid characters, that are lower-case letters, digits and underscore,
168  * we allow identifiers starting with a digit, but it is discouraged since it slows down parsing of the input file.
169  */
170  static bool is_valid_identifier(const string& key);
171 
172  /**
173  * The Singleton class LazyTypes serves for handling the lazy-evaluated input types, derived from the base class
174  * LazyType. When all static variables are initialized, the method LazyTypes::instance().finish() can be called
175  * in order to finish initialization of lazy types such as Records, AbstractRecords, Arrays and Selections.
176  * Selections have to be finished after all other types since they are used by AbstractRecords to register all
177  * derived types. For this reason LazyTypes contains two arrays - one for Selections, one for the rest.
178  *
179  * This is list of unique instances that may contain raw pointers to possibly not yet constructed
180  * (static) objects. Unique instance is the instance that creates unique instance of the data class in pimpl idiom.
181  * These has to be completed/finished before use.
182  *
183  */
185 
186  /**
187  * The reference to the singleton instance of @p lazy_type_list.
188  */
189  static LazyTypeVector &lazy_type_list();
190 
191  /**
192  * Set of pointers to all constructed (even temporaries) lazy types. This list contains ALL instances
193  * (including copies and empty handles) of lazy types.
194  */
195  typedef std::set<const TypeBase *> LazyObjectsSet;
196 
197  static LazyObjectsSet &lazy_object_set();
198 
199  static bool was_constructed(const TypeBase * ptr);
200 
201  friend class Array;
202  friend class Record;
203 };
204 
205 /**
206  * For convenience we provide also redirection operator for output documentation of Input:Type classes.
207  */
208 std::ostream& operator<<(std::ostream& stream, const TypeBase& type);
209 
210 
211 class Record;
212 class Selection;
213 
214 
215 /**
216  * @brief Class for declaration of inputs sequences.
217  *
218  * The type is fully specified after its constructor is called. All elements of the Array has same type, however you
219  * can use elements of AbstractRecord.
220  *
221  * If you not disallow Array size 1, the input reader will try to convert any other type
222  * on input into array with one element, e.g.
223  @code
224  int_array=1 # is equivalent to
225  int_array=[ 1 ]
226  @endcode
227  *
228  * @ingroup input_types
229  */
230 class Array : public TypeBase {
231  friend class OutputBase;
232 
233 protected:
234 
235  class ArrayData {
236  public:
237 
238  ArrayData(unsigned int min_size, unsigned int max_size)
239  : lower_bound_(min_size), upper_bound_(max_size), finished(false)
240  {}
241 
242  bool finish();
243 
244  boost::shared_ptr<const TypeBase> type_of_values_;
245  unsigned int lower_bound_, upper_bound_;
247  bool finished;
248 
249  };
250 
251 public:
252  /**
253  * Constructor with a @p type of array items given as pure reference. In this case \p type has to by descendant of \p TypeBase different from
254  * 'complex' types @p Record and @p Selection. You can also specify minimum and maximum size of the array.
255  */
256  template <class ValueType>
257  Array(const ValueType &type, unsigned int min_size=0, unsigned int max_size=std::numeric_limits<unsigned int>::max() );
258 
259  /// Finishes initialization of the Array type because of lazy evaluation of type_of_values.
260  virtual bool finish();
261 
262  virtual bool is_finished() const {
263  return data_->finished; }
264 
265  /// Getter for the type of array items.
266  inline const TypeBase &get_sub_type() const {
267  ASSERT( data_->finished, "Getting sub-type from unfinished Array.\n");
268  return *data_->type_of_values_; }
269 
270  /// Checks size of particular array.
271  inline bool match_size(unsigned int size) const {
272  return size >=data_->lower_bound_ && size<=data_->upper_bound_; }
273 
274  /// @brief Implements @p Type::TypeBase::type_name. Name has form \p array_of_'subtype name'
275  virtual string type_name() const;
276 
277  /// @brief Implements @p Type::TypeBase::full_type_name.
278  virtual string full_type_name() const;
279 
280  /// @brief Implements @p Type::TypeBase::operator== Compares also subtypes.
281  virtual bool operator==(const TypeBase &other) const;
282 
283  /**
284  * Default values for an array creates array containing one element
285  * that is initialized by given default value. So this method check
286  * if the default value is valid for the sub type of the array.
287  */
288  virtual bool valid_default(const string &str) const;
289 
290 protected:
291 
292  /// Handle to the actual array data.
293  boost::shared_ptr<ArrayData> data_;
294 private:
295  /// Forbids default constructor in order to prevent empty data_.
296  Array();
297 };
298 
299 
300 
301 /**
302  * @brief Base of all scalar types.
303  *
304  * @ingroup input_types
305  */
306 class Scalar : public TypeBase {
307 public:
308 
309  virtual string full_type_name() const;
310 
311 };
312 
313 
314 /**
315  * @brief Class for declaration of the input of type Bool.
316  *
317  * String names of boolean values are \p 'true' and \p 'false'.
318  *
319  * @ingroup input_types
320  */
321 class Bool : public Scalar {
322 public:
324  {}
325 
326  bool from_default(const string &str) const;
327 
328  virtual string type_name() const;
329 
330  virtual bool valid_default(const string &str) const;
331 };
332 
333 
334 /**
335  * @brief Class for declaration of the integral input data.
336  *
337  * The data are stored in an \p signed \p int variable. You can specify bounds for the valid input data.
338  *
339  * @ingroup input_types
340  */
341 class Integer : public Scalar {
342  friend class OutputBase;
343 
344 public:
345  Integer(int lower_bound=std::numeric_limits<int>::min(), int upper_bound=std::numeric_limits<int>::max())
346  : lower_bound_(lower_bound), upper_bound_(upper_bound)
347  {}
348 
349  /**
350  * Returns true if the given integer value conforms to the Type::Integer bounds.
351  */
352  bool match(int value) const;
353 
354  /**
355  * As before but also returns converted integer in @p value.
356  */
357  int from_default(const string &str) const;
358  /// Implements @p Type::TypeBase::valid_defaults.
359  virtual bool valid_default(const string &str) const;
360 
361  virtual string type_name() const;
362 private:
363 
364  int lower_bound_, upper_bound_;
365 
366 };
367 
368 
369 /**
370  * @brief Class for declaration of the input data that are floating point numbers.
371  *
372  * The data are stored in an \p double variable. You can specify bounds for the valid input data.
373  *
374  * @ingroup input_types
375  */
376 class Double : public Scalar {
377  friend class OutputBase;
378 
379 public:
380  Double(double lower_bound= -std::numeric_limits<double>::max(), double upper_bound=std::numeric_limits<double>::max())
381  : lower_bound_(lower_bound), upper_bound_(upper_bound)
382  {}
383 
384  /**
385  * Returns true if the given integer value conforms to the Type::Double bounds.
386  */
387  bool match(double value) const;
388 
389  /// Implements @p Type::TypeBase::valid_defaults.
390  virtual bool valid_default(const string &str) const;
391 
392  /**
393  * As before but also returns converted integer in @p value.
394  */
395  double from_default(const string &str) const;
396 
397  virtual string type_name() const;
398 private:
399 
400 
401  double lower_bound_, upper_bound_;
402 
403 };
404 
405 
406 
407 /**
408  * Just for consistency, but is essentially same as Scalar.
409  *
410  * @ingroup input_types
411  */
412 class String : public Scalar {
413 public:
414  virtual string type_name() const;
415 
416 
417 
418  string from_default(const string &str) const;
419 
420  /**
421  * Particular descendants can check validity of the string.
422  */
423  virtual bool match(const string &value) const;
424 
425  /// Implements @p Type::TypeBase::valid_defaults.
426  virtual bool valid_default(const string &str) const;
427 };
428 
429 
430 /**
431  * @brief Class for declaration of the input data that are file names.
432  *
433  * We strictly distinguish filenames for input and output files.
434  *
435  * @ingroup input_types
436  */
437 class FileName : public String {
438 public:
439 
440  /**
441  * Factory function for declaring type FileName for input files.
442  */
443  static FileName input()
444  { return FileName(::FilePath::input_file); }
445 
446  /**
447  * Factory function for declaring type FileName for input files.
448  */
449  static FileName output()
450  { return FileName(::FilePath::output_file); }
451 
452  virtual string type_name() const;
453 
454  virtual bool operator==(const TypeBase &other) const
455  { return typeid(*this) == typeid(other) &&
456  (type_== static_cast<const FileName *>(&other)->get_file_type() );
457  }
458 
459  /// Checks relative output paths.
460  virtual bool match(const string &str) const;
461 
462 
463  /**
464  * Returns type of the file input/output.
465  */
467  return type_;
468  }
469 
470 
471 
472 private:
474 
475  /// Forbids default constructor.
476  FileName() {}
477 
478  /// Forbids direct construction.
479  FileName(enum ::FilePath::FileType type)
480  : type_(type)
481  {}
482 
483 };
484 
485 } // closing namespace Type
486 } // closing namespace Input
487 
488 
489 
490 
491 
492 #endif /* TYPE_BASE_HH_ */