Flow123d  jenkins-Flow123d-linux-release-multijob-282
type_base.cc
Go to the documentation of this file.
1 /*
2  * input_type.cc
3  *
4  * Created on: Mar 29, 2012
5  * Author: jb
6  */
7 
8 
9 
10 #include <limits>
11 #include <ios>
12 #include <map>
13 #include <vector>
14 #include <string>
15 #include <iomanip>
16 
17 #include "system/system.hh"
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 #include <boost/functional/hash.hpp>
25 
26 
27 #include "type_base.hh"
28 #include "type_record.hh"
29 #include "type_output.hh"
30 #include <boost/algorithm/string.hpp>
31 
32 
33 namespace Input {
34 namespace Type {
35 
36 using namespace std;
37 
38 
39 
40 /*******************************************************************
41  * implementation of TypeBase
42  */
43 
44 
45 
47  TypeBase::lazy_object_set().insert(this);
48 }
49 
50 
51 
53 {
54  TypeBase::lazy_object_set().insert(this);
55 }
56 
57 
58 
61  TypeBase::LazyObjectsSet::iterator it =set.find(this);
62  ASSERT( it != set.end(), "Missing pointer in lazy_object_set to '%s'.\n", this->type_name().c_str());
63  TypeBase::lazy_object_set().erase(it);
64 }
65 
66 
67 bool TypeBase::is_valid_identifier(const string& key) {
68  namespace ba = boost::algorithm;
69  return ba::all( key, ba::is_lower() || ba::is_digit() || ba::is_any_of("_") );
70 }
71 
72 
73 string TypeBase::desc() const {
74  stringstream ss;
75  ss << OutputText(this,1);
76  return ss.str();
77 }
78 
79 
80 
82  static LazyTypeVector lazy_type_list;
83  return lazy_type_list;
84 }
85 
86 
87 
89  // TODO: dynamic cast as the switch may be expensive, in such case use some notification about type
90 
91  // first finish all lazy input types save Selection (we have to leave open Selection in AbstractType key TYPE)
92  for (LazyTypeVector::iterator it=lazy_type_list().begin(); it!=lazy_type_list().end(); it++) {
93  if (boost::dynamic_pointer_cast<Selection>(*it) == 0) {
94  (*it)->finish();
95  }
96  }
97 
98  // then finalize abstract records so that no type can derive from them
99  for (LazyTypeVector::iterator it=lazy_type_list().begin(); it!=lazy_type_list().end(); it++)
100  {
101  boost::shared_ptr<AbstractRecord> a_rec_ptr = boost::dynamic_pointer_cast<AbstractRecord>(*it);
102  if ( a_rec_ptr!= 0) a_rec_ptr->no_more_descendants();
103  }
104 
105  // at last finish all selections (including those in AbstractRecord)
106  for (LazyTypeVector::iterator it=lazy_type_list().begin(); it!=lazy_type_list().end(); it++) {
107  if (! (*it)->finish()) xprintf(PrgErr, "Can not finish '%s' during lazy_finish.\n", (*it)->type_name().c_str() );
108  }
109 
110  lazy_type_list().clear();
111 
112 }
113 
114 
115 
116 
118  static LazyObjectsSet set_;
119  return set_;
120 }
121 
122 
123 
125  return lazy_object_set().find(ptr) != lazy_object_set().end();
126 }
127 
128 
129 
130 std::ostream& operator<<(std::ostream& stream, const TypeBase& type) {
131  return ( stream << OutputText(&type, 1) );
132 }
133 
134 
135 
136 /**********************************************************************************
137  * implementation of Type::Array
138  */
139 
140 std::size_t Array::content_hash() const
141 {
142  std::size_t seed=0;
143  boost::hash_combine(seed, type_name());
144  boost::hash_combine(seed, data_->lower_bound_);
145  boost::hash_combine(seed, data_->upper_bound_);
146  boost::hash_combine(seed, data_->type_of_values_->content_hash() );
147  return seed;
148 }
149 
150 
152  return data_->finish();
153 }
154 
155 
156 
158 {
159  if (finished) return true;
160 
161  if (p_type_of_values != 0)
162  {
163  if (! was_constructed(p_type_of_values) ) return false;
164 
165  if (dynamic_cast<const AbstractRecord *>(p_type_of_values) != 0)
166  {
167  AbstractRecord *ar = (AbstractRecord *)dynamic_cast<const AbstractRecord *>(p_type_of_values);
168  boost::shared_ptr<const TypeBase> type_copy = boost::make_shared<const AbstractRecord>(*ar);
169  type_of_values_ = type_copy;
170  p_type_of_values = 0;
171  }
172  else if (dynamic_cast<const Record *>(p_type_of_values) != 0)
173  {
174  Record *r = (Record *)dynamic_cast<const Record *>(p_type_of_values);
175  boost::shared_ptr<const TypeBase> type_copy = boost::make_shared<const Record>(*r);
176  type_of_values_ = type_copy;
177  p_type_of_values = 0;
178  }
179  else if (dynamic_cast<const Selection *>(p_type_of_values) != 0)
180  {
181  Selection *s = (Selection *)dynamic_cast<const Selection *>(p_type_of_values);
182  boost::shared_ptr<const TypeBase> type_copy = boost::make_shared<const Selection>(*s);
183  type_of_values_ = type_copy;
184  p_type_of_values = 0;
185  }
186  else if (dynamic_cast<const Array *>(p_type_of_values) != 0)
187  xprintf(PrgErr, "Should not happen!\n");
188  }
189 
190  return (finished = true);
191 }
192 
193 
194 
195 string Array::type_name() const {
196  return "array_of_" + data_->type_of_values_->type_name();
197 }
198 
199 string Array::full_type_name() const {
200  return "array_of_" + data_->type_of_values_->type_name();
201 }
202 
203 
204 
205 bool Array::operator==(const TypeBase &other) const {
206  return typeid(*this) == typeid(other) &&
207  (*data_->type_of_values_ == static_cast<const Array *>(&other)->get_sub_type() );
208 }
209 
210 
211 
212 bool Array::valid_default(const string &str) const {
213  if ( this->match_size( 1 ) ) {
214  return get_sub_type().valid_default( str );
215  } else {
216  THROW( ExcWrongDefault() << EI_DefaultStr( str ) << EI_TypeName(type_name()));
217  }
218 }
219 
220 
221 /**********************************************************************************
222  * implementation and explicit instantiation of Array constructor template
223  */
224 
225 template <class ValueType>
226 Array::Array(const ValueType &type, unsigned int min_size, unsigned int max_size)
227 : data_(boost::make_shared<ArrayData>(min_size, max_size))
228 {
229  // ASSERT MESSAGE: The type of declared keys has to be a class derived from TypeBase.
230  BOOST_STATIC_ASSERT( (boost::is_base_of<TypeBase, ValueType >::value) );
231  ASSERT( min_size <= max_size, "Wrong limits for size of Input::Type::Array, min: %d, max: %d\n", min_size, max_size);
232 
233  // Records, AbstractRecords and Selections need not be initialized
234  // at the moment, so we save the reference of type and update
235  // the array later in finish().
236  if ( (boost::is_base_of<Record, ValueType>::value ||
237  boost::is_base_of<Selection, ValueType>::value)
238  && ! TypeBase::was_constructed(&type) ) {
239  data_->p_type_of_values = &type;
240  TypeBase::lazy_type_list().push_back( boost::make_shared<Array>( *this ) );
241  } else {
242  data_->p_type_of_values = NULL;
243  boost::shared_ptr<const TypeBase> type_copy = boost::make_shared<ValueType>(type);
244  data_->type_of_values_ = type_copy;
245  data_->finished=true;
246  }
247 }
248 
249 // explicit instantiation
250 
251 #define ARRAY_CONSTRUCT(TYPE) \
252 template Array::Array(const TYPE &type, unsigned int min_size, unsigned int max_size)
253 
254 ARRAY_CONSTRUCT(String);
255 ARRAY_CONSTRUCT(Integer);
256 ARRAY_CONSTRUCT(Double);
257 ARRAY_CONSTRUCT(Bool);
258 ARRAY_CONSTRUCT(FileName);
259 ARRAY_CONSTRUCT(Selection);
260 ARRAY_CONSTRUCT(Array);
261 ARRAY_CONSTRUCT(Record);
262 ARRAY_CONSTRUCT(AbstractRecord);
263 
264 
265 /**********************************************************************************
266  * implementation of Type::Scalar ... and descendants.
267  */
268 
269 string Scalar::full_type_name() const {
270  return type_name();
271 }
272 
273 /**********************************************************************************
274  * implementation of Type::Bool
275  */
276 
277 
278 std::size_t Bool::content_hash() const
279 {
280  std::size_t seed=0;
281  boost::hash_combine(seed, type_name());
282  return seed;
283 }
284 
285 
286 bool Bool::valid_default(const string &str) const {
287  from_default(str);
288  return true;
289 }
290 
291 
292 
293 bool Bool::from_default(const string &str) const {
294  if (str == "true" ) {
295  return true;
296  } else
297  if (str == "false") {
298  return false;
299  } else {
300  THROW( ExcWrongDefault() << EI_DefaultStr( str ) << EI_TypeName(type_name()));
301  }
302 }
303 
304 
305 string Bool::type_name() const {
306  return "Bool";
307 }
308 
309 
310 /**********************************************************************************
311  * implementation of Type::Integer
312  */
313 
314 std::size_t Integer::content_hash() const
315 {
316  std::size_t seed=0;
317  boost::hash_combine(seed, type_name());
318  boost::hash_combine(seed, lower_bound_);
319  boost::hash_combine(seed, upper_bound_);
320  return seed;
321 }
322 
323 
324 
325 bool Integer::match(int value) const {
326  return ( value >=lower_bound_ && value <= upper_bound_);
327 }
328 
329 
330 
331 int Integer::from_default(const string &str) const {
332  std::istringstream stream(str);
333  int value;
334  stream >> value;
335 
336  if (stream && stream.eof() && match(value)) {
337  return value;
338  } else {
339  THROW( ExcWrongDefault() << EI_DefaultStr( str ) << EI_TypeName(type_name()));
340  }
341 }
342 
343 
344 
345 bool Integer::valid_default(const string &str) const
346 {
347  from_default(str);
348  return true;
349 }
350 
351 
352 
353 string Integer::type_name() const {
354  return "Integer";
355 }
356 
357 
358 /**********************************************************************************
359  * implementation of Type::Double
360  */
361 
362 
363 std::size_t Double::content_hash() const
364 {
365  std::size_t seed=0;
366  boost::hash_combine(seed, type_name());
367  boost::hash_combine(seed, lower_bound_);
368  boost::hash_combine(seed, upper_bound_);
369  return seed;
370 }
371 
372 
373 
374 bool Double::match(double value) const {
375  return ( value >=lower_bound_ && value <= upper_bound_);
376 }
377 
378 
379 
380 double Double::from_default(const string &str) const {
381  std::istringstream stream(str);
382  double value;
383  stream >> value;
384 
385  if (stream && stream.eof() && match(value)) {
386  return value;
387  } else {
388  THROW( ExcWrongDefault() << EI_DefaultStr( str ) << EI_TypeName(type_name()));
389  }
390 }
391 
392 
393 
394 bool Double::valid_default(const string &str) const
395 {
396  from_default(str);
397  return true;
398 }
399 
400 
401 
402 
403 string Double::type_name() const {
404  return "Double";
405 }
406 
407 
408 /**********************************************************************************
409  * implementation of Type::FileName
410  */
411 
412 std::size_t FileName::content_hash() const
413 {
414  std::size_t seed=0;
415  boost::hash_combine(seed, type_name());
416  boost::hash_combine(seed, type_);
417  return seed;
418 }
419 
420 
421 
422 
423 
424 string FileName::type_name() const {
425  switch (type_) {
426  case ::FilePath::input_file:
427  return "FileName_input";
428  case ::FilePath::output_file:
429  return "FileName_output";
430  default:
431  return "FileName";
432  }
433 }
434 
435 
436 
437 bool FileName::match(const string &str) const {
438  return (type_ == ::FilePath::input_file) || (str[0] != DIR_DELIMITER); // output files can not be absolute
439 }
440 
441 
442 /**********************************************************************************
443  * implementation of Type::String
444  */
445 
446 
447 std::size_t String::content_hash() const
448 {
449  std::size_t seed=0;
450  boost::hash_combine(seed, type_name());
451  return seed;
452 }
453 
454 
455 
456 string String::type_name() const {
457  return "String";
458 }
459 
460 
461 
462 
463 bool String::valid_default(const string &str) const {
464  if (! match(str)) {
465  THROW( ExcWrongDefault() << EI_DefaultStr( str ) << EI_TypeName(type_name()));
466  }
467  return true;
468 }
469 
470 
471 
472 string String::from_default(const string &str) const {
473  valid_default(str);
474  return str;
475 }
476 
477 
478 
479 bool String::match(const string &str) const {
480  return true;
481 }
482 
483 
484 
485 } // closing namespace Type
486 } // closing namespace Input
487 
488 
489 
static bool is_valid_identifier(const string &key)
Definition: type_base.cc:67
virtual string type_name() const
Returns an identification of the type. Useful for error messages.
Definition: type_base.cc:353
Base of classes for declaring structure of the input data.
Definition: type_base.hh:63
virtual string type_name() const
Returns an identification of the type. Useful for error messages.
Definition: type_base.cc:305
std::size_t content_hash() const override
Definition: type_base.cc:412
std::size_t content_hash() const override
Definition: type_base.cc:363
string desc() const
Definition: type_base.cc:73
std::size_t content_hash() const override
Definition: type_base.cc:278
virtual bool valid_default(const string &str) const
Implements Type::TypeBase::valid_defaults.
Definition: type_base.cc:394
::FilePath::FileType type_
Definition: type_base.hh:494
virtual bool finish()
Finishes initialization of the Array type because of lazy evaluation of type_of_values.
Definition: type_base.cc:151
virtual string full_type_name() const
Implements Type::TypeBase::full_type_name.
Definition: type_base.cc:199
static LazyTypeVector & lazy_type_list()
Definition: type_base.cc:81
bool match(int value) const
Definition: type_base.cc:325
virtual string type_name() const
Returns an identification of the type. Useful for error messages.
Definition: type_base.hh:75
virtual bool operator==(const TypeBase &other) const
Implements Type::TypeBase::operator== Compares also subtypes.
Definition: type_base.cc:205
std::size_t content_hash() const override
Definition: type_base.cc:140
std::size_t content_hash() const override
Definition: type_base.cc:314
virtual bool valid_default(const string &str) const
Implements Type::TypeBase::valid_defaults.
Definition: type_base.cc:345
virtual bool valid_default(const string &str) const
Definition: type_base.cc:212
std::set< const TypeBase * > LazyObjectsSet
Definition: type_base.hh:204
#define ASSERT(...)
Definition: global_defs.h:121
static void lazy_finish()
Finishes all registered lazy types.
Definition: type_base.cc:88
bool match(double value) const
Definition: type_base.cc:374
string from_default(const string &str) const
Definition: type_base.cc:472
#define xprintf(...)
Definition: system.hh:100
virtual string type_name() const
Implements Type::TypeBase::type_name. Name has form array_of_&#39;subtype name&#39;.
Definition: type_base.cc:195
virtual string type_name() const
Returns an identification of the type. Useful for error messages.
Definition: type_base.cc:456
Class for declaration of polymorphic Record.
Definition: type_record.hh:487
static bool was_constructed(const TypeBase *ptr)
Definition: type_base.cc:124
static LazyObjectsSet & lazy_object_set()
Definition: type_base.cc:117
int from_default(const string &str) const
Definition: type_base.cc:331
boost::shared_ptr< ArrayData > data_
Handle to the actual array data.
Definition: type_base.hh:304
virtual bool match(const string &value) const
Definition: type_base.cc:479
bool from_default(const string &str) const
Definition: type_base.cc:293
virtual bool match(const string &str) const
Checks relative output paths.
Definition: type_base.cc:437
Definition: system.hh:72
#define DIR_DELIMITER
Definition: system.hh:56
virtual bool valid_default(const string &str) const
Implements Type::TypeBase::valid_defaults.
Definition: type_base.cc:463
std::ostream & operator<<(std::ostream &stream, const TypeBase &type)
Definition: type_base.cc:130
Class for create text documentation.
Definition: type_output.hh:307
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.cc:269
ARRAY_CONSTRUCT(String)
Record type proxy class.
Definition: type_record.hh:169
virtual string type_name() const
Returns an identification of the type. Useful for error messages.
Definition: type_base.cc:424
Array()
Forbids default constructor in order to prevent empty data_.
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:34
std::size_t content_hash() const override
Definition: type_base.cc:447
Template for classes storing finite set of named values.
virtual string type_name() const
Returns an identification of the type. Useful for error messages.
Definition: type_base.cc:403
virtual bool valid_default(const string &str) const
Definition: type_base.cc:286
double from_default(const string &str) const
Definition: type_base.cc:380