ccuty  1.0
 All Classes Namespaces Files Functions Enumerations Macros Pages
ccstringset.hpp
Go to the documentation of this file.
1 //
2 // stringset: string set and indexed string set
3 // (C) Eric Lecolinet 2016/17 - https:www.telecom-paristech.fr/~elc
4 //
5 
17 #ifndef __ccuty_stringset__
18 #define __ccuty_stringset__
19 
20 #include <string>
21 #include <vector>
22 #include <initializer_list>
23 #include <set>
24 #include "ccstring.hpp"
25 
27 namespace ccuty {
28 
29 #if !defined(NO_STRINGIFY) && !defined(STRINGIFY)
30 # define STRINGIFY(s) _STRINGIFY(s)
32 # define _STRINGIFY(s...) #s
33 #endif
34 
35 
36 #if !defined(NO_STRING_SWITCH) && !defined(STRING_SWITCH)
37 
51 #define STRING_SWITCH(str, ...) \
52 enum {__VA_ARGS__}; \
53 static const ccuty::stringset _stringset_ ## __LINE__(#__VA_ARGS__); \
54 switch(_stringset_ ## __LINE__[str])
55 #endif
56 
57 
92  class stringset {
93  public:
94  struct elem {
95  elem(const std::string& str, unsigned int id) : str(str), id(id) {}
96  const std::string str;
97  const unsigned int id;
98  };
99 
100  struct string_comp {
101  bool operator()(const elem& left, const elem& right) const {return left.str<right.str;}
102  };
103 
104  using string_set = std::set<elem, string_comp>;
105 
106  // - - - -
107 
110 
115  explicit stringset(const char* str) {
116  std::vector<std::string> v;
117  ccuty::strsplit(v, str, ",");
118  append(v);
119  }
120 
125  explicit stringset(const std::string& str) {
126  std::vector<std::string> v;
127  ccuty::strsplit(v, str, ",");
128  append(v);
129  }
130 
135  stringset(std::initializer_list<const char*> tokens) {
136  append(tokens);
137  }
138 
143  stringset(std::initializer_list<elem> tokens) {
144  append(tokens);
145  }
146 
150  template <typename T> explicit stringset(const T& tokens) {
151  append(tokens);
152  }
153 
155  bool empty() const {
156  return elements_.empty();
157  }
158 
160  size_t size() const {
161  return elements_.size();
162  }
163 
165  const string_set& elements() const {return elements_;}
166 
168  int operator[](const std::string& token) const {
169  auto it = elements_.find(elem{token,0});
170  return it==elements_.end() ? -1 : it->id;
171  }
172 
176  int starts_with(const std::string& str) const {
177  int count = 0;
178  int value = -1;
179  for (auto& it : elements_) {
180  if (it.str.compare(0, str.length(), str) == 0) {
181  if (it.str.length() == str.length()) return it.id; // exact match
182  else value = it.id;
183  count++;
184  }
185  }
186  if (count == 0) return -1; // no match
187  else if (count == 1) return value; // one match
188  else return -2; // multiple matches
189  }
190 
192  void clear() {
193  elements_.clear();
194  }
195 
199  int insert(const std::string& token) {
200  auto p = elements_.insert(elem{token, lastid_});
201  if (p.second) lastid_++; // not a duplicate
202  return p.first->id;
203  }
204 
208  int insert(const char* token) {
209  auto p = elements_.insert(elem{token, lastid_});
210  if (p.second) lastid_++;
211  return p.first->id;
212  }
213 
217  int insert(const elem& e) {
218  auto p = elements_.insert(e);
219  if (p.second) {
220  if (e.id >= lastid_) lastid_ = e.id + 1;
221  //else if (e.id < 0) p.first->id = lastid_++;
222  }
223  return p.first->id;
224  }
225 
229  template <typename T> void append(const T& cont) {
230  for (auto&& it : cont) insert(it);
231  }
232 
233  protected:
234  unsigned int lastid_{0};
235  string_set elements_;
236  };
237 
238  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
239 
244  class istringset : public stringset {
245  public:
246  struct comp_id {
247  bool operator()(const elem& left, const elem& right) const {return left.id < right.id;}
248  };
249  using id_set = std::set<elem, comp_id>;
250 
252  static const std::string& none() {
253  static std::string empty;
254  return empty;
255  }
256 
257  // - - - -
258 
261 
266  explicit istringset(const char* str) {
267  std::vector<std::string> v;
268  ccuty::strsplit(v, str, ",");
269  append(v);
270  }
271 
276  explicit istringset(const std::string& str) {
277  std::vector<std::string> v;
278  ccuty::strsplit(v, str, ",");
279  append(v);
280  }
281 
286  explicit istringset(std::initializer_list<const char*> tokens) {
287  append(tokens);
288  }
289 
296  istringset(std::initializer_list<elem> tokens) {
297  append(tokens);
298  }
299 
303  template <typename T> explicit istringset(const T& tokens) {
304  append(tokens);
305  }
306 
308  const id_set& ids() const {return ids_;}
309 
311  int operator[](const std::string& token) const {
312  return stringset::operator[](token);
313  }
314 
316  const std::string& operator[](unsigned int id) const {
317  auto it = ids_.find(elem{"", id});
318  if (it==ids_.end()) return none(); else return it->str;
319  }
320 
322  void clear() {
323  elements_.clear();
324  ids_.clear();
325  }
326 
330  int insert(const std::string& token) {
331  auto p = elements_.insert(elem{token, lastid_});
332  if (p.second) { // not a duplicate
333  lastid_++;
334  ids_.insert(*p.first);
335  }
336  return p.first->id;
337  }
338 
342  int insert(const char* token) {
343  auto p = elements_.insert(elem{token, lastid_});
344  if (p.second) {
345  lastid_++;
346  ids_.insert(*p.first);
347  }
348  return p.first->id;
349  }
350 
354  int insert(const elem& e) {
355  auto p = elements_.insert(e);
356  if (p.second) {
357  if (e.id >= lastid_) lastid_ = e.id + 1;
358  //else if (e.id < 0) p.first->id = lastid_++;
359  ids_.insert(*p.first);
360  }
361  return p.first->id;
362  }
363 
367  template <typename T> void append(const T& cont) {
368  for (auto& it : cont) insert(it);
369  }
370 
371  protected:
372  id_set ids_;
373  };
374 
375 }
376 #endif