| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | /**\file | ||
| 4 | * \brief HDQL-related assets for events structures */ | ||
| 5 | |||
| 6 | #include "na64sw-config.h" | ||
| 7 | #include <hdql/context.h> | ||
| 8 | |||
| 9 | #if defined(hdql_FOUND) && hdql_FOUND | ||
| 10 | |||
| 11 | #include "na64event/data/event.hh" | ||
| 12 | |||
| 13 | #include "na64detID/TBName.hh" | ||
| 14 | #include "na64calib/dispatcher.hh" // todo: violates lib.dependency? | ||
| 15 | #include "na64util/na64/event-id.hh" | ||
| 16 | #include "na64detID/detectorID.hh" | ||
| 17 | #include "na64detID/trackID.hh" | ||
| 18 | #include "na64detID/wireID.hh" | ||
| 19 | |||
| 20 | #include <hdql/helpers/compounds.hh> | ||
| 21 | |||
| 22 | #include <stdexcept> | ||
| 23 | |||
| 24 | namespace na64dp { | ||
| 25 | /**\brief Detector selector implementation for collections | ||
| 26 | * | ||
| 27 | * ... todo: doc | ||
| 28 | * */ | ||
| 29 | struct DetIDSelection | ||
| 30 | : protected calib::Handle<nameutils::DetectorNaming> { | ||
| 31 | private: | ||
| 32 | /// DSuL expression in a string form | ||
| 33 | std::string _expression; | ||
| 34 | /// Compiled DSuL selector | ||
| 35 | DetSelect * _detSelect; | ||
| 36 | protected: | ||
| 37 | /// Implements `calib::Handle` iface | ||
| 38 | void handle_update(const nameutils::DetectorNaming & nm) override; | ||
| 39 | public: | ||
| 40 | ///\brief Main ctr for selection object | ||
| 41 | /// | ||
| 42 | /// Must be used with DSuL string expression optionally prepended with | ||
| 43 | /// naming suffix, calibration dispatcher instance to handle detector | ||
| 44 | /// naming updates and detector naming class. | ||
| 45 | DetIDSelection( const char * expression | ||
| 46 | , calib::Dispatcher & cdsp | ||
| 47 | , const std::string & detNameClass="default" | ||
| 48 | ); | ||
| 49 | |||
| 50 | ///\brief Returns true if detector ID matches selector | ||
| 51 | bool matches(DetID did) const; | ||
| 52 | |||
| 53 | ///\brief Returns true if selection is "compiled" | ||
| 54 | /// | ||
| 55 | /// Returns true when string expression was used used to produce DSuL | ||
| 56 | /// selector taking into account detectors naming object -- i.e. | ||
| 57 | /// `handle_update()` was called. | ||
| 58 | bool is_compiled() const { return _detSelect; } | ||
| 59 | }; // struct DetIDSelection | ||
| 60 | |||
| 61 | namespace util { | ||
| 62 | const nameutils::DetectorNaming & get_naming_handle(hdql_Context_t context); | ||
| 63 | } // namespace ::na64dp::util | ||
| 64 | } // namespace na64dp | ||
| 65 | |||
| 66 | |||
| 67 | // Override HDQL helper traits for EventID type to consider it as a compound | ||
| 68 | // type | ||
| 69 | |||
| 70 | namespace hdql { | ||
| 71 | namespace helpers { | ||
| 72 | |||
| 73 | namespace detail { | ||
| 74 | template<> struct ArithTypeNames<::na64dp::DetID> { static constexpr const char * name = "DetID"; }; | ||
| 75 | template<> struct ArithTypeNames<::na64dp::PlaneKey> { static constexpr const char * name = "PlaneKey"; }; | ||
| 76 | template<> struct ArithTypeNames<::na64dp::TrackID> { static constexpr const char * name = "TrackID"; }; | ||
| 77 | }; | ||
| 78 | |||
| 79 | // ____________________________________________________________ | ||
| 80 | // _____________/ Helpers specialization for EventID type as a scalar compound | ||
| 81 | |||
| 82 | // Should be called before auto-generate compound creation routines to provide | ||
| 83 | // helpers with existing definition for event ID | ||
| 84 | void create_event_id_compound(hdql::helpers::CompoundTypes &, hdql_Context * context); | ||
| 85 | |||
| 86 | template<> | ||
| 87 | struct TypeInfoMixin<::na64dp::EventID> { | ||
| 88 | static constexpr bool isCompound = true; | ||
| 89 | static hdql_Compound * | ||
| 90 | 9 | type_info(const hdql_ValueTypes * valTypes, Compounds & compounds) { | |
| 91 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | assert(valTypes); |
| 92 |
1/1✓ Branch 2 taken 9 times.
|
9 | auto it = compounds.find(typeid(::na64dp::EventID)); |
| 93 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
9 | assert(compounds.end() != it); |
| 94 | 18 | return it->second; | |
| 95 | } | ||
| 96 | }; // TypeInfoMixin<EventID> | ||
| 97 | |||
| 98 | ///\brief DetID scalar attribute traits | ||
| 99 | template<typename OwnerT, ::na64dp::EventID OwnerT::*ptr> | ||
| 100 | struct IFace<ptr> | ||
| 101 | : public TypeInfoMixin<::na64dp::EventID> { | ||
| 102 | static constexpr bool isCollection = false; | ||
| 103 | |||
| 104 | static hdql_Datum_t | ||
| 105 | ✗ | dereference( hdql_Datum_t root // owning object | |
| 106 | , hdql_Datum_t dynData // allocated with `instantiate()` | ||
| 107 | , struct hdql_CollectionKey * // may be NULL | ||
| 108 | , const hdql_Datum_t // may be NULL | ||
| 109 | , hdql_Context_t | ||
| 110 | ) { | ||
| 111 | ✗ | auto p = &(reinterpret_cast<OwnerT *>(root)->*ptr); | |
| 112 | ✗ | return reinterpret_cast<hdql_Datum_t>(p); | |
| 113 | } | ||
| 114 | |||
| 115 | 9 | static hdql_ScalarAttrInterface iface() { | |
| 116 | return hdql_ScalarAttrInterface{ | ||
| 117 | // NOTE: definition data here can be used to forward some | ||
| 118 | // global auxiliary assets and in principle we can use it | ||
| 119 | // to forward calibration manager instance or | ||
| 120 | // `util::gDetIDGetters` to `compile()`, but since we sould | ||
| 121 | // like to have rather thread-local subscriptions, this | ||
| 122 | // mechanism is not used (hdql_context_custom_data_get()`) | ||
| 123 | .definitionData = NULL | ||
| 124 | , .instantiate = NULL | ||
| 125 | , .dereference = dereference | ||
| 126 | , .reset = NULL | ||
| 127 | , .destroy = NULL | ||
| 128 | 9 | }; | |
| 129 | } | ||
| 130 | |||
| 131 | static constexpr auto create_attr_def = detail::AttrDefCallback<true, false>::create_attr_def; | ||
| 132 | }; // scalar compound attribute | ||
| 133 | |||
| 134 | |||
| 135 | // ____________________________________________________________________ | ||
| 136 | // _____/ Helpers specialization for event time type as a scalar compound type | ||
| 137 | |||
| 138 | // Caveat: pair of integers of the same type can, in principle, appear in the | ||
| 139 | // event structures. In that case an automated interface instantiation will | ||
| 140 | // follow this specialization as well. | ||
| 141 | template<> | ||
| 142 | struct TypeInfoMixin<std::pair<time_t, uint32_t>> { | ||
| 143 | static constexpr bool isCompound = true; | ||
| 144 | static hdql_Compound * | ||
| 145 | 9 | type_info(const hdql_ValueTypes * valTypes, Compounds & compounds) { | |
| 146 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | assert(valTypes); |
| 147 |
1/1✓ Branch 2 taken 9 times.
|
9 | auto it = compounds.find(typeid(std::pair<time_t, uint32_t>)); |
| 148 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
9 | assert(compounds.end() != it); |
| 149 | 18 | return it->second; | |
| 150 | } | ||
| 151 | }; // TypeInfoMixin<std::pair<time_t, uint32_t>> | ||
| 152 | |||
| 153 | // contrary to `TypeInfoMixin<pair<...>>` above this specialization is | ||
| 154 | // parameterized with pointer-to member explicitly and won't appear in other | ||
| 155 | // structs | ||
| 156 | template<> | ||
| 157 | struct IFace<&::na64dp::event::Event::time > | ||
| 158 | : public TypeInfoMixin< std::pair<time_t, uint32_t> > { | ||
| 159 | static constexpr bool isCollection = false; | ||
| 160 | |||
| 161 | static hdql_Datum_t | ||
| 162 | ✗ | dereference( hdql_Datum_t root // owning object | |
| 163 | , hdql_Datum_t dynData // allocated with `instantiate()` | ||
| 164 | , struct hdql_CollectionKey * // may be NULL | ||
| 165 | , const hdql_Datum_t // may be NULL | ||
| 166 | , hdql_Context_t | ||
| 167 | ) { | ||
| 168 | ✗ | auto p = &(reinterpret_cast<::na64dp::event::Event *>(root)->time); | |
| 169 | ✗ | return reinterpret_cast<hdql_Datum_t>(p); | |
| 170 | } | ||
| 171 | |||
| 172 | 9 | static hdql_ScalarAttrInterface iface() { | |
| 173 | return hdql_ScalarAttrInterface{ | ||
| 174 | .definitionData = NULL | ||
| 175 | , .instantiate = NULL | ||
| 176 | , .dereference = dereference | ||
| 177 | , .reset = NULL | ||
| 178 | , .destroy = NULL | ||
| 179 | 9 | }; | |
| 180 | } | ||
| 181 | |||
| 182 | static constexpr auto create_attr_def = detail::AttrDefCallback<true, false>::create_attr_def; | ||
| 183 | }; // scalar compound attribute | ||
| 184 | |||
| 185 | |||
| 186 | ///\brief Collection indexed by DetID helper traits for HDQL C++ API | ||
| 187 | template<typename T> | ||
| 188 | struct SelectionTraits< na64dp::DetIDSelection | ||
| 189 | , T | ||
| 190 | , typename std::enable_if<std::is_convertible<typename T::key_type, na64dp::DetID>::value>::type | ||
| 191 | > { | ||
| 192 | typedef typename T::iterator Iterator; | ||
| 193 | //static_assert(std::is_same<na64dp::DetID, typename T::key_type>::value, ""); | ||
| 194 | 22 | static Iterator advance( T & owner | |
| 195 | , const na64dp::DetIDSelection * sel | ||
| 196 | , Iterator current | ||
| 197 | ) { | ||
| 198 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
|
22 | if(!sel) return ++current; |
| 199 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
4 | assert(owner.end() != current); |
| 200 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
4 | assert(sel->matches(current->first)); |
| 201 | 4 | for( ++current | |
| 202 |
7/7✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 2 times.
|
6 | ; current != owner.end() && !sel->matches(current->first) |
| 203 | 2 | ; ++current ) {} | |
| 204 | //assert(owner.end() == current); | ||
| 205 |
4/5✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
|
4 | assert(current == owner.end() || sel->matches(current->first)); |
| 206 | 4 | return current; | |
| 207 | } | ||
| 208 | |||
| 209 | 12 | static Iterator reset( T & owner | |
| 210 | , const na64dp::DetIDSelection * sel | ||
| 211 | , Iterator current | ||
| 212 | ) { | ||
| 213 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
|
12 | if(!sel) return owner.begin(); |
| 214 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
4 | if(owner.empty()) return owner.end(); |
| 215 | 4 | for( current = owner.begin() | |
| 216 |
4/7✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
|
4 | ; current != owner.end() && !sel->matches(current->first) |
| 217 | ✗ | ; ++current ) { | |
| 218 | } | ||
| 219 |
3/5✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
|
2 | assert(current == owner.end() || sel->matches(current->first)); |
| 220 | 2 | return current; | |
| 221 | } | ||
| 222 | |||
| 223 | 4 | static na64dp::DetIDSelection * compile( const char * expression | |
| 224 | , const hdql_Datum_t defData // userdata | ||
| 225 | , hdql_Context & ctx | ||
| 226 | ) { | ||
| 227 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
4 | assert(expression); |
| 228 | 4 | auto cdsp_ = hdql_context_custom_data_get(&ctx, "na64sw/calib-dispatcher-ptr"); | |
| 229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
4 | if(!cdsp_) { |
| 230 | char errBuf[256]; | ||
| 231 | ✗ | snprintf( errBuf, sizeof(errBuf) | |
| 232 | , "Cannot compile DSuL expression \"%s\" as current HDQLang" | ||
| 233 | " context %p does not provide custom data item" | ||
| 234 | " \"na64sw/calib-dispatcher-ptr\"." | ||
| 235 | , expression, &ctx ); | ||
| 236 | ✗ | throw std::runtime_error(errBuf); | |
| 237 | } | ||
| 238 | const char * detIDClassName; | ||
| 239 | 4 | auto detIDClassName_ = hdql_context_custom_data_get(&ctx, "na64sw/det-ID-class-name"); | |
| 240 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
4 | if(!detIDClassName_) detIDClassName = "default"; |
| 241 | 4 | else detIDClassName = reinterpret_cast<const char *>(detIDClassName_); | |
| 242 |
2/2✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
|
12 | return new na64dp::DetIDSelection(expression |
| 243 | , *reinterpret_cast<na64dp::calib::Dispatcher *>(cdsp_) | ||
| 244 | , detIDClassName | ||
| 245 |
0/1✗ Branch 2 not taken.
|
12 | ); // TODO: use hdql context for allocation? |
| 246 | } | ||
| 247 | |||
| 248 | 4 | static void destroy( na64dp::DetIDSelection * sel | |
| 249 | , const hdql_Datum_t | ||
| 250 | , hdql_Context & | ||
| 251 | ) { | ||
| 252 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
4 | assert(sel); |
| 253 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | delete sel; // TODO: use hdql context for deletio? |
| 254 | } | ||
| 255 | }; | ||
| 256 | |||
| 257 | } // namespace ::hdql::helpers | ||
| 258 | } // namespace hdql | ||
| 259 | |||
| 260 | #endif // defined(hdql_FOUND) && hdql_FOUND | ||
| 261 | |||
| 262 |