Atlas  0.7.0
Networking protocol for the Worldforge system.
Element.h
1 // This file may be redistributed and modified only under the terms of
2 // the GNU Lesser General Public License (See COPYING for details).
3 // Copyright (C) 2000-2001 Stefanus Du Toit, Karsten-O. Laux and Al Riddoch
4 
5 // $Id$
6 
7 #ifndef ATLAS_MESSAGE_ELEMENT_H
8 #define ATLAS_MESSAGE_ELEMENT_H
9 
10 #include <Atlas/Exception.h>
11 #include <Atlas/float.h>
12 
13 #include <string>
14 #include <map>
15 #include <vector>
16 #include <cinttypes>
17 
18 namespace Atlas { namespace Message {
19 
22 {
23  public:
24  WrongTypeException() noexcept : Atlas::Exception("Wrong Message::Element type") { }
25 };
26 
27 class Element;
28 
29 typedef std::int64_t IntType;
30 typedef double FloatType;
31 typedef void * PtrType;
32 typedef std::string StringType;
33 typedef std::map<std::string, Element> MapType;
34 typedef std::vector<Element> ListType;
35 
39 class Element
40 {
41 public:
42  enum Type {
43  TYPE_NONE,
44  TYPE_INT,
45  TYPE_FLOAT,
46  TYPE_PTR,
47  TYPE_STRING,
48  TYPE_MAP,
49  TYPE_LIST
50  };
51 
52 private:
53 
55  void clear(Type new_type = TYPE_NONE);
56 
57 public:
60  : t(TYPE_NONE)
61  {
62  }
63 
65  ~Element()
66  {
67  clear();
68  }
69 
71  Element(const Element& obj);
72 
75  Element(Element&& obj) noexcept;
76 
78  Element(int v)
79  : t(TYPE_INT), i(v)
80  {
81  }
82 
83  Element(long v)
84  : t(TYPE_INT), i(v)
85  {
86  }
87 
88  Element(long long v)
89  : t(TYPE_INT), i(v)
90  {
91  }
92 
94  Element(bool v)
95  : t(TYPE_INT), i(v)
96  {
97  }
98 
100  Element(FloatType v)
101  : t(TYPE_FLOAT), f(v)
102  {
103  }
104 
106  Element(PtrType v)
107  : t(TYPE_PTR), p(v)
108  {
109  }
110 
112  Element(const char* v)
113  : t(TYPE_STRING)
114  {
115  if(v) {
116  s = new DataType<StringType>(v);
117  }
118  else
119  s = new DataType<StringType>();
120  }
121 
123  Element(const StringType& v)
124  : t(TYPE_STRING)
125  {
126  s = new DataType<StringType>(v);
127  }
129  Element(StringType&& v)
130  : t(TYPE_STRING)
131  {
132  s = new DataType<StringType>(std::move(v));
133  }
134 
136  Element(const MapType& v)
137  : t(TYPE_MAP)
138  {
139  m = new DataType<MapType>(v);
140  }
142  Element(MapType&& v)
143  : t(TYPE_MAP)
144  {
145  m = new DataType<MapType>(std::move(v));
146  }
147 
149  Element(const ListType& v)
150  : t(TYPE_LIST)
151  {
152  l = new DataType<ListType>(v);
153  }
155  Element(ListType&& v)
156  : t(TYPE_LIST)
157  {
158  l = new DataType<ListType>(std::move(v));
159  }
160 
162  Element& operator=(const Element& obj);
163 
169  Element& operator=(Element&& obj) noexcept;
170 
171  Element& operator=(int v)
172  {
173  if (TYPE_INT != t)
174  {
175  clear(TYPE_INT);
176  }
177  i = v;
178  return *this;
179  }
180 
181  Element& operator=(long v)
182  {
183  if (TYPE_INT != t)
184  {
185  clear(TYPE_INT);
186  }
187  i = v;
188  return *this;
189  }
190 
191  Element& operator=(long long v)
192  {
193  if (TYPE_INT != t)
194  {
195  clear(TYPE_INT);
196  }
197  i = v;
198  return *this;
199  }
200 
201  Element& operator=(bool v)
202  {
203  if (TYPE_INT != t)
204  {
205  clear(TYPE_INT);
206  }
207  i = v;
208  return *this;
209  }
210 
211  Element& operator=(FloatType v)
212  {
213  if (TYPE_FLOAT != t)
214  {
215  clear(TYPE_FLOAT);
216  }
217  f = v;
218  return *this;
219  }
220 
221  Element& operator=(PtrType v)
222  {
223  if (TYPE_PTR != t)
224  {
225  clear(TYPE_PTR);
226  }
227  p = v;
228  return *this;
229  }
230 
231  Element& operator=(const char * v)
232  {
233  if (TYPE_STRING != t || !s->unique())
234  {
235  clear(TYPE_STRING);
236  s = new DataType<StringType>(std::string(v));
237  } else {
238  *s = StringType(v);
239  }
240  return *this;
241  }
242 
243  Element& operator=(const StringType & v)
244  {
245  if (TYPE_STRING != t || !s->unique())
246  {
247  clear(TYPE_STRING);
248  s = new DataType<StringType>(v);
249  } else {
250  *s = v;
251  }
252  return *this;
253  }
254 
255  Element& operator=(StringType && v)
256  {
257  if (TYPE_STRING != t || !s->unique())
258  {
259  clear(TYPE_STRING);
260  s = new DataType<StringType>(v);
261  } else {
262  *s = v;
263  }
264  return *this;
265  }
266 
267  Element& operator=(const MapType & v)
268  {
269  if (TYPE_MAP != t || !m->unique())
270  {
271  clear(TYPE_MAP);
272  m = new DataType<MapType>(v);
273  } else {
274  *m = v;
275  }
276  return *this;
277  }
278 
279  Element& operator=(MapType && v)
280  {
281  if (TYPE_MAP != t || !m->unique())
282  {
283  clear(TYPE_MAP);
284  m = new DataType<MapType>(std::move(v));
285  } else {
286  *m = v;
287  }
288  return *this;
289  }
290 
291  Element& operator=(const ListType & v)
292  {
293  if (TYPE_LIST != t || !l->unique())
294  {
295  clear(TYPE_LIST);
296  l = new DataType<ListType>(v);
297  } else {
298  *l = v;
299  }
300  return *this;
301  }
302 
303  Element& operator=(ListType && v)
304  {
305  if (TYPE_LIST != t || !l->unique())
306  {
307  clear(TYPE_LIST);
308  l = new DataType<ListType>(std::move(v));
309  } else {
310  *l = v;
311  }
312  return *this;
313  }
314 
316  bool operator==(const Element& o) const;
317 
319  template<class C>
320  bool operator!=(C c) const
321  {
322  return !(*this == c);
323  }
324 
326  bool operator==(int v) const
327  {
328  return (t == TYPE_INT && i == v);
329  }
330 
332  bool operator==(long v) const
333  {
334  return (t == TYPE_INT && i == v);
335  }
336 
337  bool operator==(long long v) const
338  {
339  return (t == TYPE_INT && i == v);
340  }
342  bool operator==(FloatType v) const
343  {
344  return t == TYPE_FLOAT && Equal(f, v);
345  }
346 
348  bool operator==(PtrType v) const
349  {
350  return t == TYPE_PTR && p == v;
351  }
352 
354  bool operator==(const char * v) const
355  {
356  if(t == TYPE_STRING)
357  return (*s == v);
358  return false;
359  }
360 
362  bool operator==(const StringType& v) const
363  {
364  if(t == TYPE_STRING)
365  return (*s == v);
366  return false;
367  }
368 
370  bool operator==(const MapType& v) const
371  {
372  if(t == TYPE_MAP)
373  return (*m == v);
374  return false;
375  }
376 
378  bool operator==(const ListType& v) const
379  {
380  if (t == TYPE_LIST)
381  return (*l == v);
382  return false;
383  }
384 
386  Type getType() const { return t; }
388  bool isNone() const { return (t == TYPE_NONE); }
390  bool isInt() const { return (t == TYPE_INT); }
392  bool isFloat() const { return (t == TYPE_FLOAT); }
394  bool isPtr() const { return (t == TYPE_PTR); }
396  bool isNum() const { return ((t == TYPE_FLOAT) || (t == TYPE_INT)); }
398  bool isString() const { return (t == TYPE_STRING); }
400  bool isMap() const { return (t == TYPE_MAP); }
402  bool isList() const { return (t == TYPE_LIST); }
403 
405  IntType asInt() const
406  {
407  if (t == TYPE_INT) return i;
408  throw WrongTypeException();
409  }
410  IntType Int() const
411  {
412  return i;
413  }
415  FloatType asFloat() const
416  {
417  if (t == TYPE_FLOAT) return f;
418  throw WrongTypeException();
419  }
420  FloatType Float() const
421  {
422  return f;
423  }
425  PtrType asPtr() const
426  {
427  if (t == TYPE_PTR) return p;
428  throw WrongTypeException();
429  }
430  PtrType Ptr() const
431  {
432  return p;
433  }
435  FloatType asNum() const
436  {
437  if (t == TYPE_FLOAT) return f;
438  if (t == TYPE_INT) return FloatType(i);
439  throw WrongTypeException();
440  }
442  const std::string& asString() const
443  {
444  if (t == TYPE_STRING) return *s;
445  throw WrongTypeException();
446  }
448  std::string& asString()
449  {
450  if (t == TYPE_STRING) return *(s = s->makeUnique());
451  throw WrongTypeException();
452  }
453  const StringType& String() const
454  {
455  return *s;
456  }
457  StringType& String()
458  {
459  return *(s = s->makeUnique());
460  }
461 
468  StringType&& moveString() {
469  if (t != TYPE_STRING) throw WrongTypeException();
470  s = s->makeUnique();
471  return s->move();
472  }
473 
475  const MapType& asMap() const
476  {
477  if (t == TYPE_MAP) return *m;
478  throw WrongTypeException();
479  }
481  MapType& asMap()
482  {
483  if (t == TYPE_MAP) return *(m = m->makeUnique());
484  throw WrongTypeException();
485  }
486  const MapType& Map() const
487  {
488  return *m;
489  }
490  MapType& Map()
491  {
492  return *(m = m->makeUnique());
493  }
494 
501  MapType&& moveMap() {
502  if (t != TYPE_MAP) throw WrongTypeException();
503  m = m->makeUnique();
504  return m->move();
505  }
506 
508  const ListType& asList() const
509  {
510  if (t == TYPE_LIST) return *l;
511  throw WrongTypeException();
512  }
514  ListType& asList()
515  {
516  if (t == TYPE_LIST) return *(l = l->makeUnique());
517  throw WrongTypeException();
518  }
519  const ListType& List() const
520  {
521  return *l;
522  }
523  ListType& List()
524  {
525  return *(l = l->makeUnique());
526  }
527 
534  ListType&& moveList() {
535  if (t != TYPE_LIST) throw WrongTypeException();
536  l = l->makeUnique();
537  return l->move();
538  }
539 
540  static const char * typeName(Type);
541 
542 protected:
543 
544  template<class C>
545  class DataType
546  {
547  public:
548  DataType() : _refcount(1), _data(nullptr) {}
549 
550  explicit DataType(const C& c) : _refcount(1), _data(c) {}
551  explicit DataType(C&& c) : _refcount(1), _data(std::move(c)) {}
552  DataType(const DataType&) = delete;
553 
554  DataType& operator=(const C& c) {_data = c; return *this;}
555  DataType& operator=(const C&& c) {_data = std::move(c); return *this;}
556  DataType& operator=(const DataType&) = delete;
557 
558  bool operator==(const C& c) const {return _data == c;}
559 
560  void ref() {++_refcount;}
561  void unref() {if(--_refcount == 0) delete this;}
562 
563  bool unique() const {return _refcount == 1;}
564  DataType* makeUnique()
565  {
566  if(unique())
567  return this;
568  unref(); // _refcount > 1, so this is fine
569  return new DataType(_data);
570  }
571 
572  operator C&() {return _data;}
579  C&& move() {
580  return std::move(_data);
581  }
582 // operator const C&() const {return _data;}
583 
584  private:
585 
586  unsigned long _refcount;
587  C _data;
588  };
589 
590  Type t;
591  union {
592  IntType i;
593  FloatType f;
594  void* p;
595  DataType<StringType>* s;
596  DataType<MapType>* m;
597  DataType<ListType>* l;
598  };
599 };
600 
601 } } // namespace Atlas::Message
602 
603 
604 #endif // ATLAS_MESSAGE_ELEMENT_H
bool operator==(FloatType v) const
Check for equality with a double.
Definition: Element.h:342
ListType & asList()
Retrieve the current value as a non-const ListType reference.
Definition: Element.h:514
Element(const StringType &v)
Set type to std::string, and value to v.
Definition: Element.h:123
bool operator==(const StringType &v) const
Check for equality with a std::string.
Definition: Element.h:362
Element(FloatType v)
Set type to double, and value to v.
Definition: Element.h:100
bool isString() const
Check whether the current type is std::string.
Definition: Element.h:398
const std::string & asString() const
Retrieve the current value as a const std::string reference.
Definition: Element.h:442
Element(bool v)
Set type to int, and value to v.
Definition: Element.h:94
bool operator==(const Element &o) const
Check for equality with another Element.
Definition: Element.cpp:176
bool isNum() const
Check whether the current type is numeric.
Definition: Element.h:396
Element(ListType &&v)
Set type to ListType, and move v.
Definition: Element.h:155
PtrType asPtr() const
Retrieve the current value as a pointer.
Definition: Element.h:425
FloatType asFloat() const
Retrieve the current value as a double.
Definition: Element.h:415
FloatType asNum() const
Retrieve the current value as a number.
Definition: Element.h:435
Element(const char *v)
Set type to std::string, and value to v.
Definition: Element.h:112
bool isFloat() const
Check whether the current type is double.
Definition: Element.h:392
Element(int v)
Set type to int, and value to v.
Definition: Element.h:78
bool isPtr() const
Check whether the current type is pointer.
Definition: Element.h:394
const MapType & asMap() const
Retrieve the current value as a const MapType reference.
Definition: Element.h:475
bool operator==(int v) const
Check for equality with a int.
Definition: Element.h:326
Element(StringType &&v)
Set type to std::string, and move v.
Definition: Element.h:129
Type getType() const
Get the current type.
Definition: Element.h:386
MapType && moveMap()
Definition: Element.h:501
Element(PtrType v)
Set type to PtrType, and value to v.
Definition: Element.h:106
MapType & asMap()
Retrieve the current value as a non-const MapType reference.
Definition: Element.h:481
bool operator==(const MapType &v) const
Check for equality with a MapType.
Definition: Element.h:370
std::string & asString()
Retrieve the current value as a non-const std::string reference.
Definition: Element.h:448
bool operator==(const ListType &v) const
Check for equality with a ListType.
Definition: Element.h:378
StringType && moveString()
Definition: Element.h:468
bool operator==(PtrType v) const
Check for equality with a pointer.
Definition: Element.h:348
Element & operator=(const Element &obj)
overload assignment operator !
Definition: Element.cpp:96
const ListType & asList() const
Retrieve the current value as a const ListType reference.
Definition: Element.h:508
Element()
Construct an empty object.
Definition: Element.h:59
bool isMap() const
Check whether the current type is MapType.
Definition: Element.h:400
bool operator!=(C c) const
Check for inequality with anything we can check equality with.
Definition: Element.h:320
Element(const ListType &v)
Set type to ListType, and value to v.
Definition: Element.h:149
bool isList() const
Check whether the current type is ListType.
Definition: Element.h:402
bool operator==(const char *v) const
Check for equality with a const char *.
Definition: Element.h:354
Element(MapType &&v)
Set type to MapType, and move v.
Definition: Element.h:142
IntType asInt() const
Retrieve the current value as a int.
Definition: Element.h:405
Element(const MapType &v)
Set type to MapType, and value to v.
Definition: Element.h:136
ListType && moveList()
Definition: Element.h:534
bool operator==(long v) const
Check for equality with a int.
Definition: Element.h:332
bool isNone() const
Check whether the current type is nothing.
Definition: Element.h:388
bool isInt() const
Check whether the current type is int.
Definition: Element.h:390
An exception class issued when the wrong type is requested in as().
Definition: Element.h:22
Definition: Bridge.h:21