NTRT Simulator
 All Classes Files Functions Variables Typedefs Friends Pages
tgTags.h
Go to the documentation of this file.
1 /*
2  * Copyright © 2012, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is licensed
7  * under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * http://www.apache.org/licenses/LICENSE-2.0.
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15  * either express or implied. See the License for the specific language
16  * governing permissions and limitations under the License.
17 */
18 
25 #ifndef TG_TAGS_H
26 #define TG_TAGS_H
27 
28 #include <deque>
29 #include <set>
30 #include <string>
31 #include <algorithm>
32 #include <iostream>
33 #include <sstream>
34 #include <locale> // std::locale, std::isalnum
35 
36 #include "tgException.h"
37 
38 struct tgTagException : public tgException
39 {
40  tgTagException(std::string ss) : tgException(ss) {}
41 };
42 
43 class tgTags
44 {
45 public:
46  tgTags() {}
47  tgTags(const std::string& space_separated_tags)
48  {
49  append(space_separated_tags);
50  }
51 
52  bool contains(const std::string& space_separated_tags) const
53  {
54  const std::deque<std::string> tags = splitTags(space_separated_tags);
55  return contains(tags);
56  }
57 
58  bool contains(const tgTags& tags) const
59  {
60  return contains(tags.getTags());
61  }
62 
63  bool containsAny(const std::string& space_separated_tags)
64  {
65  std::deque<std::string> tags = splitTags(space_separated_tags);
66  return containsAny(tags);
67  }
68 
69  bool containsAny(const tgTags& tags)
70  {
71  return containsAny(tags.getTags());
72  }
73 
74  void append(const std::string& space_separated_tags)
75  {
76  append(splitTags(space_separated_tags));
77  }
78 
79  void append(const tgTags& tags)
80  {
81  append(tags.getTags());
82  }
83 
84  void prepend(const std::string& space_separated_tags)
85  {
86  prepend(splitTags(space_separated_tags));
87  }
88 
89  void prepend(const tgTags& tags)
90  {
91  prepend(tags.getTags());
92  }
93 
94  void remove(const std::string& space_separated_tags)
95  {
96  remove(splitTags(space_separated_tags));
97  }
98 
99  void remove(const tgTags& tags)
100  {
101  remove(tags.getTags());
102  }
103 
104  const int size() const
105  {
106  return m_tags.size();
107  }
108 
109  const bool empty() const
110  {
111  return m_tags.empty();
112  }
113 
114  static std::deque<std::string> splitTags(const std::string &s, char delim = ' ') {
115  std::deque<std::string> elems;
116  std::stringstream ss(s);
117  std::string item;
118  while (std::getline(ss, item, delim)) {
119  if(!item.empty())
120  elems.push_back(item);
121  }
122  return elems;
123  }
124 
129  static std::deque<std::string> splitTags(const std::deque<std::string> &s,
130  char delim = ' ') {
131  std::deque<std::string> result;
132  for(int i = 0; i < s.size(); i++) {
133  std::deque<std::string> spl = splitTags(s[i]);
134  for(int j = 0; j < spl.size(); j++) {
135  result.push_back(spl[j]);
136  }
137  }
138  return result;
139  }
140 
141  std::string joinTags(std::string delim = "_") {
142  std::stringstream ss;
143  for(int i = 0; i < m_tags.size(); i++) {
144  if(i != 0) {
145  ss << delim;
146  }
147  ss << m_tags[i];
148  }
149  return ss.str();
150  }
151 
155  bool isIntegery(const std::string s) const
156  {
157  if(s.empty()) {
158  return false;
159  }
160  std::stringstream ss;
161  ss << atoi(s.c_str()); //add number to the stream
162  // If our initial string equals the string converted to int and back to string, it's integery.
163  if(ss.str() == s)
164  return true;
165  return false;
166  }
167 
168  bool isValid(std::string tag)
169  {
170  if (tag.empty())
171  return false;
172 
173  // Can't be an integer
174  if(isIntegery(tag)) {
175  return false;
176  }
177  // Can't contain the delimiter (space)
178  if(tag.find(' ') != std::string::npos) {
179  return false;
180  }
181  // Must be alphanumeric, or at least can't start with strange characters or contain things like '|'
182  // @todo: Add this functionality. Apparently it's not as straightforward as one might hope...
183  //if(!std::isalnum(tag)) {
184  // return false;
185  //}
186  return true;
187  }
188 
189  std::deque<std::string>& getTags()
190  {
191  return m_tags;
192  }
193 
194  const std::deque<std::string>& getTags() const
195  {
196  return m_tags;
197  }
198 
202  const std::set<std::string> asSet() const
203  {
204  return std::set<std::string>(m_tags.begin(), m_tags.end());
205  }
206 
213  std::string& operator[](int key) {
214  return m_tags[key];
215  }
216 
217  const std::string& operator[](int key) const {
218  return m_tags[key];
219  }
220 
224  bool operator==(const tgTags& rhs)
225  {
226  return rhs.asSet() == asSet();
227  }
228 
229  tgTags& operator+=(const tgTags& rhs)
230  {
231  const std::deque<std::string>& other = rhs.getTags();
232  m_tags.insert(m_tags.end(), other.begin(), other.end());
233  return *this;
234  }
235 
236 private:
237 
242  void appendOne(std::string tag) {
243  if(!isValid(tag)) {
244  throw tgTagException("Invalid tag '" + tag + "' - tags must be alphanumeric and may not be castable to int.");
245  }
246  if(!containsOne(tag)) {
247  m_tags.push_back(tag);
248  }
249  }
250 
251  void append(const std::deque<std::string>& tags)
252  {
253  for(int i = 0; i < tags.size(); i++) {
254  appendOne(tags[i]);
255  }
256  }
257 
258  void prependOne(std::string tag) {
259  if(isValid(tag) && !containsOne(tag)) {
260  m_tags.push_front(tag);
261  }
262  }
263 
264  void prepend(const std::deque<std::string>& tags)
265  {
266  for(int i = 0; i < tags.size(); i++) {
267  prependOne(tags[i]);
268  }
269  }
270 
271  bool contains(const std::deque<std::string>& tags) const {
272  for(int i = 0; i < tags.size(); i++) {
273  if(!containsOne(tags[i]))
274  return false;
275  }
276  return true;
277  }
278 
279  bool containsAny(const std::deque<std::string>& tags) const {
280  for(int i = 0; i < tags.size(); i++) {
281  if(containsOne(tags[i]))
282  return true;
283  }
284  return false;
285  }
286 
290  bool containsOne(std::string tag) const {
291  return (std::find(m_tags.begin(), m_tags.end(), tag) != m_tags.end());
292  }
293 
294  void removeOne(std::string tag) {
295  m_tags.erase(std::remove(m_tags.begin(), m_tags.end(), tag), m_tags.end());
296  }
297 
298  void remove(std::deque<std::string> tags) {
299  for(int i = 0; i < tags.size(); i++) {
300  removeOne(tags[i]);
301  }
302  }
303 
304  std::deque<std::string> m_tags;
305 };
306 
314 inline std::ostream&
315 operator<<(std::ostream& os, const tgTags& tags)
316 {
317  const std::deque<std::string>& t = tags.getTags();
318  for(size_t i = 0; i < t.size(); ++i)
319  {
320  if(i != 0)
321  os << " ";
322  os << t[i];
323  }
324  return os;
325 }
326 
327 inline tgTags operator+(tgTags lhs, const tgTags& rhs)
328 {
329  lhs += rhs;
330  return lhs;
331 }
332 
333 inline bool operator< (const tgTags& lhs, const tgTags& rhs){ return lhs.asSet() < rhs.asSet(); }
334 inline bool operator> (const tgTags& lhs, const tgTags& rhs){return rhs < lhs;}
335 inline bool operator<=(const tgTags& lhs, const tgTags& rhs){return !(lhs > rhs);}
336 inline bool operator>=(const tgTags& lhs, const tgTags& rhs){return !(lhs < rhs);}
337 
338 
339 #endif
std::ostream & operator<<(std::ostream &os, const tgTags &tags)
Definition: tgTags.h:315
bool isIntegery(const std::string s) const
Definition: tgTags.h:155
static std::deque< std::string > splitTags(const std::deque< std::string > &s, char delim= ' ')
Definition: tgTags.h:129
bool operator==(const tgTags &rhs)
Definition: tgTags.h:224
const std::set< std::string > asSet() const
Definition: tgTags.h:202
std::string & operator[](int key)
Definition: tgTags.h:213
Extension of std::exception for use within the library.
Definition: tgTags.h:43