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