Flow123d  jenkins-Flow123d-linux-release-multijob-282
json_to_storage.cc
Go to the documentation of this file.
1 /*
2  * json_to_storage.cc
3  *
4  * Created on: May 7, 2012
5  * Author: jb
6  */
7 
8 #include <boost/cstdint.hpp>
9 #include <limits>
10 #include <boost/iostreams/device/file.hpp>
11 #include <boost/iostreams/filtering_stream.hpp>
12 
13 #include "json_to_storage.hh"
14 #include "input/comment_filter.hh"
15 
17 
18 namespace Input {
19 using namespace std;
20 using namespace internal;
21 
22 
23 
24 /********************************************
25  * Implementation of internal::JSONPath
26  */
27 
28 
29 JSONPath::JSONPath(const Node& root_node)
30 {
31  path_.push_back( make_pair( (int)(-1), string("/") ) );
32  nodes_.push_back( &root_node );
33 }
34 
35 const JSONPath::Node * JSONPath::down(unsigned int index)
36 {
37  const Node * head_node = nodes_.back();
38  const json_spirit::mArray &array = head_node->get_array(); // the type should be checked in make_storage
39 
40  if ( index >= array.size()) return NULL;
41  path_.push_back( make_pair( index, string("") ) );
42  nodes_.push_back( &( array[index] ) );
43 
44  return nodes_.back();
45 }
46 
47 
48 const JSONPath::Node * JSONPath::down(const string& key)
49 {
50  const Node * head_node = nodes_.back();
51  const json_spirit::mObject &obj = head_node->get_obj(); // the type should be checked in make_storage
52 
53  json_spirit::mObject::const_iterator it = obj.find(key);
54  if (it == obj.end()) {
55  return NULL;
56  } else {
57  path_.push_back( make_pair( (int)(-1), key) );
58  nodes_.push_back( &( it->second ) );
59  }
60  return nodes_.back();
61 }
62 
63 
65 {
66  if (path_.size() > 1) {
67  path_.pop_back();
68  nodes_.pop_back();
69  }
70 }
71 
73  path_.resize(1);
74  nodes_.resize(1);
75 }
76 
77 
78 bool JSONPath::get_ref_from_head(string & ref_address)
79 {
80  const Node * head_node = nodes_.back();
81  if (head_node->type() != json_spirit::obj_type) return false;
82  const json_spirit::mObject &obj = head_node->get_obj();
83  if (obj.size() != 1) return false;
84  if (obj.begin()->first != "REF") return false;
85 
86  const Node &ref_node = obj.begin()->second;
87  if (ref_node.type() != json_spirit::str_type) {
88  THROW( ExcRefOfWrongType() << EI_ErrorAddress(*this) );
89 
90  }
91  ref_address = ref_node.get_str();
92  return true;
93 }
94 
95 
96 /**
97  * This returns path to reference given by address in ref_address.
98  *
99  */
100 JSONPath JSONPath::find_ref_node(const string& ref_address)
101 {
102  namespace ba = boost::algorithm;
103 
104  JSONPath ref_path(*this);
105 
106  string::size_type pos = 0;
107  string::size_type new_pos = 0;
108  string address = ref_address + '/';
109  string tmp_str;
110  bool relative_ref = false;
111 
112  std::set<string>::iterator it = previous_references_.find(ref_address);
113  if (it == previous_references_.end()) {
114  ref_path.previous_references_.insert(ref_address);
115  } else {
116  THROW( ExcReferenceNotFound() << EI_RefAddress(*this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
117  << EI_Specification("cannot follow reference") );
118  }
119 
120  while ( ( new_pos=address.find('/',pos) ) != string::npos ) {
121  tmp_str = address.substr(pos, new_pos - pos);
122  if (pos==0 && tmp_str == "") {
123  // absolute path
124  ref_path.go_to_root();
125 
126  } else if ( ba::all( tmp_str, ba::is_digit()) ) {
127  // integer == index in array
128  if (ref_path.head() -> type() != json_spirit::array_type) {
129  THROW( ExcReferenceNotFound() << EI_RefAddress(*this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
130  << EI_Specification("there should be Array") );
131  }
132 
133  if ( ref_path.down( atoi(tmp_str.c_str()) ) == NULL) {
134  THROW( ExcReferenceNotFound() << EI_RefAddress(*this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
135  << EI_Specification("index out of size of Array") );
136  }
137 
138  } else if (tmp_str == "..") {
139  relative_ref = true;
140  if (ref_path.level() <= 0 ) {
141  THROW( ExcReferenceNotFound() << EI_RefAddress(*this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
142  << EI_Specification("can not go up from root") );
143  }
144  ref_path.up();
145 
146  } else {
147  if (ref_path.head() -> type() != json_spirit::obj_type)
148  THROW( ExcReferenceNotFound() << EI_RefAddress(*this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
149  << EI_Specification("there should be Record") );
150  if ( ref_path.down(tmp_str) == NULL )
151  THROW( ExcReferenceNotFound() << EI_RefAddress(*this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
152  << EI_Specification("key '"+tmp_str+"' not found") );
153  }
154  pos = new_pos+1;
155  }
156  if (relative_ref) {
157  xprintf(Msg, "Referencing '%s' to '%s'.\n", this->str().c_str(), ref_path.str().c_str());
158  }
159  return ref_path;
160 }
161 
162 
163 
164 void JSONPath::output(ostream &stream) const {
165  if (level() == 0) {
166  stream << "/";
167  return;
168  }
169 
170  for(vector< pair<int, string> >::const_iterator it = path_.begin()+1; it != path_.end(); ++it) {
171  if ( it->first < 0 ) {
172  stream << "/" << it->second;
173  } else {
174  stream << "/" << it->first;
175  }
176  }
177 }
178 
179 
180 
181 string JSONPath::str() {
182  stringstream ss;
183  output(ss);
184  return ss.str();
185 }
186 
187 
188 
190  previous_references_.insert(str());
191 }
192 
193 
194 
195 std::ostream& operator<<(std::ostream& stream, const JSONPath& path) {
196  path.output(stream);
197  return stream;
198 }
199 
200 
201 /********************************************
202  * Implementation of public part of JSONToStorage
203  */
204 
206 : storage_(nullptr),
207  root_type_(nullptr)
208 {
209  /* from json_spirit_value.hh:
210  * enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type };
211  */
212  json_type_names.push_back("JSON object");
213  json_type_names.push_back("JSON array");
214  json_type_names.push_back("JSON string");
215  json_type_names.push_back("JSON bool");
216  json_type_names.push_back("JSON int");
217  json_type_names.push_back("JSON real");
218  json_type_names.push_back("JSON null");
219 }
220 
221 
222 
223 JSONToStorage::JSONToStorage(istream &in, const Type::TypeBase &root_type)
224 : JSONToStorage()
225 {
226  read_stream(in,root_type);
227 }
228 
229 
230 
231 JSONToStorage::JSONToStorage( const string &str, const Type::TypeBase &root_type)
232 : JSONToStorage()
233 {
234  try {
235  istringstream is(str);
236  read_stream(is, root_type);
237  } catch (ExcNotJSONFormat &e) {
238  e << EI_File("STRING: "+str); throw;
239  }
240 }
241 
242 
243 
244 void JSONToStorage::read_stream(istream &in, const Type::TypeBase &root_type)
245 {
246  namespace io = boost::iostreams;
247  ASSERT(storage_==nullptr," ");
248 
249  // finish all lazy input types
251 
252  io::filtering_istream filter_in;
253 
254  filter_in.push(uncommenting_filter());
255  filter_in.push(in);
256 
257  JSONPath::Node node;
258 
259 
260  try {
261  json_spirit::read_or_throw( filter_in, node);
262  } catch (json_spirit::Error_position &e ) {
263  THROW( ExcNotJSONFormat() << EI_JSONLine(e.line_) << EI_JSONColumn(e.column_) << EI_JSONReason(e.reason_));
264  }
265 
266  JSONPath root_path(node);
267 
268  root_type_ = &root_type;
269  storage_ = make_storage(root_path, root_type_);
270 
271  ASSERT( storage_ != nullptr, "Internal error in JSON reader, the storage pointer is NULL after reading the stream.\n");
272 }
273 
274 
275 
276 
277 
278 
279 /********************************************
280  * Implementation of private part of JSONToStorage - make_storage dispatch
281  */
282 
283 
285 {
286  ASSERT(type != NULL, "Can not dispatch, NULL pointer to TypeBase.\n");
287 
288  // first check reference
289  string ref_address;
290  if (p.get_ref_from_head(ref_address)) {
291  // todo: mark passed references and check cyclic references
292 
293  // dereference and take data from there
294  JSONPath ref_path = p.find_ref_node(ref_address);
295  return make_storage( ref_path, type );
296  }
297 
298  // return Null storage if there is null on the current location
299  if (p.head()->type() == json_spirit::null_type)
300  return new StorageNull();
301 
302  // dispatch types
303  if (typeid(*type) == typeid(Type::Record)) {
304  return make_storage(p, static_cast<const Type::Record *>(type) );
305  } else
306  if (typeid(*type) == typeid(Type::Array)) {
307  return make_storage(p, static_cast<const Type::Array *>(type) );
308  } else
309  if (typeid(*type) == typeid(Type::Integer)) {
310  return make_storage(p, static_cast<const Type::Integer *>(type) );
311  } else
312  if (typeid(*type) == typeid(Type::Double)) {
313  return make_storage(p, static_cast<const Type::Double *>(type) );
314  } else
315  if (typeid(*type) == typeid(Type::Bool)) {
316  return make_storage(p, static_cast<const Type::Bool *>(type) );
317  } else
318  if (typeid(*type) == typeid(Type::Selection)) {
319  return make_storage(p, static_cast<const Type::Selection *>(type) );
320  } else {
321  const Type::AbstractRecord * abstract_record_type = dynamic_cast<const Type::AbstractRecord *>(type);
322  if (abstract_record_type != NULL ) return make_storage(p, abstract_record_type );
323 
324  const Type::String * string_type = dynamic_cast<const Type::String *>(type);
325  if (string_type != NULL ) return make_storage(p, string_type );
326 
327  // default -> error
328  xprintf(Err,"Unknown descendant of TypeBase class, name: %s\n", typeid(type).name());
329  }
330 
331  return new StorageNull();
332 }
333 
334 
336 {
337  if (p.head()->type() == json_spirit::obj_type) {
338  const json_spirit::mObject & j_map = p.head()->get_obj();
339  std::set<string> keys_to_process;
340  json_spirit::mObject::const_iterator map_it;
341  std::set<string>::iterator set_it;
342 
343  for( map_it = j_map.begin(); map_it != j_map.end(); ++map_it) {
344  keys_to_process.insert(map_it->first);
345  }
346 
347  /*Type::Record::KeyIter key_it;
348  if ( record->has_key_iterator("TYPE", key_it) && record->auto_conversion_key_iter() != record->end() ) {
349  JSONPath type_path(p);
350  if (type_path.down( "TYPE" ) != NULL) {
351  try {
352  if ( type_path.head()->get_str() != record->type_name() ) {
353  xprintf(UsrErr, "Invalid value of TYPE key of record %s.", record->type_name().c_str());
354  }
355  make_storage(type_path, key_it->type_.get() )->get_int();
356  } catch(Type::Selection::ExcSelectionKeyNotFound &e) {
357  return record_automatic_conversion(p, record);
358  }
359  }
360  else { // automatic conversion
361  return record_automatic_conversion(p, record);
362  }
363  }*/
364 
365  StorageArray *storage_array = new StorageArray(record->size());
366  // check individual keys
367  for( Type::Record::KeyIter it= record->begin(); it != record->end(); ++it) {
368  // remove processed key from keys_to_process
369  set_it = keys_to_process.find(it->key_);
370  if (set_it != keys_to_process.end()) {
371  keys_to_process.erase(set_it);
372  }
373 
374  if (p.down(it->key_) != NULL) {
375  // key on input => check & use it
376  storage_array->new_item(it->key_index, make_storage(p, it->type_.get()) );
377  p.up();
378  } else {
379  // key not on input
380  if (it->default_.is_obligatory() ) {
381  THROW( ExcInputError() << EI_Specification("Missing obligatory key '"+ it->key_ +"'.")
382  << EI_ErrorAddress(p) << EI_InputType(record->desc()) );
383  } else if (it->default_.has_value_at_declaration() ) {
384  storage_array->new_item(it->key_index,
385  make_storage_from_default( it->default_.value(), it->type_.get() ) );
386  } else { // defalut - optional or default at read time
387  // set null
388  storage_array->new_item(it->key_index, new StorageNull() );
389  }
390  }
391  }
392 
393  for( set_it = keys_to_process.begin(); set_it != keys_to_process.end(); ++set_it) {
394  xprintf(Warn, "Unprocessed key '%s' in record '%s'.\n", (*set_it).c_str(), p.str().c_str() );
395  }
396 
397  return storage_array;
398 
399  } else { // automatic conversion
400  return record_automatic_conversion(p, record);
401  }
402  // possibly construction of reduced record
403 }
404 
405 
407 {
408  Type::Record::KeyIter auto_key_it = record->auto_conversion_key_iter();
409  if ( auto_key_it != record->end() ) {
410  try {
411  StorageArray *storage_array = new StorageArray(record->size());
412  for( Type::Record::KeyIter it= record->begin(); it != record->end(); ++it) {
413  if ( it == auto_key_it ) {
414  // one key is initialized by input
415  storage_array->new_item(it->key_index, make_storage(p, it->type_.get()) );
416  } else if (it->default_.has_value_at_declaration() ) {
417  // other key from default values
418  storage_array->new_item(it->key_index,
419  make_storage_from_default( it->default_.value(), it->type_.get() ) );
420  } else { // defalut - optional or default at read time
421  ASSERT( ! it->default_.is_obligatory() ,
422  "Obligatory key: '%s' in auto-convertible record, wrong check during finish().", it->key_.c_str());
423  // set null
424  storage_array->new_item(it->key_index, new StorageNull() );
425  }
426  }
427 
428  return storage_array;
429  } catch (ExcInputError &e ) {
430  THROW( ExcAutomaticConversionError() << EI_RecordName(record->type_name()) << EI_InputErrorMessage(e.what()) );
431  }
432 
433  } else {
434  THROW( ExcInputError() << EI_Specification("The value should be 'JSON object', but we found: ")
435  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType( record->desc()) );
436  }
437 
438  return NULL;
439 }
440 
441 
442 
444 {
445  if (p.head()->type() == json_spirit::obj_type) {
446 
447  JSONPath type_path(p);
448  if ( type_path.down("TYPE") == NULL ) {
449  if ( ! abstr_rec->begin()->default_.has_value_at_declaration() ) {
450  THROW( ExcInputError() << EI_Specification("Missing key 'TYPE' in AbstractRecord.") << EI_ErrorAddress(p) << EI_InputType(abstr_rec->desc()) );
451  } else { // auto conversion
452  return abstract_rec_automatic_conversion(p, abstr_rec);
453  }
454  } else {
455  try {
456  // convert to base type to force type dispatch and reference chatching
457  const Type::TypeBase * type_of_type = &( abstr_rec->get_type_selection() );
458  unsigned int descendant_index = make_storage(type_path, type_of_type )->get_int();
459  return make_storage(p, &( abstr_rec->get_descendant(descendant_index) ) );
460  } catch(Type::Selection::ExcSelectionKeyNotFound &e) {
461 
462  THROW( ExcInputError() << EI_Specification("Wrong TYPE='"+Type::EI_KeyName::ref(e)+"' of AbstractRecord.") << EI_ErrorAddress(p) << EI_InputType(abstr_rec->desc()) );
463  }
464  }
465  } else {
466  if ( ! abstr_rec->begin()->default_.has_value_at_declaration() ) {
467  THROW( ExcInputError() << EI_Specification("The value should be 'JSON object', but we found: ")
468  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(abstr_rec->desc()) );
469  } else { // auto conversion
470  return abstract_rec_automatic_conversion(p, abstr_rec);
471  }
472  }
473 
474  return NULL;
475 }
476 
477 
478 
480 {
481  // perform automatic conversion
482  const Type::Record *default_child = abstr_rec->get_default_descendant();
483  if (! default_child) THROW(ExcInputError()
484  << EI_Specification("Auto conversion of AbstractRecord not allowed.\n")
485  << EI_ErrorAddress(p)
486  << EI_InputType(abstr_rec->desc())
487  );
488  return make_storage(p, default_child );
489 }
490 
491 
492 
494 {
495 
496  if (p.head()->type() == json_spirit::array_type) {
497  const json_spirit::mArray & j_array = p.head()->get_array();
498  if ( array->match_size( j_array.size() ) ) {
499  // copy the array and check type of values
500  StorageArray *storage_array = new StorageArray(j_array.size());
501  for( unsigned int idx=0; idx < j_array.size(); idx++) {
502  p.down(idx);
503  const Type::TypeBase &sub_type = array->get_sub_type();
504  storage_array->new_item(idx, make_storage(p, &sub_type) );
505  p.up();
506  }
507  return storage_array;
508 
509  } else {
510  THROW( ExcInputError()
511  << EI_Specification("Do not fit into size limits of the Array.")
512  << EI_ErrorAddress(p) << EI_InputType(array->desc()) );
513  }
514  } else {
515  // try automatic conversion to array with one element
516  if ( array->match_size( 1 ) ) {
517  StorageArray *storage_array = new StorageArray(1);
518  const Type::TypeBase &sub_type = array->get_sub_type();
519  storage_array->new_item(0, make_storage(p, &sub_type) );
520 
521  return storage_array;
522  } else {
523  THROW( ExcInputError() << EI_Specification("Automatic conversion to array not allowed. The value should be 'JSON array', but we found: ")
524  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(array->desc()) );
525  }
526  }
527 
528  return NULL;
529 }
530 
531 
532 
534 {
535  string item_name;
536  if (p.head()->type() == json_spirit::str_type) {
537  try {
538  item_name = p.head()->get_str();
539  int value = selection->name_to_int( item_name );
540  return new StorageInt( value );
541  } catch (Type::Selection::ExcSelectionKeyNotFound &exc) {
542  THROW( ExcInputError() << EI_Specification("Wrong value '" + item_name + "' of the Selection.")
543  << EI_ErrorAddress(p) << EI_JSON_Type( "" ) << EI_InputType(selection->desc()) );
544  }
545  }
546 
547  THROW( ExcInputError() << EI_Specification("The value should be 'JSON string', but we found: ")
548  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(selection->desc()) );
549 
550  return NULL;
551 }
552 
553 
554 
556 {
557  if (p.head()->type() == json_spirit::bool_type) {
558  return new StorageBool( p.head()->get_bool() );
559  } else {
560  THROW( ExcInputError() << EI_Specification("The value should be 'JSON bool', but we found: ")
561  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(bool_type->desc()) );
562  }
563  return NULL;
564 }
565 
566 
567 
569 {
570  if (p.head()->type() == json_spirit::int_type) {
571  boost::int64_t value = p.head()->get_int64();
572 
573  if ( value >= std::numeric_limits<int>::min() &&
574  value <= std::numeric_limits<int>::max() &&
575  int_type->match(value) )
576  {
577  return new StorageInt( value );
578  } else {
579  THROW( ExcInputError() << EI_Specification("Value out of bounds.") << EI_ErrorAddress(p) << EI_InputType(int_type->desc()) );
580  }
581 
582  } else {
583  THROW( ExcInputError() << EI_Specification("The value should be 'JSON int', but we found: ")
584  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(int_type->desc()) );
585 
586  }
587  return NULL;
588 }
589 
590 
591 
593 {
594  double value;
595 
596  auto value_type = p.head()->type();
597  if ( value_type== json_spirit::real_type
598  || value_type == json_spirit::int_type) {
599  value = p.head()->get_real();
600  } else {
601  THROW( ExcInputError() << EI_Specification("The value should be 'JSON real', but we found: ")
602  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(double_type->desc()) );
603  }
604 
605  if (double_type->match(value)) {
606  return new StorageDouble( value );
607  } else {
608  THROW( ExcInputError() << EI_Specification("Value out of bounds.") << EI_ErrorAddress(p) << EI_InputType(double_type->desc()) );
609  }
610 
611  return NULL;
612 }
613 
614 
615 
617 {
618  if (p.head()->type() == json_spirit::str_type) {
619  string value = p.head()->get_str();
620  if (string_type->match(value))
621  return new StorageString( value );
622  else
623  THROW( ExcInputError() << EI_Specification("Output file can not be given by absolute path: '" + value + "'")
624  << EI_ErrorAddress(p) << EI_JSON_Type("") << EI_InputType(string_type->desc()) );
625  } else {
626  THROW( ExcInputError() << EI_Specification("The value should be 'JSON string', but we found: ")
627  << EI_ErrorAddress(p) << EI_JSON_Type( json_type_names[ p.head()->type() ] ) << EI_InputType(string_type->desc()) );
628 
629  }
630  return NULL;
631 }
632 
633 
634 
636  try {
637  /*
638  // Possible simplification of this method (need default strings to be valid JSON)
639  JSONToStorage tmp_storage(dflt_str, *type);
640  return tmp_storage.storage_;
641  */
642 
643  // an auto-convertible AbstractRecord can be initialized form default value
644  const Type::AbstractRecord *a_record = dynamic_cast<const Type::AbstractRecord *>(type);
645  if (a_record != NULL ) {
646  if (a_record->begin()->default_.has_value_at_declaration() ) // a_record->bagin() ... TYPE key
647  return make_storage_from_default( dflt_str, a_record->get_default_descendant() );
648  else
649  xprintf(PrgErr,"Can not initialize (non-auto-convertible) AbstractRecord '%s' by default value\n", type->type_name().c_str());
650  } else
651  if (typeid(*type) == typeid(Type::Record) ) {
652  // an auto-convertible Record can be initialized form default value
653  const Type::Record *record = static_cast<const Type::Record *>(type);
654  Type::Record::KeyIter auto_key_it = record->auto_conversion_key_iter();
655  if ( auto_key_it != record->end() ) {
656  StorageArray *storage_array = new StorageArray(record->size());
657  for( Type::Record::KeyIter it= record->begin(); it != record->end(); ++it) {
658  if ( it == auto_key_it ) {
659  // one key is initialized by the record default string
660  storage_array->new_item(it->key_index, make_storage_from_default(dflt_str, it->type_.get()) );
661  } else {
662 
663  ASSERT( ! it->default_.is_obligatory(),
664  "Missing default value for key: '%s' in auto-convertible record, wrong check during finish().", it->key_.c_str());
665 
666  if (it->default_.has_value_at_declaration() ) {
667  storage_array->new_item(it->key_index,
668  make_storage_from_default( it->default_.value(), it->type_.get() ) );
669  } else { // defalut - optional or default at read time
670  // set null
671  storage_array->new_item(it->key_index, new StorageNull() );
672  }
673  }
674  }
675 
676  return storage_array;
677  } else {
678  xprintf(PrgErr,"Can not initialize (non-auto-convertible) Record '%s' by default value\n", type->type_name().c_str());
679  }
680  } else
681  if (typeid(*type) == typeid(Type::Array) ) {
682  const Type::Array *array = static_cast<const Type::Array *>(type);
683  if ( array->match_size(1) ) {
684  // try auto conversion to array
685  StorageArray *storage_array = new StorageArray(1);
686  const Type::TypeBase &sub_type = array->get_sub_type();
687  storage_array->new_item(0, make_storage_from_default(dflt_str, &sub_type) );
688  return storage_array;
689  } else {
690  xprintf(PrgErr,"Can not initialize Array '%s' by default value, size 1 not allowed.\n", type->type_name().c_str());
691  }
692 
693  } else
694  if (typeid(*type) == typeid(Type::Integer)) {
695  return new StorageInt( static_cast<const Type::Integer *>(type) ->from_default(dflt_str) );
696  } else
697  if (typeid(*type) == typeid(Type::Double)) {
698  return new StorageDouble( static_cast<const Type::Double *>(type) ->from_default(dflt_str) );
699  } else
700  if (typeid(*type) == typeid(Type::Bool)) {
701  return new StorageBool( static_cast<const Type::Bool *>(type) ->from_default(dflt_str) );
702  } else
703  if (typeid(*type) == typeid(Type::Selection)) {
704  return new StorageInt( static_cast<const Type::Selection *>(type) ->from_default(dflt_str) );
705  } else {
706  const Type::String * string_type = dynamic_cast<const Type::String *>(type);
707  if (string_type != NULL ) return new StorageString( string_type->from_default(dflt_str) );
708 
709  // default error
710  xprintf(PrgErr,"Can not store default value for type: %s\n", typeid(type).name());
711  }
712 
713 
714  } catch (Input::Type::ExcWrongDefault & e) {
715  // message to distinguish exceptions thrown during Default value check at declaration
716  xprintf(Msg, "Wrong default value while reading an input stream:\n");
717  e << EI_KeyName("UNKNOWN KEY");
718  throw;
719  }
720 
721  return NULL;
722 }
723 
724 
725 
726 } // namespace Input
const Record * get_default_descendant() const
Definition: type_record.cc:614
Base of classes for declaring structure of the input data.
Definition: type_base.hh:63
Base class for nodes of a data storage tree.
Definition: storage.hh:57
StorageBase * make_storage_from_default(const string &dflt_str, const Type::TypeBase *type)
boost::int64_t get_int64() const
std::vector< struct Key >::const_iterator KeyIter
Definition: type_record.hh:200
StorageBase * abstract_rec_automatic_conversion(JSONPath &p, const Type::AbstractRecord *abstr_rec)
io::finite_state_filter< uncommenting_fsm > uncommenting_filter
std::set< string > previous_references_
Definition: system.hh:72
unsigned int size() const
Definition: type_record.hh:754
bool get_ref_from_head(string &ref_address)
string desc() const
Definition: type_base.cc:73
vector< string > json_type_names
std::ostream & operator<<(std::ostream &stream, const Address &address)
Definition: accessors.hh:288
JSONPath(const Node &root_node)
Class for declaration of the input of type Bool.
Definition: type_base.hh:332
void output(ostream &stream) const
int name_to_int(const string &key) const
StorageBase * record_automatic_conversion(JSONPath &p, const Type::Record *record)
JSONPath find_ref_node(const string &ref_address)
bool match(int value) const
Definition: type_base.cc:325
const Selection & get_type_selection() const
Definition: type_record.cc:626
virtual string type_name() const
Record type name getter.
Definition: type_record.cc:321
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 integral input data.
Definition: type_base.hh:355
KeyIter begin() const
Definition: type_record.hh:731
Class for declaration of inputs sequences.
Definition: type_base.hh:239
void read_or_throw(const std::string &s, mValue &value)
virtual int get_int() const
Definition: storage.cc:19
int level() const
const Type::TypeBase * root_type_
Root of the declaration tree of the data in the storage.
#define ASSERT(...)
Definition: global_defs.h:121
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:392
Definition: system.hh:72
static void lazy_finish()
Finishes all registered lazy types.
Definition: type_base.cc:88
const String_type & get_str() const
StorageBase * storage_
Storage of the read and checked input data.
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
StorageBase * make_storage(JSONPath &p, const Type::TypeBase *type)
Class for declaration of polymorphic Record.
Definition: type_record.hh:487
bool match_size(unsigned int size) const
Checks size of particular array.
Definition: type_base.hh:282
void new_item(unsigned int index, StorageBase *item)
Definition: storage.cc:91
Value_type type() const
const Array & get_array() const
virtual bool match(const string &value) const
Definition: type_base.cc:479
const Node * down(unsigned int index)
const Node * head() const
Definition: system.hh:72
KeyIter end() const
Definition: type_record.hh:739
const TypeBase & get_sub_type() const
Getter for the type of array items.
Definition: type_base.hh:277
Definition: system.hh:72
Record type proxy class.
Definition: type_record.hh:169
const Object & get_obj() const
const Record & get_descendant(const string &name) const
Definition: type_record.cc:597
Reader for (slightly) modified JSON files.
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:34
Template for classes storing finite set of named values.
Class used by JSONToStorage class to iterate over the JSON tree provided by json_spirit library...
KeyIter auto_conversion_key_iter() const
Definition: type_record.cc:354
void read_stream(istream &in, const Type::TypeBase &root_type)