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);
120 if (pos==0 && tmp_str ==
"") {
124 }
else if ( ba::all( tmp_str, ba::is_digit()) ) {
127 THROW( ExcReferenceNotFound() << EI_RefAddress(*
this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
128 << EI_Specification(
"there should be Array") );
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") );
136 }
else if (tmp_str ==
"..") {
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") );
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") );
155 xprintf(
Msg,
"Key '%s' is set to value of key '%s'\n", this->str().c_str(), ref_path.
str().c_str());
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;
172 stream <<
"/" << it->first;
188 previous_references_.insert(str());
233 istringstream is(str);
235 }
catch (ExcNotJSONFormat &e) {
236 e << EI_File(
"STRING: "+str);
throw;
244 namespace io = boost::iostreams;
250 io::filtering_istream filter_in;
269 ASSERT(
storage_ !=
nullptr,
"Internal error in JSON reader, the storage pointer is NULL after reading the stream.\n");
284 ASSERT(type != NULL,
"Can not dispatch, NULL pointer to TypeBase.\n");
302 return make_storage(p, static_cast<const Type::Record *>(type) );
305 return make_storage(p, static_cast<const Type::Array *>(type) );
308 return make_storage(p, static_cast<const Type::Integer *>(type) );
311 return make_storage(p, static_cast<const Type::Double *>(type) );
314 return make_storage(p, static_cast<const Type::Bool *>(type) );
317 return make_storage(p, static_cast<const Type::Selection *>(type) );
320 if (abstract_record_type != NULL )
return make_storage(p, abstract_record_type );
323 if (string_type != NULL )
return make_storage(p, string_type );
326 xprintf(
Err,
"Unknown descendant of TypeBase class, name: %s\n",
typeid(type).name());
337 std::set<string> keys_to_processed;
338 json_spirit::mObject::const_iterator map_it;
339 std::set<string>::iterator set_it;
341 for( map_it = j_map.begin(); map_it != j_map.end(); ++map_it) {
342 keys_to_processed.insert(map_it->first);
349 set_it = keys_to_processed.find(it->key_);
350 if (set_it != keys_to_processed.end()) {
351 keys_to_processed.erase(set_it);
354 if (p.
down(it->key_) != NULL) {
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,
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() );
377 return storage_array;
383 if ( auto_key_it != record->
end() ) {
387 if ( it == auto_key_it ) {
390 }
else if (it->default_.has_value_at_declaration() ) {
392 storage_array->
new_item(it->key_index,
395 ASSERT( ! it->default_.is_obligatory() ,
396 "Obligatory key: '%s' in auto-convertible record, wrong check during finish().", it->key_.c_str());
402 return storage_array;
405 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON object', but we found: ")
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()) );
431 }
catch(Type::Selection::ExcSelectionKeyNotFound &e) {
433 THROW( ExcInputError() << EI_Specification(
"Wrong TYPE='"+Type::EI_KeyName::ref(e)+
"' of AbstractRecord.") << EI_ErrorAddress(p) << EI_InputType(abstr_rec->
desc()) );
437 if ( ! abstr_rec->
begin()->default_.has_value_at_declaration() ) {
438 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON object', but we found: ")
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())
463 for(
unsigned int idx=0; idx < j_array.size(); idx++) {
469 return storage_array;
472 THROW( ExcInputError()
473 << EI_Specification(
"Do not fit into size limits of the Array.")
474 << EI_ErrorAddress(p) << EI_InputType(array->
desc()) );
483 return storage_array;
485 THROW( ExcInputError() << EI_Specification(
"Automatic conversion to array not allowed. The value should be 'JSON array', but we found: ")
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()) );
509 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON string', but we found: ")
522 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON bool', but we found: ")
534 int_type->
match(value);
535 if (int_type->
match(value)) {
538 THROW( ExcInputError() << EI_Specification(
"Value out of bounds.") << EI_ErrorAddress(p) << EI_InputType(int_type->
desc()) );
542 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON int', but we found: ")
560 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON real', but we found: ")
564 if (double_type->
match(value)) {
567 THROW( ExcInputError() << EI_Specification(
"Value out of bounds.") << EI_ErrorAddress(p) << EI_InputType(double_type->
desc()) );
579 if (string_type->
match(value))
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()) );
585 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON string', but we found: ")
604 if (a_record != NULL ) {
605 if (a_record->
begin()->default_.has_value_at_declaration() )
608 xprintf(
PrgErr,
"Can not initialize (non-auto-convertible) AbstractRecord '%s' by default value\n", type->
type_name().c_str());
614 if ( auto_key_it != record->
end() ) {
617 if ( it == auto_key_it ) {
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());
625 if (it->default_.has_value_at_declaration() ) {
626 storage_array->
new_item(it->key_index,
635 return storage_array;
637 xprintf(
PrgErr,
"Can not initialize (non-auto-convertible) Record '%s' by default value\n", type->
type_name().c_str());
647 return storage_array;
649 xprintf(
PrgErr,
"Can not initialize Array '%s' by default value, size 1 not allowed.\n", type->
type_name().c_str());
654 return new StorageInt( static_cast<const Type::Integer *>(type) ->from_default(dflt_str) );
657 return new StorageDouble( static_cast<const Type::Double *>(type) ->from_default(dflt_str) );
660 return new StorageBool( static_cast<const Type::Bool *>(type) ->from_default(dflt_str) );
663 return new StorageInt( static_cast<const Type::Selection *>(type) ->from_default(dflt_str) );
669 xprintf(
PrgErr,
"Can not store default value for type: %s\n",
typeid(type).name());
673 }
catch (Input::Type::ExcWrongDefault & e) {
675 xprintf(
Msg,
"Wrong default value while reading an input stream:\n");
676 e << EI_KeyName(
"UNKNOWN KEY");
void read_or_throw(const std::string &s, mValue &value)
const String_type & get_str() const
const Array & get_array() const
const Object & get_obj() const
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.