8 #include <boost/cstdint.hpp>
10 #include <boost/iostreams/device/file.hpp>
11 #include <boost/iostreams/filtering_stream.hpp>
20 using namespace internal;
31 path_.push_back( make_pair( (
int)(-1),
string(
"/") ) );
32 nodes_.push_back( &root_node );
37 const Node * head_node = nodes_.back();
40 if ( index >= array.size())
return NULL;
41 path_.push_back( make_pair( index,
string(
"") ) );
42 nodes_.push_back( &( array[index] ) );
50 const Node * head_node = nodes_.back();
53 json_spirit::mObject::const_iterator it = obj.find(key);
54 if (it == obj.end()) {
57 path_.push_back( make_pair( (
int)(-1), key) );
58 nodes_.push_back( &( it->second ) );
66 if (path_.size() > 1) {
80 const Node * head_node = nodes_.back();
83 if (obj.size() != 1)
return false;
84 if (obj.begin()->first !=
"REF")
return false;
86 const Node &ref_node = obj.begin()->second;
88 THROW( ExcRefOfWrongType() << EI_ErrorAddress(*
this) );
91 ref_address = ref_node.
get_str();
102 namespace ba = boost::algorithm;
106 string::size_type pos = 0;
107 string::size_type new_pos = 0;
108 string address = ref_address +
'/';
110 bool relative_ref =
false;
112 std::set<string>::iterator it = previous_references_.find(ref_address);
113 if (it == previous_references_.end()) {
116 THROW( ExcReferenceNotFound() << EI_RefAddress(*
this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
117 << EI_Specification(
"cannot follow reference") );
120 while ( ( new_pos=address.find(
'/',pos) ) != string::npos ) {
121 tmp_str = address.substr(pos, new_pos - pos);
122 if (pos==0 && tmp_str ==
"") {
126 }
else if ( ba::all( tmp_str, ba::is_digit()) ) {
129 THROW( ExcReferenceNotFound() << EI_RefAddress(*
this) << EI_ErrorAddress(ref_path) << EI_RefStr(ref_address)
130 << EI_Specification(
"there should be Array") );
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") );
138 }
else if (tmp_str ==
"..") {
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") );
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") );
157 xprintf(
Msg,
"Referencing '%s' to '%s'.\n", this->str().c_str(), ref_path.
str().c_str());
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;
174 stream <<
"/" << it->first;
190 previous_references_.insert(str());
235 istringstream is(str);
237 }
catch (ExcNotJSONFormat &e) {
238 e << EI_File(
"STRING: "+str);
throw;
246 namespace io = boost::iostreams;
252 io::filtering_istream filter_in;
271 ASSERT(
storage_ !=
nullptr,
"Internal error in JSON reader, the storage pointer is NULL after reading the stream.\n");
286 ASSERT(type != NULL,
"Can not dispatch, NULL pointer to TypeBase.\n");
304 return make_storage(p, static_cast<const Type::Record *>(type) );
307 return make_storage(p, static_cast<const Type::Array *>(type) );
310 return make_storage(p, static_cast<const Type::Integer *>(type) );
313 return make_storage(p, static_cast<const Type::Double *>(type) );
316 return make_storage(p, static_cast<const Type::Bool *>(type) );
319 return make_storage(p, static_cast<const Type::Selection *>(type) );
322 if (abstract_record_type != NULL )
return make_storage(p, abstract_record_type );
325 if (string_type != NULL )
return make_storage(p, string_type );
328 xprintf(
Err,
"Unknown descendant of TypeBase class, name: %s\n",
typeid(type).name());
339 std::set<string> keys_to_process;
340 json_spirit::mObject::const_iterator map_it;
341 std::set<string>::iterator set_it;
343 for( map_it = j_map.begin(); map_it != j_map.end(); ++map_it) {
344 keys_to_process.insert(map_it->first);
369 set_it = keys_to_process.find(it->key_);
370 if (set_it != keys_to_process.end()) {
371 keys_to_process.erase(set_it);
374 if (p.
down(it->key_) != NULL) {
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,
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() );
397 return storage_array;
409 if ( auto_key_it != record->
end() ) {
413 if ( it == auto_key_it ) {
416 }
else if (it->default_.has_value_at_declaration() ) {
418 storage_array->
new_item(it->key_index,
421 ASSERT( ! it->default_.is_obligatory() ,
422 "Obligatory key: '%s' in auto-convertible record, wrong check during finish().", it->key_.c_str());
428 return storage_array;
429 }
catch (ExcInputError &e ) {
430 THROW( ExcAutomaticConversionError() << EI_RecordName(record->
type_name()) << EI_InputErrorMessage(e.what()) );
434 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON object', but we found: ")
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()) );
460 }
catch(Type::Selection::ExcSelectionKeyNotFound &e) {
462 THROW( ExcInputError() << EI_Specification(
"Wrong TYPE='"+Type::EI_KeyName::ref(e)+
"' of AbstractRecord.") << EI_ErrorAddress(p) << EI_InputType(abstr_rec->
desc()) );
466 if ( ! abstr_rec->
begin()->default_.has_value_at_declaration() ) {
467 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON object', but we found: ")
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())
501 for(
unsigned int idx=0; idx < j_array.size(); idx++) {
507 return storage_array;
510 THROW( ExcInputError()
511 << EI_Specification(
"Do not fit into size limits of the Array.")
512 << EI_ErrorAddress(p) << EI_InputType(array->
desc()) );
521 return storage_array;
523 THROW( ExcInputError() << EI_Specification(
"Automatic conversion to array not allowed. The value should be 'JSON array', but we found: ")
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()) );
547 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON string', but we found: ")
560 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON bool', but we found: ")
573 if ( value >= std::numeric_limits<int>::min() &&
574 value <= std::numeric_limits<int>::max() &&
575 int_type->
match(value) )
579 THROW( ExcInputError() << EI_Specification(
"Value out of bounds.") << EI_ErrorAddress(p) << EI_InputType(int_type->
desc()) );
583 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON int', but we found: ")
601 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON real', but we found: ")
605 if (double_type->
match(value)) {
608 THROW( ExcInputError() << EI_Specification(
"Value out of bounds.") << EI_ErrorAddress(p) << EI_InputType(double_type->
desc()) );
620 if (string_type->
match(value))
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()) );
626 THROW( ExcInputError() << EI_Specification(
"The value should be 'JSON string', but we found: ")
645 if (a_record != NULL ) {
646 if (a_record->
begin()->default_.has_value_at_declaration() )
649 xprintf(
PrgErr,
"Can not initialize (non-auto-convertible) AbstractRecord '%s' by default value\n", type->
type_name().c_str());
655 if ( auto_key_it != record->
end() ) {
658 if ( it == auto_key_it ) {
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());
666 if (it->default_.has_value_at_declaration() ) {
667 storage_array->
new_item(it->key_index,
676 return storage_array;
678 xprintf(
PrgErr,
"Can not initialize (non-auto-convertible) Record '%s' by default value\n", type->
type_name().c_str());
688 return storage_array;
690 xprintf(
PrgErr,
"Can not initialize Array '%s' by default value, size 1 not allowed.\n", type->
type_name().c_str());
695 return new StorageInt( static_cast<const Type::Integer *>(type) ->from_default(dflt_str) );
698 return new StorageDouble( static_cast<const Type::Double *>(type) ->from_default(dflt_str) );
701 return new StorageBool( static_cast<const Type::Bool *>(type) ->from_default(dflt_str) );
704 return new StorageInt( static_cast<const Type::Selection *>(type) ->from_default(dflt_str) );
710 xprintf(
PrgErr,
"Can not store default value for type: %s\n",
typeid(type).name());
714 }
catch (Input::Type::ExcWrongDefault & e) {
716 xprintf(
Msg,
"Wrong default value while reading an input stream:\n");
717 e << EI_KeyName(
"UNKNOWN KEY");
boost::int64_t get_int64() const
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.