GCC Code Coverage Report


Directory: ./
File: src/calib/loaders/yaml-document.cc
Date: 2025-09-01 06:19:01
Exec Total Coverage
Lines: 0 76 0.0%
Functions: 0 4 0.0%
Branches: 0 20 0.0%

Line Branch Exec Source
1 #include "na64calib/loaders/yaml-document.hh"
2 #include "na64util/uri.hh"
3 #include "na64calib/manager.hh"
4
5 namespace na64dp {
6 namespace calib {
7
8 void
9 YAMLDocumentLoader::load( const iUpdate & recipe
10 , Dispatcher & dsp
11 ) {
12 auto rttiIt = CIDataAliases::self()
13 .name_by_type_id()
14 .find(recipe.subject_data_type());
15 if( CIDataAliases::self().name_by_type_id().end() == rttiIt ) {
16 NA64DP_RUNTIME_ERROR( "Can't lookup for conversion of unaliased type"
17 " %s."
18 , util::calib_id_to_str(recipe.subject_data_type()).c_str() );
19 }
20 const std::string & typeAlias = rttiIt->second;
21 // Find the conversion callback
22 auto it = _conversions.find(typeAlias);
23 if( _conversions.end() == it ) {
24 NA64DP_RUNTIME_ERROR( "No data conversion from YAML node to type \"%s\""
25 " (alias to %s) defined for generic YAML document loader."
26 , typeAlias.c_str()
27 , util::calib_id_to_str(recipe.subject_data_type()).c_str() );
28 }
29
30 // Reach the file and parse it to the YAML node
31 YAML::Node n;
32 // Downcast to yaml update
33 const iSpecificUpdate<YAML::Node> & upd
34 = static_cast<const iSpecificUpdate<YAML::Node>&>(recipe);
35 if( upd.payload["source"] ) {
36 // load source
37 std::string path = upd.payload["source"].as<std::string>();
38 auto names = util::expand_names( path );
39 if( 1 != names.size() ) {
40 NA64DP_RUNTIME_ERROR( "Failed to expand string expression to the"
41 " file name: \"%s\".", path.c_str() );
42 }
43 _log << log4cpp::Priority::DEBUG
44 << "\"source\" field provided for update -- reading file \""
45 << path << "\" expanded as \"" << names[0].c_str() << "\"..."
46 ;
47 try {
48 n = YAML::LoadFile( names[0] );
49 } catch( std::exception & e ) {
50 _log.error( "Error occured while accessing, reading or parsing"
51 " YAML calibration data \"%s\": %s"
52 , names[0].c_str()
53 , e.what()
54 );
55 throw;
56 }
57 _log.debug( "Converting data of YAML document \"%s\" into %s..."
58 , names[0].c_str()
59 , util::calib_id_to_str(recipe.subject_data_type()).c_str() );
60 // Perform the conversion and dispatch the data
61 try {
62 it->second(n, dsp);
63 } catch( std::exception & e ) {
64 _log.error( "During conversion of YAML document data \"%s\" into"
65 " %s occured an error: %s."
66 , names[0].c_str()
67 , util::calib_id_to_str(recipe.subject_data_type()).c_str()
68 , e.what()
69 );
70 throw;
71 }
72 _log.debug( "Calibration info from YAML document \"%s\" has been loaded into %s."
73 , names[0].c_str()
74 , util::calib_id_to_str(recipe.subject_data_type()).c_str() );
75 } else if( upd.payload["payload"] ) {
76 // directly use information from payload
77 _log << log4cpp::Priority::DEBUG
78 << "\"payload\" field provided for update -- converting it to "
79 << util::calib_id_to_str(recipe.subject_data_type()) << "..."
80 ;
81 // Perform the conversion and dispatch the data
82 it->second(upd.payload["payload"], dsp);
83 _log.debug( "Calibration data from YAML node has been loaded into %s."
84 , util::calib_id_to_str(recipe.subject_data_type()).c_str() );
85 } else {
86 // This must be a result of a wrong specification
87 NA64DP_RUNTIME_ERROR( "Update did not bring payload info meaningful"
88 " for this loader (perhaps, wrong specification of"
89 " recommended loader in the update)." );
90 }
91 }
92
93 bool
94 YAMLDocumentLoader::can_handle( const iUpdate & recipe ) {
95 // This handler is capable to handle update if:
96 // - type is aliased
97 // - the subject type conversion is defined
98 // - update type can be downcasted to the iSpecificUpdate<YAML::Node>
99 // - YAML node has "payload" or "source" fields
100 auto rttiIt = CIDataAliases::self()
101 .name_by_type_id()
102 .find(recipe.subject_data_type());
103 if( CIDataAliases::self().name_by_type_id().end() == rttiIt ) {
104 return false; // unaliased type
105 }
106 const std::string & typeAlias = rttiIt->second;
107
108 auto it = _conversions.find(typeAlias);
109 if( _conversions.end() == it ) return false; // no conversion defined
110
111 auto ptr = dynamic_cast<const iSpecificUpdate<YAML::Node>*>(&recipe);
112 if(!ptr) return false; // downcast failed
113
114 return ((bool) ptr->payload["payload"])
115 || ((bool) ptr->payload["source"]);
116 }
117
118 void
119 YAMLDocumentLoader::define_conversion(
120 const std::string & aliasName
121 , void (*callback)(const YAML::Node &, Dispatcher &)
122 ) {
123 auto ir = _conversions.emplace(aliasName, callback);
124 if( ! ir.second ) {
125 if(ir.first->second != ir.first->second)
126 NA64DP_RUNTIME_ERROR( "Ambiguious conversion for type alias"
127 " \"%s\" requested (different conversion"
128 " callback for this type is provided to YAML document"
129 " loader)."
130 , aliasName.c_str() );
131 _log.debug( "Repeated registration of the conversion callback for alias"
132 " \"%s\" is omitted.", aliasName.c_str() );
133 } else {
134 _log.debug( "Added YAML document conversion for type with alias \"%s\"."
135 , aliasName.c_str() );
136 }
137 }
138
139 void
140 YAMLDocumentLoader::to_yaml_as_loader( YAML::Node & node ) const {
141 char bf[128];
142 node["_type"] = "YAMLDocumentLoader";
143 snprintf(bf, sizeof(bf), "%p", this);
144 node["_ptr"] = bf;
145 YAML::Node conversions;
146 for( auto cnvPair : _conversions ) {
147 snprintf(bf, sizeof(bf), "%p", cnvPair.second);
148 conversions[cnvPair.first] = bf;
149 }
150 node["conversions"] = conversions;
151 }
152
153
154 #if 0
155 void
156 YAMLDocumentLoader::put_provided_types( CITypeAliases & aliases ) {
157 assert(!_aliases); // same loader instance is added to another manager?
158 _aliases = &aliases;
159 }
160
161 bool
162 YAMLDocumentLoader::can_handle( const iIndex::UpdateRecipe & updRecipe
163 , Dispatcher::CIDataID dataID ) {
164 // TODO: check if the file is reachable using updRecipe.payload["source"]
165 return _callbacks.end() != _callbacks.find(dataID);
166 }
167 #endif
168
169 }
170 }
171
172