25 #undef OSVR_DEV_VERBOSE_DISABLE
42 #include <json/value.h>
43 #include <json/reader.h>
44 #include <boost/noncopyable.hpp>
45 #include <boost/variant/get.hpp>
46 #include <boost/algorithm/string/predicate.hpp>
47 #include <boost/algorithm/string/erase.hpp>
55 static const char INTERFACES_KEY[] =
"interfaces";
57 static inline util::Flag
58 processInterfacesFromDescriptor(
PathNode &devNode,
59 Json::Value
const &desc) {
61 if (!desc.isMember(INTERFACES_KEY)) {
66 Json::Value
const &ifaces = desc[INTERFACES_KEY];
67 if (!ifaces.isObject()) {
71 for (
auto const &iface : ifaces.getMemberNames()) {
82 static const char TARGET_KEY[] =
"$target";
83 static const char SEMANTIC_KEY[] =
"semantic";
84 static const char AUTOMATIC_KEY[] =
"automaticAliases";
86 class SemanticRecursion : boost::noncopyable {
88 SemanticRecursion(
PathNode &devNode) : m_devNode(devNode) {}
90 util::Flag operator()(Json::Value
const &semanticObject) {
91 m_recurse(semanticObject, SEMANTIC_KEY);
96 bool m_add(Json::Value
const ¤tLevel,
97 std::string
const &relativeSemanticPath) {
99 m_devNode, currentLevel.toStyledString(),
100 relativeSemanticPath, ALIASPRIORITY_SEMANTICROUTE);
102 void m_recurse(Json::Value
const ¤tLevel,
103 std::string
const &relativeSemanticPath) {
104 if (currentLevel.isString()) {
105 m_flag += m_add(currentLevel, relativeSemanticPath);
108 if (currentLevel.isObject()) {
109 Json::Value target = currentLevel[TARGET_KEY];
110 if (!target.isNull()) {
111 m_flag += m_add(target, relativeSemanticPath);
114 for (
auto const &memberName :
115 currentLevel.getMemberNames()) {
116 if (TARGET_KEY == memberName) {
119 m_recurse(currentLevel[memberName],
131 static inline util::Flag
132 processSemanticFromDescriptor(
PathNode &devNode, Json::Value
const &desc) {
134 Json::Value
const &sem = desc[SEMANTIC_KEY];
135 if (!sem.isObject()) {
139 SemanticRecursion f{devNode};
143 static inline bool processAutomaticFromDescriptor(
PathNode &devNode,
144 Json::Value
const &desc) {
145 Json::Value
const &automatic = desc[AUTOMATIC_KEY];
146 return AliasProcessor{}
147 .setDefaultPriority(ALIASPRIORITY_AUTOMATIC)
148 .enableRelativePath()
149 .enableRelativeSource()
151 .process(devNode, automatic);
156 static inline std::pair<std::string, std::string>
157 getDevHost(std::string
const &deviceName, std::string
const &host) {
159 auto atLocation = deviceName.find(
'@');
160 if (std::string::npos == atLocation) {
162 return std::make_pair(deviceName, host);
166 std::string devName(deviceName);
167 devName.resize(atLocation);
168 return std::make_pair(devName, devName.substr(atLocation + 1));
172 std::string
const &deviceName,
173 std::string
const &jsonDescriptor,
175 std::string
const &host) {
176 std::string devName{deviceName};
177 if (getPathSeparatorCharacter() == devName.at(0)) {
179 devName.erase(begin(devName));
185 auto devElt = boost::get<elements::DeviceElement>(&devNode.value());
186 if (
nullptr == devElt) {
191 std::tie(dev, devHost) = getDevHost(devName, host);
194 devElt = boost::get<elements::DeviceElement>(&devNode.value());
199 const std::string normalizedDescriptor =
203 Json::Value descriptor;
206 if (!reader.parse(normalizedDescriptor, descriptor)) {
208 return changed.
get();
211 if (descriptor == devElt->getDescriptor() && !changed) {
213 return changed.
get();
215 devElt->getDescriptor() = descriptor;
219 return changed.
get();
227 processInterfacesFromDescriptor(devNode, devElt.getDescriptor());
230 processSemanticFromDescriptor(devNode, devElt.getDescriptor());
233 processAutomaticFromDescriptor(devNode, devElt.getDescriptor());
235 return changed.get();
A tree representation, with path/url syntax, of the known OSVR system.
std::string normalizeDeviceDescriptor(std::string const &jsonDescriptor)
"Normalizes" a device descriptor by parsing it and adding implied interfaces to the existing device d...
::osvr::util::TreeNode< PathElement > PathNode
The specific tree node type that contains a path element.
util::TreeNode< ValueType > & treePathRetrieve(util::TreeNode< ValueType > &node, std::string path, bool permitParent=false)
Internal method for parsing a path and getting or creating the nodes along it.
static DeviceElement createDeviceElement(std::string const &deviceName, std::string const &server, int port=util::UseDefaultPort)
The element type corresponding to a device, which implements 0 or more interfaces.
bool get() const
Get the value of the flag as a bool.
PathNode & getNodeByPath(std::string const &path)
Returns the node indicated by the path, which must be absolute (begin with a /). Any non-existent nod...
bool isNull(PathElement const &elt)
Returns true if the path element provided is a NullElement.
bool processDeviceDescriptorForPathTree(PathTree &tree, std::string const &deviceName, std::string const &jsonDescriptor, int listenPort, std::string const &host)
Set up a path tree based on a device descriptor.
The element type corresponding to an interface, which often may have one or more sensors.
Internal, configured header file for verbosity macros.
const char * getPathSeparator()
Gets the path separator - a slash - as a null-terminated string.
bool addAliasFromSourceAndRelativeDest(PathNode &node, std::string const &source, std::string const &dest, AliasPriority priority=ALIASPRIORITY_MANUAL)
void set()
Set the flag to true.
A class that lightly wraps a bool, in order to provide easier maintenance of a "dirty" flag...
bool processDeviceDescriptorFromExistingDevice(PathNode &devNode, elements::DeviceElement const &devElt)
Set up a path tree based on a device descriptor from an existing DeviceElement node.