32 #include <boost/variant/static_visitor.hpp>
33 #include <boost/variant/apply_visitor.hpp>
34 #include <boost/variant/get.hpp>
35 #include <boost/optional.hpp>
36 #include <boost/lexical_cast.hpp>
44 OriginalSource::OriginalSource()
45 : m_device(nullptr), m_interface(nullptr), m_sensor(nullptr) {}
47 bool OriginalSource::isResolved()
const {
48 return m_device !=
nullptr && m_interface !=
nullptr;
52 BOOST_ASSERT_MSG(m_device ==
nullptr,
53 "Device should only be set once.");
58 BOOST_ASSERT_MSG(m_interface ==
nullptr,
59 "Interface should only be set once.");
64 BOOST_ASSERT_MSG(m_sensor ==
nullptr,
65 "Sensor should only be set once.");
69 void OriginalSource::nestTransform(Json::Value
const &
transform) {
70 m_transform.nest(transform);
73 std::string OriginalSource::getDevicePath()
const {
74 BOOST_ASSERT_MSG(isResolved(),
75 "Only makes sense when called on a resolved source.");
82 OriginalSource::getDeviceElement()
const {
83 BOOST_ASSERT_MSG(isResolved(),
84 "Only makes sense when called on a resolved source.");
85 return boost::get<common::elements::DeviceElement>(m_device->value());
92 std::string OriginalSource::getInterfaceName()
const {
93 BOOST_ASSERT_MSG(isResolved(),
94 "Only makes sense when called on a resolved source.");
96 if (
nullptr == m_interface) {
99 ret = m_interface->getName();
105 template <
typename T>
106 inline boost::optional<T>
107 getSensorNumberHelper(OriginalSource
const &
self) {
108 BOOST_ASSERT_MSG(
self.isResolved(),
109 "Only makes sense when called on a resolved source.");
110 boost::optional<T> ret;
111 if (
nullptr ==
self.getSensor()) {
115 ret = boost::lexical_cast<T>(
self.getSensor()->getName());
116 }
catch (boost::bad_lexical_cast &) {
123 boost::optional<int> OriginalSource::getSensorNumber()
const {
124 return getSensorNumberHelper<int>(*this);
127 boost::optional<OSVR_ChannelCount>
128 OriginalSource::getSensorNumberAsChannelCount()
const {
129 return getSensorNumberHelper<OSVR_ChannelCount>(*this);
132 Json::Value OriginalSource::getTransformJson()
const {
133 BOOST_ASSERT_MSG(isResolved(),
134 "Only makes sense when called on a resolved source.");
135 return m_transform.get(m_getPath());
138 bool OriginalSource::hasTransform()
const {
139 BOOST_ASSERT_MSG(isResolved(),
140 "Only makes sense when called on a resolved source.");
141 return !m_transform.empty();
144 std::string OriginalSource::m_getPath()
const {
145 BOOST_ASSERT_MSG(isResolved(),
146 "Only makes sense when called on a resolved source.");
149 node = getInterface();
157 return std::string{};
160 class DecomposeOriginalSource :
public boost::static_visitor<>,
163 DecomposeOriginalSource(
PathNode &node, OriginalSource &source)
164 : boost::static_visitor<>(), m_source(source) {
165 m_applyVisitor(node);
168 template <
typename T>
void operator()(
PathNode &, T &) {
169 throw std::runtime_error(
"Element type encountered that is not "
170 "recognized in decomposition!");
174 m_source.setSensor(node);
175 if (
nullptr == node.getParent()) {
176 throw exceptions::invariants::SensorMissingParent(
179 m_applyVisitor(*node.getParent());
180 if (
nullptr == m_source.getInterface()) {
183 throw exceptions::invariants::SensorMissingInterfaceParent(
189 m_source.setInterface(node);
190 if (
nullptr == node.getParent()) {
191 throw exceptions::invariants::InterfaceMissingParent(
194 m_applyVisitor(*node.getParent());
198 m_source.setDevice(node);
204 void m_applyVisitor(
PathNode &node) {
207 OriginalSource &m_source;
211 DecomposeOriginalSource decomp{node, *
this};
::osvr::util::TreeNode< PathElement > PathNode
The specific tree node type that contains a path element.
The element type corresponding to a particular sensor of an interface.
The element type corresponding to a device, which implements 0 or more interfaces.
std::string getFullPath(PathNode const &node)
Gets the absolute path for the given node.
t_< detail::transform_< List, Fun >> transform
The element type corresponding to an interface, which often may have one or more sensors.
Visitor::result_type applyPathNodeVisitor(Visitor &v, PathNode &node)
Visit a node's element's contained type, similar to boost::apply_visitor, but passing both the PathNo...