OSVR-Core
PathParseAndRetrieve.h
Go to the documentation of this file.
1 
11 // Copyright 2014 Sensics, Inc.
12 //
13 // Licensed under the Apache License, Version 2.0 (the "License");
14 // you may not use this file except in compliance with the License.
15 // You may obtain a copy of the License at
16 //
17 // http://www.apache.org/licenses/LICENSE-2.0
18 //
19 // Unless required by applicable law or agreed to in writing, software
20 // distributed under the License is distributed on an "AS IS" BASIS,
21 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 // See the License for the specific language governing permissions and
23 // limitations under the License.
24 
25 #ifndef INCLUDED_PathParseAndRetrieve_h_GUID_C451663C_0711_4B85_2011_61D26E5C237C
26 #define INCLUDED_PathParseAndRetrieve_h_GUID_C451663C_0711_4B85_2011_61D26E5C237C
27 
28 // Internal Includes
31 #include <osvr/Util/TreeNode.h>
32 
33 // Library/third-party includes
34 #include <boost/assert.hpp>
35 #include <boost/algorithm/string/find_iterator.hpp>
36 #include <boost/algorithm/string/finder.hpp>
37 #include <boost/range/adaptor/sliced.hpp>
38 
39 // Standard includes
40 #include <string>
41 
42 namespace osvr {
43 namespace common {
44  namespace detail {
46  template <typename Node>
47  Node *operator()(Node *node, std::string const &component) const {
48  return &(node->getOrCreateChildByName(component));
49  }
50  };
51 
52  struct GetChildFunctor {
53  template <typename Node>
54  Node const *operator()(Node const *node,
55  std::string const &component) const {
56  return &(node->getChildByName(component));
57  }
58  };
59  enum ParentPolicy { GETPARENT_PERMIT, GETPARENT_DENY };
60  enum AbsolutePolicy { ABSOLUTEPATH_PERMIT, ABSOLUTEPATH_DENY };
61 
62  template <typename GetChildFunctor, typename Node>
63  inline Node &treePathRetrieveImplementation(
64  GetChildFunctor f, Node &node, std::string path,
65  ParentPolicy permitParent = GETPARENT_DENY,
66  AbsolutePolicy permitAbsolute = ABSOLUTEPATH_PERMIT) {
67 
68  if (path.empty()) {
69  return node;
70  }
71  Node *ret = &node;
72 
73  // Check for leading slash, indicating absolute path
74  if (path.at(0) == getPathSeparatorCharacter()) {
75  if (ABSOLUTEPATH_PERMIT != permitAbsolute) {
77  }
78  // Got it, so move to the root of the tree.
79  while (!ret->isRoot()) {
80  ret = ret->getParent();
81  }
82  if (path == getPathSeparator()) {
83  // Literally just asking for the root.
84  return *ret;
85  }
86  // Remove the leading slash for the iterator's benefit.
87  path.erase(begin(path));
88  }
89 
90  // Remove any trailing slash
91  if (path.back() == getPathSeparatorCharacter()) {
92  path.pop_back();
93  }
94 
95  // new scope for the iterators and loop:
96  {
97  // Create a boost string algorithm "split iterator" to iterate
98  // through components of the path.
99  auto begin = boost::algorithm::make_split_iterator(
100  path,
101  boost::first_finder(getPathSeparator(), boost::is_equal()));
102  // Create the corresponding end iterator: same type as begin,
103  // but default constructed.
104  auto end = decltype(begin)();
105 
106  // Temporary string that will be re-used each pass through the
107  // loop
108  std::string component;
109 
110  // Use the iterators as a range in a loop, to process each
111  // component of the path
112  for (auto rangeIt : boost::make_iterator_range(begin, end)) {
113  // Extract the component to a string for interpretation.
114  component = boost::copy_range<std::string>(rangeIt);
115 
116  // Interpret the component: four cases
117  if (component.empty()) {
118  // Empty components are forbidden
119  throw exceptions::EmptyPathComponent(path);
120  } else if (component == ".") {
121  // current location - go to the next component without
122  // changing location
123  continue;
124  } else if (component == "..") {
125  // parent path - must check for permission first, then
126  // possibility (root has no parent)
127  if (GETPARENT_PERMIT != permitParent) {
129  }
130  if (ret->isRoot()) {
132  }
133  ret = ret->getParent();
134  } else {
135  // A non-special string: just get the child
136  ret = f(ret, component);
137  }
138  // if we make it to here we've updated ret.
139  }
140  }
141 
142  return *ret;
143  }
144 
145  } // namespace detail
164  template <typename ValueType>
167  bool permitParent = false) {
168  return detail::treePathRetrieveImplementation(
169  detail::GetOrCreateFunctor(), node, path,
170  permitParent ? detail::GETPARENT_PERMIT : detail::GETPARENT_DENY);
171  }
172 
177  template <typename ValueType>
178  inline util::TreeNode<ValueType> const &
179  treePathRetrieve(util::TreeNode<ValueType> const &node, std::string path,
180  bool permitParent = false) {
181  return detail::treePathRetrieveImplementation(
182  detail::GetChildFunctor(), node, path,
183  permitParent ? detail::GETPARENT_PERMIT : detail::GETPARENT_DENY);
184  }
185 
199  template <typename ValueType>
202  std::string const &path) {
203  BOOST_ASSERT_MSG(root.isRoot(), "Must pass the root node!");
204  if (path.empty()) {
205  throw exceptions::EmptyPath();
206  }
207  if (path == getPathSeparator()) {
208  return root;
209  }
210  if (path.at(0) != getPathSeparatorCharacter()) {
211  throw exceptions::PathNotAbsolute(path);
212  }
213 
214  return treePathRetrieve(root, path);
215  }
216 
218  template <typename ValueType>
219  inline util::TreeNode<ValueType> const &
221  std::string const &path) {
222  BOOST_ASSERT_MSG(root.isRoot(), "Must pass the root node!");
223  if (path.empty()) {
224  throw exceptions::EmptyPath();
225  }
226  if (path == getPathSeparator()) {
227  return root;
228  }
229  if (path.at(0) != getPathSeparatorCharacter()) {
230  throw exceptions::PathNotAbsolute(path);
231  }
232 
233  return treePathRetrieve(root, path);
234  }
235 } // namespace common
236 } // namespace osvr
237 
238 #endif // INCLUDED_PathParseAndRetrieve_h_GUID_C451663C_0711_4B85_2011_61D26E5C237C
Thrown when attempting to use a path with an empty component.
Definition: RoutingExceptions.h:54
Handles spatial transformations.
Definition: SerializationTraitExample_Complicated.h:40
A node in a generic tree, which can contain an object by value.
Definition: TreeNode.h:72
The main namespace for all C++ elements of the framework, internal and external.
Definition: namespace_osvr.dox:3
Definition: PathParseAndRetrieve.h:45
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.
Definition: PathParseAndRetrieve.h:166
Thrown when attempting to go to the parent path when forbidden.
Definition: RoutingExceptions.h:77
Definition: PathParseAndRetrieve.h:52
Definition: newuoa.h:1888
Thrown when attempting to go use an absolute path when forbidden.
Definition: RoutingExceptions.h:69
Thrown when attempting to use a path with no leading slash where an absolute path is required...
Definition: RoutingExceptions.h:91
Thrown when attempting to go to the parent path from the root.
Definition: RoutingExceptions.h:61
Thrown when attempting to use an empty path.
Definition: RoutingExceptions.h:84
util::TreeNode< ValueType > & pathParseAndRetrieve(util::TreeNode< ValueType > &root, std::string const &path)
Internal method for parsing a path and getting or creating the nodes along it.
Definition: PathParseAndRetrieve.h:201
bool isRoot() const
Is the current node a root node?
Definition: TreeNode.h:276
OSVR_COMMON_EXPORT const char * getPathSeparator()
Gets the path separator - a slash - as a null-terminated string.
Definition: RoutingConstants.cpp:38
Header.