msl 1.1.0
 
Loading...
Searching...
No Matches
Case.h
Go to the documentation of this file.
1// Copyright 2024-2025 Julien Lamy, ICube, Université de Strasbourg-CNRS.
2// Part of msl, distributed under the terms of the MIT license.
3
4#ifndef _c1c4f441_160f_46bf_869e_1bf9c199aa91
5#define _c1c4f441_160f_46bf_869e_1bf9c199aa91
6
7#include <unordered_map>
8
9#include <boost/variant/variant.hpp>
10
11#include <MrMeasSrv/MeasUtils/NLSStatus.h>
12
13#include <MrProtSrv/Domain/CoreNative/SeqLim.h>
14#include <MrProtSrv/Domain/MrProtData/MrProt/MrProt.h>
15#include <MrProtSrv/Domain/MrProtData/MrProt/SeqIF/SeqExpo.h>
16#include <MrProtSrv/Domain/MrProtData/MrProt/SeqIF/SeqExpoRFBlockInfo.h>
17
18#include "msl/Dictionary.h"
20#include "msl/graph/Node.h"
21
22namespace msl
23{
24namespace graph
25{
26
31template<typename T>
32class Case: public AbstractNode
33{
34public:
35 using Map = std::unordered_map<T, AbstractNode::Pointer>;
36
37 // NOTE: most of the Siemens API is not const-correct
38 using Function = boost::variant<
39 std::function<T()>,
40 std::function<T(MrProt &)>,
41 std::function<T(MrProt &, SeqLim &, SeqExpo &)>>;
42
44
45 static Pointer New(
46 std::string const & key, Map const & cases,
47 Dictionary::Pointer registry={})
48 {
49 return Pointer(new Case(key, cases, registry));
50 }
51
58 NLSStatus prepare(
59 MrProt & protocol, SeqLim & limits, SeqExpo & exports) override
60 {
61 auto child = this->_child(protocol, limits, exports);
62 return child->prepare(protocol, limits, exports);
63 }
64
71 NLSStatus run(
72 MrProt & protocol, SeqLim & limits, SeqExpo & exports) override
73 {
74 auto child = this->_child(protocol, limits, exports);
75 return child->run(protocol, limits, exports);
76 }
77
79 Case & setRegistry(Dictionary::Pointer registry) override
80 {
81 this->AbstractNode::setRegistry(registry);
82 for(auto && item: this->_cases)
83 {
84 auto & child = item.second;
85 child->setRegistry(this->_registry);
86 }
87 return *this;
88 }
89
94 uint64_t duration() const override
95 {
96 return this->_child()->duration();
97 }
98
103 MrProtocolData::SeqExpoRFInfo rfInfo() const override
104 {
105 return this->_child()->rfInfo();
106 }
107
108private:
109 // template<typename T>
110 class Visitor: public boost::static_visitor<
111 std::function<T(MrProt &, SeqLim &, SeqExpo &)>>
112 {
113 public:
114 std::function<T(MrProt &, SeqLim &, SeqExpo &)> operator()(std::function<T()> const & f) const
115 {
116 return [&](MrProt &, SeqLim &, SeqExpo &){ return f(); };
117 }
118
119 std::function<T(MrProt &, SeqLim &, SeqExpo &)> operator()(std::function<T(MrProt &)> const & f) const
120 {
121 return [&](MrProt & p, SeqLim &, SeqExpo &){ return f(p); };
122 }
123
124 std::function<T(MrProt &, SeqLim &, SeqExpo &)> operator()(
125 std::function<T(MrProt &, SeqLim &, SeqExpo &)> const & f) const
126 {
127 return f;
128 }
129 };
130
131 std::string _key;
132 Map _cases;
133
134 // NOTE: SeqLim is an abstract class. Since the concrete object may change
135 // between calls to ::prepare or ::run, it can only be stored in a pointer.
136 mutable bool _hasCache;
137 mutable MrProt * _protocol;
138 mutable SeqLim * _limits;
139 mutable SeqExpo * _exports;
140
141 Case(
142 std::string const & key, Map const & cases,
143 Dictionary::Pointer registry={})
144 : AbstractNode(registry), _key(key), _cases(cases), _hasCache(false)
145 {
146 this->setRegistry(registry);
147 }
148
149 AbstractNode::ConstPointer _child() const
150 {
151 if(!this->_hasCache)
152 {
153 throw std::runtime_error("No cached data");
154 }
155 else
156 {
157 return this->_child(
158 *this->_protocol, *this->_limits, *this->_exports);
159 }
160 }
161
162 AbstractNode::ConstPointer _child(
163 MrProt & protocol, SeqLim & limits, SeqExpo & exports) const
164 {
165 this->_protocol = &protocol;
166 this->_limits = &limits;
167 this->_exports = &exports;
168 this->_hasCache = true;
169
170 return this->_cases.at(
171 this->type(this->_key) == typeid(T)
172 ? this->get<T>(this->_key)
173 : boost::apply_visitor(Visitor(), this->get<Function>(this->_key))(
174 protocol, limits, exports)
175 );
176 }
177
178 AbstractNode::Pointer _child()
179 {
180 if(!this->_hasCache)
181 {
182 throw std::runtime_error("No cached data");
183 }
184 else
185 {
186 return this->_child(
187 *this->_protocol, *this->_limits, *this->_exports);
188 }
189 }
190
191 AbstractNode::Pointer _child(
192 MrProt & protocol, SeqLim & limits, SeqExpo & exports)
193 {
194 this->_protocol = &protocol;
195 this->_limits = &limits;
196 this->_exports = &exports;
197 this->_hasCache = true;
198
199 return this->_cases.at(
200 this->type(this->_key) == typeid(T)
201 ? this->get<T>(this->_key)
202 : boost::apply_visitor(Visitor(), this->get<Function>(this->_key))(
203 protocol, limits, exports)
204 );
205 }
206};
207
208}
209}
210
211#endif // _c1c4f441_160f_46bf_869e_1bf9c199aa91
boost::typeindex::type_info const & type(std::string const &key) const
Return the type of an object in the dictionary.
Dictionary::ConstPointer registry() const
Return the registry.
Dictionary::Pointer _registry
Definition AbstractNode.h:80
T const & get(std::string const &key) const
Return an object from the dictionary.
Definition AbstractNode.h:64
virtual AbstractNode & setRegistry(Dictionary::Pointer registry)
Set the registry.
AbstractNode(Dictionary::Pointer registry={})
Node encapsulating a switch/case structure based on a boolean key or a function key.
Definition Case.h:33
static Pointer New(std::string const &key, Map const &cases, Dictionary::Pointer registry={})
Definition Case.h:45
NLSStatus prepare(MrProt &protocol, SeqLim &limits, SeqExpo &exports) override
Prepare the selected child, throw an exception if unknown value.
Definition Case.h:58
NLSStatus run(MrProt &protocol, SeqLim &limits, SeqExpo &exports) override
Run the selected child, throw an exception if unknown value.
Definition Case.h:71
DECLARE_POINTERS(Case< T >)
Case & setRegistry(Dictionary::Pointer registry) override
Set the registry to this node and its children.
Definition Case.h:79
boost::variant< std::function< T()>, std::function< T(MrProt &)>, std::function< T(MrProt &, SeqLim &, SeqExpo &)> > Function
Definition Case.h:38
std::unordered_map< T, AbstractNode::Pointer > Map
Definition Case.h:35
MrProtocolData::SeqExpoRFInfo rfInfo() const override
Return the RF information of the selected child, throw an exception if unknown value.
Definition Case.h:103
uint64_t duration() const override
Return the duration of the selected child, throw an exception if unknown value.
Definition Case.h:94
Definition AbstractNode.h:23
Definition acceleration.h:17