Flow123d  jenkins-Flow123d-linux-release-multijob-282
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  /**
143  * Hash of the type specification. Provides unique id computed from its
144  * content (definition) so that same types have same hash.
145  */
146  virtual std::size_t content_hash() const =0;
147 
148 protected:
149 
150  /**
151  * Default constructor. Register type object into lazy_object_set.
152  */
153  TypeBase();
154 
155  /**
156  * Copy constructor. Register type object into lazy_object_set.
157  */
158  TypeBase(const TypeBase& other);
159 
160 
161 
162 
163  /**
164  * Type of hash values used in associative array that translates key names to indices in Record and Selection.
165  *
166  * For simplicity, we currently use whole strings as "hash".
167  */
168  typedef string KeyHash;
169 
170  /// Hash function.
171  inline static KeyHash key_hash(const string &str) {
172  return (str);
173  }
174 
175  /**
176  * Check that a @p key is valid identifier, i.e. consists only of valid characters, that are lower-case letters, digits and underscore,
177  * we allow identifiers starting with a digit, but it is discouraged since it slows down parsing of the input file.
178  */
179  static bool is_valid_identifier(const string& key);
180 
181  /**
182  * The Singleton class LazyTypes serves for handling the lazy-evaluated input types, derived from the base class
183  * LazyType. When all static variables are initialized, the method LazyTypes::instance().finish() can be called
184  * in order to finish initialization of lazy types such as Records, AbstractRecords, Arrays and Selections.
185  * Selections have to be finished after all other types since they are used by AbstractRecords to register all
186  * derived types. For this reason LazyTypes contains two arrays - one for Selections, one for the rest.
187  *
188  * This is list of unique instances that may contain raw pointers to possibly not yet constructed
189  * (static) objects. Unique instance is the instance that creates unique instance of the data class in pimpl idiom.
190  * These has to be completed/finished before use.
191  *
192  */
194 
195  /**
196  * The reference to the singleton instance of @p lazy_type_list.
197  */
198  static LazyTypeVector &lazy_type_list();
199 
200  /**
201  * Set of pointers to all constructed (even temporaries) lazy types. This list contains ALL instances
202  * (including copies and empty handles) of lazy types.
203  */
204  typedef std::set<const TypeBase *> LazyObjectsSet;
205 
206  static LazyObjectsSet &lazy_object_set();
207 
208  static bool was_constructed(const TypeBase * ptr);
209 
210  friend class Array;
211  friend class Record;
212 };
213 
214 /**
215  * For convenience we provide also redirection operator for output documentation of Input:Type classes.
216  */
217 std::ostream& operator<<(std::ostream& stream, const TypeBase& type);
218 
219 
220 class Record;
221 class Selection;
222 
223 
224 /**
225  * @brief Class for declaration of inputs sequences.
226  *
227  * The type is fully specified after its constructor is called. All elements of the Array has same type, however you
228  * can use elements of AbstractRecord.
229  *
230  * If you not disallow Array size 1, the input reader will try to convert any other type
231  * on input into array with one element, e.g.
232  @code
233  int_array=1 # is equivalent to
234  int_array=[ 1 ]
235  @endcode
236  *
237  * @ingroup input_types
238  */
239 class Array : public TypeBase {
240  friend class OutputBase;
241 
242 protected:
243 
244  class ArrayData {
245  public:
246 
247  ArrayData(unsigned int min_size, unsigned int max_size)
248  : lower_bound_(min_size), upper_bound_(max_size), finished(false)
249  {}
250 
251  bool finish();
252 
253  boost::shared_ptr<const TypeBase> type_of_values_;
254  unsigned int lower_bound_, upper_bound_;
256  bool finished;
257 
258  };
259 
260 public:
261  /**
262  * 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
263  * 'complex' types @p Record and @p Selection. You can also specify minimum and maximum size of the array.
264  */
265  template <class ValueType>
266  Array(const ValueType &type, unsigned int min_size=0, unsigned int max_size=std::numeric_limits<unsigned int>::max() );
267 
268  std::size_t content_hash() const override;
269 
270  /// Finishes initialization of the Array type because of lazy evaluation of type_of_values.
271  virtual bool finish();
272 
273  virtual bool is_finished() const {
274  return data_->finished; }
275 
276  /// Getter for the type of array items.
277  inline const TypeBase &get_sub_type() const {
278  ASSERT( data_->finished, "Getting sub-type from unfinished Array.\n");
279  return *data_->type_of_values_; }
280 
281  /// Checks size of particular array.
282  inline bool match_size(unsigned int size) const {
283  return size >=data_->lower_bound_ && size<=data_->upper_bound_; }
284 
285  /// @brief Implements @p Type::TypeBase::type_name. Name has form \p array_of_'subtype name'
286  virtual string type_name() const;
287 
288  /// @brief Implements @p Type::TypeBase::full_type_name.
289  virtual string full_type_name() const;
290 
291  /// @brief Implements @p Type::TypeBase::operator== Compares also subtypes.
292  virtual bool operator==(const TypeBase &other) const;
293 
294  /**
295  * Default values for an array creates array containing one element
296  * that is initialized by given default value. So this method check
297  * if the default value is valid for the sub type of the array.
298  */
299  virtual bool valid_default(const string &str) const;
300 
301 protected:
302 
303  /// Handle to the actual array data.
304  boost::shared_ptr<ArrayData> data_;
305 private:
306  /// Forbids default constructor in order to prevent empty data_.
307  Array();
308 };
309 
310 
311 
312 /**
313  * @brief Base of all scalar types.
314  *
315  * @ingroup input_types
316  */
317 class Scalar : public TypeBase {
318 public:
319 
320  virtual string full_type_name() const;
321 
322 };
323 
324 
325 /**
326  * @brief Class for declaration of the input of type Bool.
327  *
328  * String names of boolean values are \p 'true' and \p 'false'.
329  *
330  * @ingroup input_types
331  */
332 class Bool : public Scalar {
333 public:
335  {}
336 
337  std::size_t content_hash() const override;
338 
339 
340  bool from_default(const string &str) const;
341 
342  virtual string type_name() const;
343 
344  virtual bool valid_default(const string &str) const;
345 };
346 
347 
348 /**
349  * @brief Class for declaration of the integral input data.
350  *
351  * The data are stored in an \p signed \p int variable. You can specify bounds for the valid input data.
352  *
353  * @ingroup input_types
354  */
355 class Integer : public Scalar {
356  friend class OutputBase;
357 
358 public:
359  Integer(int lower_bound=std::numeric_limits<int>::min(), int upper_bound=std::numeric_limits<int>::max())
360  : lower_bound_(lower_bound), upper_bound_(upper_bound)
361  {}
362 
363  std::size_t content_hash() const override;
364 
365  /**
366  * Returns true if the given integer value conforms to the Type::Integer bounds.
367  */
368  bool match(int value) const;
369 
370  /**
371  * As before but also returns converted integer in @p value.
372  */
373  int from_default(const string &str) const;
374  /// Implements @p Type::TypeBase::valid_defaults.
375  virtual bool valid_default(const string &str) const;
376 
377  virtual string type_name() const;
378 private:
379 
380  int lower_bound_, upper_bound_;
381 
382 };
383 
384 
385 /**
386  * @brief Class for declaration of the input data that are floating point numbers.
387  *
388  * The data are stored in an \p double variable. You can specify bounds for the valid input data.
389  *
390  * @ingroup input_types
391  */
392 class Double : public Scalar {
393  friend class OutputBase;
394 
395 public:
396  Double(double lower_bound= -std::numeric_limits<double>::max(), double upper_bound=std::numeric_limits<double>::max())
397  : lower_bound_(lower_bound), upper_bound_(upper_bound)
398  {}
399 
400  std::size_t content_hash() const override;
401 
402  /**
403  * Returns true if the given integer value conforms to the Type::Double bounds.
404  */
405  bool match(double value) const;
406 
407  /// Implements @p Type::TypeBase::valid_defaults.
408  virtual bool valid_default(const string &str) const;
409 
410  /**
411  * As before but also returns converted integer in @p value.
412  */
413  double from_default(const string &str) const;
414 
415  virtual string type_name() const;
416 private:
417 
418 
419  double lower_bound_, upper_bound_;
420 
421 };
422 
423 
424 
425 /**
426  * Just for consistency, but is essentially same as Scalar.
427  *
428  * @ingroup input_types
429  */
430 class String : public Scalar {
431 public:
432  virtual string type_name() const;
433 
434  std::size_t content_hash() const override;
435 
436 
437  string from_default(const string &str) const;
438 
439  /**
440  * Particular descendants can check validity of the string.
441  */
442  virtual bool match(const string &value) const;
443 
444  /// Implements @p Type::TypeBase::valid_defaults.
445  virtual bool valid_default(const string &str) const;
446 };
447 
448 
449 /**
450  * @brief Class for declaration of the input data that are file names.
451  *
452  * We strictly distinguish filenames for input and output files.
453  *
454  * @ingroup input_types
455  */
456 class FileName : public String {
457 public:
458 
459  std::size_t content_hash() const override;
460 
461  /**
462  * Factory function for declaring type FileName for input files.
463  */
464  static FileName input()
465  { return FileName(::FilePath::input_file); }
466 
467  /**
468  * Factory function for declaring type FileName for input files.
469  */
470  static FileName output()
471  { return FileName(::FilePath::output_file); }
472 
473  virtual string type_name() const;
474 
475  virtual bool operator==(const TypeBase &other) const
476  { return typeid(*this) == typeid(other) &&
477  (type_== static_cast<const FileName *>(&other)->get_file_type() );
478  }
479 
480  /// Checks relative output paths.
481  virtual bool match(const string &str) const;
482 
483 
484  /**
485  * Returns type of the file input/output.
486  */
488  return type_;
489  }
490 
491 
492 
493 private:
495 
496  /// Forbids default constructor.
497  FileName() {}
498 
499  /// Forbids direct construction.
500  FileName(enum ::FilePath::FileType type)
501  : type_(type)
502  {}
503 
504 };
505 
506 } // closing namespace Type
507 } // closing namespace Input
508 
509 
510 
511 
512 
513 #endif /* TYPE_BASE_HH_ */
Base of classes for declaring structure of the input data.
Definition: type_base.hh:63
virtual bool operator==(const TypeBase &other) const
Definition: type_base.hh:103
virtual string full_type_name() const
Returns an identification of the type in format &quot;type_name():parent-&gt;type_name()&quot;.
Definition: type_base.hh:78
TYPEDEF_ERR_INFO(EI_KeyName, const string)
Class for declaration of the input of type Bool.
Definition: type_base.hh:332
FileType
Possible types of file.
Definition: file_path.hh:40
std::vector< boost::shared_ptr< TypeBase > > LazyTypeVector
Definition: type_base.hh:193
virtual bool is_finished() const
Definition: type_base.hh:71
::FilePath::FileType type_
Definition: type_base.hh:494
Base abstract class for output description of the Input::Type tree.
Definition: type_output.hh:37
Double(double lower_bound=-std::numeric_limits< double >::max(), double upper_bound=std::numeric_limits< double >::max())
Definition: type_base.hh:396
Base of all scalar types.
Definition: type_base.hh:317
static KeyHash key_hash(const string &str)
Hash function.
Definition: type_base.hh:171
virtual string type_name() const
Returns an identification of the type. Useful for error messages.
Definition: type_base.hh:75
Class for declaration of the input data that are file names.
Definition: type_base.hh:456
Class for declaration of the integral input data.
Definition: type_base.hh:355
ArrayData(unsigned int min_size, unsigned int max_size)
Definition: type_base.hh:247
Class for declaration of inputs sequences.
Definition: type_base.hh:239
bool operator==(const Null &, const Null &)
std::set< const TypeBase * > LazyObjectsSet
Definition: type_base.hh:204
Global macros to enhance readability and debugging, general constants.
#define ASSERT(...)
Definition: global_defs.h:121
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:392
static FileName input()
Definition: type_base.hh:464
virtual bool operator==(const TypeBase &other) const
Definition: type_base.hh:475
const TypeBase * p_type_of_values
Definition: type_base.hh:255
bool match_size(unsigned int size) const
Checks size of particular array.
Definition: type_base.hh:282
bool operator!=(const TypeBase &other) const
Comparison of types.
Definition: type_base.hh:107
boost::shared_ptr< ArrayData > data_
Handle to the actual array data.
Definition: type_base.hh:304
FileName()
Forbids default constructor.
Definition: type_base.hh:497
::FilePath::FileType get_file_type() const
Definition: type_base.hh:487
static FileName output()
Definition: type_base.hh:470
boost::shared_ptr< const TypeBase > type_of_values_
Definition: type_base.hh:253
const TypeBase & get_sub_type() const
Getter for the type of array items.
Definition: type_base.hh:277
DECLARE_EXCEPTION(ExcWrongDefault,<< "Default value "<< EI_DefaultStr::qval<< " do not match type: "<< EI_TypeName::qval<< ";\n"<< "During declaration of the key: "<< EI_KeyName::qval)
virtual bool finish()
Definition: type_base.hh:131
std::ostream & operator<<(std::ostream &stream, const TypeBase &type)
Definition: type_base.cc:130
Record type proxy class.
Definition: type_record.hh:169
Integer(int lower_bound=std::numeric_limits< int >::min(), int upper_bound=std::numeric_limits< int >::max())
Definition: type_base.hh:359
Template for classes storing finite set of named values.
FileName(enum::FilePath::FileType type)
Forbids direct construction.
Definition: type_base.hh:500
virtual bool is_finished() const
Definition: type_base.hh:273