RSB  0.9.6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Scope.cpp
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is a part of the RSB project.
4  *
5  * Copyright (C) 2011 by Johannes Wienke <jwienke at techfak dot uni-bielefeld dot de>
6  *
7  * This file may be licensed under the terms of the
8  * GNU Lesser General Public License Version 3 (the ``LGPL''),
9  * or (at your option) any later version.
10  *
11  * Software distributed under the License is distributed
12  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13  * express or implied. See the LGPL for the specific language
14  * governing rights and limitations.
15  *
16  * You should have received a copy of the LGPL along with this
17  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
18  * or write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The development of this software was supported by:
22  * CoR-Lab, Research Institute for Cognition and Robotics
23  * Bielefeld University
24  *
25  * ============================================================ */
26 
27 #include "Scope.h"
28 
29 #include <sstream>
30 #include <stdexcept>
31 #include <iterator>
32 
33 #include <boost/format.hpp>
34 
35 using namespace std;
36 
37 using namespace boost;
38 
39 namespace rsb {
40 
41 const char Scope::COMPONENT_SEPARATOR = '/';
42 
53 inline void verifyAndSplit(const string& s, vector<string>& components,
54  string& normalizedString) {
55  if (s.empty()) {
56  throw invalid_argument("Empty scope string given.");
57  }
58  string::const_iterator prev = s.begin();
59  // The scope string has to start with a '/'.
60  if (*prev != Scope::COMPONENT_SEPARATOR) {
61  throw invalid_argument(
62  str(
63  format(
64  "Invalid scope syntax for '%1%': has to begin with '%2%'")
65  % s % Scope::COMPONENT_SEPARATOR));
66  }
67 
68  // Process remainder of s. If we are at the end of s already, it
69  // denotes the root scope and we do not have to create any
70  // components.
71  string::const_iterator next = prev + 1;
72  for (; next != s.end(); ++next) {
73  // If we encounter a '/', make sure that we accumulated at
74  // least one character in the current scope component.
75  if (*next == Scope::COMPONENT_SEPARATOR) {
76  if (distance(prev, next) == 1) {
77  throw invalid_argument(
78  str(
79  format(
80  "Invalid scope syntax for '%1%' at char %2%: zero-length component between two '%3%'")
81  % s % distance(s.begin(), next)
82  % Scope::COMPONENT_SEPARATOR));
83  }
84  components.push_back(string(prev + 1, next));
85  prev = next;
86  }
87  // The current character is not a '/' and we want to append it
88  // to the current scope component. Verify that it is a legal
89  // scope component character.
90  else if (!(('a' <= *next && *next <= 'z')
91  || ('A' <= *next && *next <= 'Z')
92  || ('0' <= *next && *next <= '9')
93  || (*next == '_') || (*next == '-'))) {
94  throw invalid_argument(
95  str(
96  format(
97  "Invalid scope syntax for '%1%' at char %2%: invalid character '%3%'")
98  % s % distance(s.begin(), next) % *next));
99  }
100  // The current character is a valid scope component
101  // character. Append it to the current scope component.
102  }
103  if (prev + 1 != next) {
104  components.push_back(string(prev + 1, next));
105  }
106 
107  // now build the normalized string. ATM we only need to check for the
108  // trailing slash, All other things are handled by the checks before
109  normalizedString = s;
110  if (*(--s.end()) != Scope::COMPONENT_SEPARATOR) {
111  normalizedString += Scope::COMPONENT_SEPARATOR;
112  }
113 
114 }
115 
116 Scope::Scope(const string& s) :
117  scopestring() {
118  // reserve a number of vector components that should be enough for most
119  // realistic scopes. This speeds up parsing.
120  components.reserve(10);
121  verifyAndSplit(s, this->components, this->scopestring);
122 }
123 
124 Scope::Scope(const char *scope) :
125  scopestring() {
126  // reserve a number of vector components that should be enough for most
127  // realistic scopes. This speeds up parsing.
128  components.reserve(10);
129  verifyAndSplit(string(scope), this->components, this->scopestring);
130 }
131 
133  scopestring("/") {
134 }
135 
137 }
138 
139 const vector<string>& Scope::getComponents() const {
140  return components;
141 }
142 
143 const std::string& Scope::toString() const {
144  return this->scopestring;
145 }
146 
147 Scope Scope::concat(const Scope& childScope) const {
148  Scope result; // start with empty string cache
149  result.components = this->components;
150 
151  for (vector<string>::const_iterator it = childScope.components.begin();
152  it != childScope.components.end(); ++it) {
153  result.components.push_back(*it);
154  }
155  result.updateStringCache();
156 
157  return result;
158 }
159 
160 bool Scope::isSubScopeOf(const Scope& other) const {
161 
162  if (components.size() <= other.components.size()) {
163  return false;
164  }
165 
166  for (size_t i = 0; i < other.components.size(); ++i) {
167  if (components[i] != other.components[i]) {
168  return false;
169  }
170  }
171 
172  return true;
173 }
174 
175 bool Scope::isSuperScopeOf(const Scope& other) const {
176 
177  if (components.size() >= other.components.size()) {
178  return false;
179  }
180 
181  for (size_t i = 0; i < components.size(); ++i) {
182  if (components[i] != other.components[i]) {
183  return false;
184  }
185  }
186 
187  return true;
188 }
189 
191  unsigned int scopesize = 1;
192  for (vector<string>::const_iterator it = components.begin();
193  it != components.end(); ++it) {
194  scopesize += it->size() + 1;
195  }
196 
197  this->scopestring.resize(scopesize);
198  this->scopestring[0] = COMPONENT_SEPARATOR;
199  string::iterator cursor = scopestring.begin() + 1;
200  for (vector<string>::const_iterator it = components.begin();
201  it != components.end(); ++it) {
202  std::copy(it->begin(), it->end(), cursor);
203  cursor += it->size();
204  *cursor++ = COMPONENT_SEPARATOR;
205  }
206 }
207 
208 vector<Scope> Scope::superScopes(const bool& includeSelf) const {
209 
210  vector<Scope> result;
211 
212  if (!components.empty()) {
213 
214  // this math only works for scopes that are not the root scope
215  for (size_t requiredComponents = 0;
216  requiredComponents <= components.size() - 1;
217  ++requiredComponents) {
218 
219  Scope super;
220  for (size_t i = 0; i < requiredComponents; ++i) {
221  super.components.push_back(components[i]);
222  }
223  super.updateStringCache();
224  result.push_back(super);
225 
226  }
227 
228  }
229 
230  if (includeSelf) {
231  result.push_back(*this);
232  }
233 
234  return result;
235 }
236 
237 bool Scope::operator==(const Scope& other) const {
238  return toString() == other.toString();
239 }
240 
241 bool Scope::operator<(const Scope& other) const {
242  return toString() < other.toString();
243 }
244 
245 ostream& operator<<(ostream& stream, const Scope& scope) {
246  return stream << "Scope[" << scope.toString() << "]";
247 }
248 
249 }
bool isSubScopeOf(const Scope &other) const
Tests whether this scope is a sub-scope of the given other scope, which means that the other scope is...
Definition: Scope.cpp:160
const std::string & toString() const
Reconstructs a fully formal string representation of the scope with leading an trailing slashes...
Definition: Scope.cpp:143
Scope()
Creates a scope representing "/".
Definition: Scope.cpp:132
void verifyAndSplit(const string &s, vector< string > &components, string &normalizedString)
Validate that s satisfies the regular expression /([-_a-zA-Z0-9]+/)* and splits it at '/' characters...
Definition: Scope.cpp:53
void updateStringCache()
Updates the contents of scopestring based on components.
Definition: Scope.cpp:190
std::string scopestring
Definition: Scope.h:149
const std::vector< std::string > & getComponents() const
Returns all components of the scope as an ordered list.
Definition: Scope.cpp:139
ostream & operator<<(ostream &stream, const MetaData &meta)
Definition: MetaData.cpp:253
bool operator==(const Scope &other) const
Definition: Scope.cpp:237
static const char COMPONENT_SEPARATOR
Definition: Scope.h:139
virtual ~Scope()
Destructor.
Definition: Scope.cpp:136
bool operator<(const Scope &other) const
Definition: Scope.cpp:241
Scope concat(const Scope &childScope) const
Creates a new scope that is a sub-scope of this one with the subordinated scope described by the give...
Definition: Scope.cpp:147
bool isSuperScopeOf(const Scope &other) const
Inverse operation of isSubScopeOf.
Definition: Scope.cpp:175
std::vector< Scope > superScopes(const bool &includeSelf=false) const
Generates all super scopes of this scope including the root scope "/".
Definition: Scope.cpp:208
std::vector< std::string > components
Definition: Scope.h:150
Scope is a descriptor for a hierarchical channel of the unified bus.
Definition: Scope.h:46