GAMS  1.4.0
ArgumentParser.h
Go to the documentation of this file.
1 
54 #ifndef GAMS_UTILITY_ARGUMENT_PARSER_H_
55 #define GAMS_UTILITY_ARGUMENT_PARSER_H_
56 
57 #include <iostream>
58 #include <string>
59 #include "gams/CPP11_compat.h"
60 #include "madara/utility/Utility.h"
61 #include "madara/knowledge/KnowledgeBase.h"
62 #include <iterator>
63 
64 namespace gams
65 {
66  namespace utility
67  {
75  class RadixLess
76  {
77  public:
78  bool operator()(const std::string &lhs, const std::string &rhs) const
79  {
80  size_t lsz = lhs.size(), rsz = rhs.size();
81  if (lsz < rsz)
82  return true;
83  else if (rsz < lsz)
84  return false;
85  else
86  return std::less<std::string>()(lhs, rhs);
87  }
88  };
89 
98  inline madara::knowledge::KnowledgeVector kmap2kvec(
99  const madara::knowledge::KnowledgeMap &kmap)
100  {
101  using namespace madara::knowledge;
102  std::map<std::string, KnowledgeRecord,
103  RadixLess> map(kmap.begin(), kmap.end());
104  KnowledgeVector ret;
105  for (KnowledgeMap::const_iterator i = map.begin(); i != map.end(); ++i)
106  {
107  char c = i->first[0];
108  if (c >= '0' && c <= '9')
109  ret.push_back(i->second);
110  }
111  return ret;
112  }
113 
115  {
116  public:
118 
119  ArgumentParser(const madara::knowledge::KnowledgeMap &kmap)
120  : kmap_(&kmap) {}
121 
122  private:
123  template<class map_iterator>
124  class my_iterator : public std::iterator<
125  std::input_iterator_tag, typename map_iterator::value_type >
126  {
127  public:
129  private:
130  my_iterator() : dummy_(0), parent_(nullptr), cache_valid_(0) {}
131 
133  : dummy_(0), parent_(&parent), it_k_(parent_->kmap_->begin()),
135  {
137  }
138 
139  public:
141  : dummy_(0), parent_(o.parent_), it_k_(o.it_k_), it_v_(o.it_v_),
142  cache_valid_(0) {}
143 
145  {
146  parent_ = o.parent_;
147  it_k_ = o.it_k_;
148  it_v_ = o.it_v_;
149  clear_cache();
150  return *this;
151  }
152 
154 
155  private:
156  union {
157 #ifdef CPP11
158  mutable int dummy_; // initialize this by default
159  mutable value_type cache_;
160 #else
161  mutable char cache_[sizeof(value_type)];
162  // Try to ensure that any possible alignment requirements are met:
163  mutable uint64_t dummy_;
164  mutable long double dummy2_;
165  mutable void * dummy3_;
166 #endif
167  };
168 
169 #ifdef CPP11
170  value_type *cache() const
171  {
172  return cache_valid_ ? &cache_ : nullptr;
173  }
174 #else
175  value_type *cache() const
176  {
177  return cache_valid_ ?
178  reinterpret_cast<value_type*>(&cache_) :
179  nullptr;
180  }
181 #endif
182 
184  map_iterator it_k_;
185  map_iterator it_v_;
186 
187  mutable bool cache_valid_;
188  public:
189  bool at_end() const
190  {
191  return parent_ == nullptr || parent_->kmap_ == nullptr ||
192  it_k_ == parent_->kmap_->end();
193  }
194 
195  bool operator==(const my_iterator &o) const
196  {
197  bool ae1 = at_end(), ae2 = o.at_end();
198  if (ae1 || ae2)
199  return ae1 && ae2;
200  else
201  return parent_ == o.parent_ &&
202  it_k_ == o.it_k_;
203  }
204 
205  bool operator!=(const my_iterator &o) const
206  {
207  return !(*this == o);
208  }
209 
210  public:
211  std::string name() const
212  {
213  return (!is_old_style()) ?
214  it_k_->first :
215  it_k_->second.to_string();
216  }
217 
218  typename value_type::second_type value() const
219  {
220  return it_v_->second;
221  }
222 
223  bool is_old_style() const
224  {
225  return it_k_ != it_v_;
226  }
227 
228  private:
229  bool name_is_old_style() const
230  {
231  char c = it_k_->first[0];
232  if (c >= '0' && c <= '9')
233  return true;
234  return false;
235  }
236 
238  {
239  if (at_end())
240  return;
241  if (!at_end() && name_is_old_style() && !is_old_style())
242  ++it_v_;
243  if (it_v_ == parent_->kmap_->end())
244  it_k_ = it_v_;
245  }
246 
247  void clear_cache()
248  {
249  if (cache())
250  {
251  cache()->~value_type();
252  cache_valid_ = false;
253  }
254  }
255 
256  public:
257  void next()
258  {
259  ++it_v_;
260  it_k_ = it_v_;
262  clear_cache();
263  }
264 
265  const value_type &operator*() const
266  {
267  if (cache())
268  return *cache();
269  value_type *ret = new((void*)&cache_) value_type(name(),value());
270  cache_valid_ = true;
271  return *ret;
272  }
273 
275  {
276  next();
277  return *this;
278  }
279 
281  {
282  my_iterator ret(*this);
283  next();
284  return ret;
285  }
286 
288  {
289  return &operator*();
290  }
291 
292  friend class ArgumentParser;
293  };
294  public:
296 
299 
301  {
302  return const_iterator(*this);
303  }
304 
306  {
307  return const_iterator();
308  }
309 
310  private:
311  const madara::knowledge::KnowledgeMap *kmap_;
312  };
313  }
314 }
315 
316 #endif
value_type::second_type value() const
my_iterator & operator=(const my_iterator &o)
my_iterator(const ArgumentParser &parent)
bool operator==(const my_iterator &o) const
bool operator!=(const my_iterator &o) const
my_iterator< madara::knowledge::KnowledgeMap::iterator > iterator
my_iterator< madara::knowledge::KnowledgeMap::const_iterator > const_iterator
static const_iterator end()
const_iterator begin() const
ArgumentParser(const madara::knowledge::KnowledgeMap &kmap)
const madara::knowledge::KnowledgeMap * kmap_
Compare object suitable for use with standard library.
bool operator()(const std::string &lhs, const std::string &rhs) const
madara::knowledge::KnowledgeVector kmap2kvec(const madara::knowledge::KnowledgeMap &kmap)
Converts a knowledge map into a knowledge vector by adding the values from the map in numerical order...
Contains all GAMS-related tools, classes and code.