8 #include <boost/iostreams/device/file.hpp>
9 #include <boost/iostreams/filtering_stream.hpp>
18 using namespace internal;
29 path_.push_back( make_pair( (
int)(-1),
string(
"/") ) );
30 nodes_.push_back( &root_node );
35 const Node * head_node = nodes_.back();
38 if ( index >= array.size())
return NULL;
39 path_.push_back( make_pair( index,
string(
"") ) );
40 nodes_.push_back( &( array[index] ) );
48 const Node * head_node = nodes_.back();
51 json_spirit::mObject::const_iterator it = obj.find(key);
52 if (it == obj.end()) {
55 path_.push_back( make_pair( (
int)(-1), key) );
56 nodes_.push_back( &( it->second ) );
64 if (path_.size() > 1) {
78 const Node * head_node = nodes_.back();
81 if (obj.size() != 1)
return false;
82 if (obj.begin()->first !=
"REF")
return false;
84 const Node &ref_node = obj.begin()->second;
86 THROW( ExcRefOfWrongType() << EI_ErrorAddress(*
this) );
89 ref_address = ref_node.
get_str();
100 namespace ba = boost::algorithm;
104 string::size_type pos = 0;
105 string::size_type new_pos = 0;
106 string address = ref_address +
'/';
108 bool relative_ref =
false;
110 std::set<string>::iterator it = previous_references_.find(ref_address);
111 if (it == previous_references_.end()) {
114 THROW( ExcReferenceNotFound() << EI_RefAddress(*
this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
115 << EI_Specification(
"cannot follow reference") );
118 while ( ( new_pos=address.find(
'/',pos) ) != string::npos ) {
119 tmp_str = address.substr(pos, new_pos - pos);
121 if (pos==0 && tmp_str ==
"") {
125 }
else if ( ba::all( tmp_str, ba::is_digit()) ) {
128 THROW( ExcReferenceNotFound() << EI_RefAddress(*
this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
129 << EI_Specification(
"there should be Array") );
132 if ( ref_path.
down( atoi(tmp_str.c_str()) ) == NULL) {
133 THROW( ExcReferenceNotFound() << EI_RefAddress(*
this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
134 << EI_Specification(
"index out of size of Array") );
137 }
else if (tmp_str ==
"..") {
139 if (ref_path.
level() <= 0 ) {
140 THROW( ExcReferenceNotFound() << EI_RefAddress(*
this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
141 << EI_Specification(
"can not go up from root") );
147 THROW( ExcReferenceNotFound() << EI_RefAddress(*
this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
148 << EI_Specification(
"there should be Record") );
149 if ( ref_path.
down(tmp_str) == NULL )
150 THROW( ExcReferenceNotFound() << EI_RefAddress(*
this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
151 << EI_Specification(
"key '"+tmp_str+
"' not found") );
156 xprintf(
Msg,
"Key '%s' is set to value of key '%s'\n", this->str().c_str(), ref_path.
str().c_str());
169 for(
vector< pair<int, string> >::const_iterator it = path_.begin()+1; it != path_.end(); ++it) {
170 if ( it->first < 0 ) {
171 stream <<
"/" << it->second;
173 stream <<
"/" << it->first;
189 previous_references_.insert(str());
238 istringstream is(str);
240 }
catch (ExcNotJSONFormat &e) {
241 e << EI_File(
"STRING: "+str);
throw;
249 namespace io = boost::iostreams;
255 io::filtering_istream filter_in;
274 ASSERT(
storage_ !=
nullptr,
"Internal error in JSON reader, the storage pointer is NULL after reading the stream.\n");
289 ASSERT(type != NULL,
"Can not dispatch, NULL pointer to TypeBase.\n");
308 return make_storage(p, static_cast<const Type::Record *>(type) );
311 return make_storage(p, static_cast<const Type::Array *>(type) );
314 return make_storage(p, static_cast<const Type::Integer *>(type) );
317 return make_storage(p, static_cast<const Type::Double *>(type) );
320 return make_storage(p, static_cast<const Type::Bool *>(type) );
323 return make_storage(p, static_cast<const Type::Selection *>(type) );
326 if (abstract_record_type != NULL )
return make_storage(p, abstract_record_type );
329 if (string_type != NULL )
return make_storage(p, string_type );
332 xprintf(
Err,
"Unknown descendant of TypeBase class, name: %s\n",
typeid(type).name());
343 std::set<string> keys_to_processed;
344 json_spirit::mObject::const_iterator map_it;
345 std::set<string>::iterator set_it;
347 for( map_it = j_map.begin(); map_it != j_map.end(); ++map_it) {
348 keys_to_processed.insert(map_it->first);
355 set_it = keys_to_processed.find(it->key_);
356 if (set_it != keys_to_processed.end()) {
357 keys_to_processed.erase(set_it);
360 if (p.
down(it->key_) != NULL) {
366 if (it->default_.is_obligatory() ) {
367 THROW( ExcInputError() << EI_Specification(
"Missing obligatory key '"+ it->key_ +
"'.")
368 << EI_ErrorAddress(p) << EI_InputType(record->
desc()) );
369 }
else if (it->default_.has_value_at_declaration() ) {
370 storage_array->
new_item(it->key_index,
379 for( set_it = keys_to_processed.begin(); set_it != keys_to_processed.end(); ++set_it) {
380 xprintf(
Warn,
"Key '%s' in record '%s' was not retrieved from input JSON file.\n", (*set_it).c_str(), record->
type_name().c_str() );
383 return storage_array;
389 if ( auto_key_it != record->
end() ) {
397 if ( it == auto_key_it ) {
400 }
else if (it->default_.has_value_at_declaration() ) {
402 storage_array->
new_item(it->key_index,
405 ASSERT( ! it->default_.is_obligatory() ,
406 "Obligatory key: '%s' in auto-convertible record, wrong check during finish().", it->key_.c_str());
412 return storage_array;
415 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON object', but we found: ")
431 if ( type_path.
down(
"TYPE") == NULL ) {
432 if ( ! abstr_rec->
begin()->default_.has_value_at_declaration() ) {
433 THROW( ExcInputError() << EI_Specification(
"Missing key 'TYPE' in AbstractRecord.") << EI_ErrorAddress(p) << EI_InputType(abstr_rec->
desc()) );
441 }
catch(Type::Selection::ExcSelectionKeyNotFound &e) {
443 THROW( ExcInputError() << EI_Specification(
"Wrong TYPE='"+Type::EI_KeyName::ref(e)+
"' of AbstractRecord.") << EI_ErrorAddress(p) << EI_InputType(abstr_rec->
desc()) );
447 if ( ! abstr_rec->
begin()->default_.has_value_at_declaration() ) {
448 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON object', but we found: ")
459 if (! default_child)
THROW(ExcInputError()
460 << EI_Specification(
"Auto conversion of AbstractRecord not allowed.\n")
461 << EI_ErrorAddress(p)
462 << EI_InputType(abstr_rec->
desc())
477 for(
unsigned int idx=0; idx < j_array.size(); idx++) {
483 return storage_array;
486 THROW( ExcInputError()
487 << EI_Specification(
"Do not fit into size limits of the Array.")
488 << EI_ErrorAddress(p) << EI_InputType(array->
desc()) );
497 return storage_array;
499 THROW( ExcInputError() << EI_Specification(
"Automatic conversion to array not allowed. The value should be 'JSON array', but we found: ")
517 }
catch (Type::Selection::ExcSelectionKeyNotFound &exc) {
518 THROW( ExcInputError() << EI_Specification(
"Wrong value '" + item_name +
"' of the Selection.")
519 << EI_ErrorAddress(p) << EI_JSON_Type(
"" ) << EI_InputType(selection->
desc()) );
523 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON string', but we found: ")
536 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON bool', but we found: ")
548 int_type->
match(value);
549 if (int_type->
match(value)) {
552 THROW( ExcInputError() << EI_Specification(
"Value out of bounds.") << EI_ErrorAddress(p) << EI_InputType(int_type->
desc()) );
556 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON int', but we found: ")
574 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON real', but we found: ")
578 if (double_type->
match(value)) {
581 THROW( ExcInputError() << EI_Specification(
"Value out of bounds.") << EI_ErrorAddress(p) << EI_InputType(double_type->
desc()) );
593 if (string_type->
match(value))
596 THROW( ExcInputError() << EI_Specification(
"Output file can not be given by absolute path: '" + value +
"'")
597 << EI_ErrorAddress(p) << EI_JSON_Type(
"") << EI_InputType(string_type->
desc()) );
599 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON string', but we found: ")
618 if (a_record != NULL ) {
619 if (a_record->
begin()->default_.has_value_at_declaration() )
622 xprintf(
PrgErr,
"Can not initialize (non-auto-convertible) AbstractRecord '%s' by default value\n", type->
type_name().c_str());
628 if ( auto_key_it != record->
end() ) {
631 if ( it == auto_key_it ) {
636 ASSERT( ! it->default_.is_obligatory(),
637 "Missing default value for key: '%s' in auto-convertible record, wrong check during finish().", it->key_.c_str());
639 if (it->default_.has_value_at_declaration() ) {
640 storage_array->
new_item(it->key_index,
649 return storage_array;
651 xprintf(
PrgErr,
"Can not initialize (non-auto-convertible) Record '%s' by default value\n", type->
type_name().c_str());
661 return storage_array;
663 xprintf(
PrgErr,
"Can not initialize Array '%s' by default value, size 1 not allowed.\n", type->
type_name().c_str());
668 return new StorageInt( static_cast<const Type::Integer *>(type) ->from_default(dflt_str) );
671 return new StorageDouble( static_cast<const Type::Double *>(type) ->from_default(dflt_str) );
674 return new StorageBool( static_cast<const Type::Bool *>(type) ->from_default(dflt_str) );
677 return new StorageInt( static_cast<const Type::Selection *>(type) ->from_default(dflt_str) );
683 xprintf(
PrgErr,
"Can not store default value for type: %s\n",
typeid(type).name());
687 }
catch (Input::Type::ExcWrongDefault & e) {
689 xprintf(
Msg,
"Wrong default value while reading an input stream:\n");
690 e << EI_KeyName(
"UNKNOWN KEY");