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 
17 namespace Atlas { namespace Message {
18 
21 {
22  public:
23  WrongTypeException() noexcept : Atlas::Exception("Wrong Message::Element type") { }
24 };
25 
26 class Element;
27 
28 typedef std::int64_t IntType;
29 typedef double FloatType;
30 typedef void * PtrType;
31 typedef std::string StringType;
32 typedef std::map<std::string, Element> MapType;
33 typedef std::vector<Element> ListType;
34 
38 class Element
39 {
40 public:
41  enum Type {
42  TYPE_NONE,
43  TYPE_INT,
44  TYPE_FLOAT,
45  TYPE_PTR,
46  TYPE_STRING,
47  TYPE_MAP,
48  TYPE_LIST
49  };
50 
51 private:
52 
54  void clear(Type new_type = TYPE_NONE);
55 
56 public:
59  : t(TYPE_NONE)
60  {
61  }
62 
64  ~Element()
65  {
66  clear();
67  }
68 
70  Element(const Element& obj);
71 
74  Element(Element&& obj) noexcept;
75 
77  Element(int v)
78  : t(TYPE_INT), i(v)
79  {
80  }
81 
82  Element(long v)
83  : t(TYPE_INT), i(v)
84  {
85  }
86 
88  Element(bool v)
89  : t(TYPE_INT), i(v)
90  {
91  }
92 
94  Element(long long v)
95  : t(TYPE_INT), i(v)
96  {
97  }
98 
100  Element(float v)
101  : t(TYPE_FLOAT), f(v)
102  {
103  }
104 
106  Element(FloatType v)
107  : t(TYPE_FLOAT), f(v)
108  {
109  }
110 
112  Element(PtrType v)
113  : t(TYPE_PTR), p(v)
114  {
115  }
116 
118  Element(const char* v)
119  : t(TYPE_STRING)
120  {
121  if(v) {
122  s = new DataType<StringType>(v);
123  }
124  else
125  s = new DataType<StringType>();
126  }
127 
129  Element(const StringType& v)
130  : t(TYPE_STRING)
131  {
132  s = new DataType<StringType>(v);
133  }
135  Element(StringType&& v)
136  : t(TYPE_STRING)
137  {
138  s = new DataType<StringType>(std::move(v));
139  }
140 
142  Element(const MapType& v)
143  : t(TYPE_MAP)
144  {
145  m = new DataType<MapType>(v);
146  }
148  Element(MapType&& v)
149  : t(TYPE_MAP)
150  {
151  m = new DataType<MapType>(std::move(v));
152  }
153 
155  Element(const ListType& v)
156  : t(TYPE_LIST)
157  {
158  l = new DataType<ListType>(v);
159  }
161  Element(ListType&& v)
162  : t(TYPE_LIST)
163  {
164  l = new DataType<ListType>(std::move(v));
165  }
166 
168  Element& operator=(const Element& obj);
169 
175  Element& operator=(Element&& obj) noexcept;
176 
177  Element& operator=(int v)
178  {
179  if (TYPE_INT != t)
180  {
181  clear(TYPE_INT);
182  }
183  i = v;
184  return *this;
185  }
186 
187  Element& operator=(long v)
188  {
189  if (TYPE_INT != t)
190  {
191  clear(TYPE_INT);
192  }
193  i = v;
194  return *this;
195  }
196 
197  Element& operator=(bool v)
198  {
199  if (TYPE_INT != t)
200  {
201  clear(TYPE_INT);
202  }
203  i = v;
204  return *this;
205  }
206 
207  Element& operator=(long long v)
208  {
209  if (TYPE_INT != t)
210  {
211  clear(TYPE_INT);
212  }
213  i = v;
214  return *this;
215  }
216 
217  Element& operator=(float v)
218  {
219  if (TYPE_FLOAT != t)
220  {
221  clear(TYPE_FLOAT);
222  }
223  f = v;
224  return *this;
225  }
226 
227  Element& operator=(FloatType v)
228  {
229  if (TYPE_FLOAT != t)
230  {
231  clear(TYPE_FLOAT);
232  }
233  f = v;
234  return *this;
235  }
236 
237  Element& operator=(PtrType v)
238  {
239  if (TYPE_PTR != t)
240  {
241  clear(TYPE_PTR);
242  }
243  p = v;
244  return *this;
245  }
246 
247  Element& operator=(const char * v)
248  {
249  if (TYPE_STRING != t || !s->unique())
250  {
251  clear(TYPE_STRING);
252  s = new DataType<StringType>(std::string(v));
253  } else {
254  *s = StringType(v);
255  }
256  return *this;
257  }
258 
259  Element& operator=(const StringType & v)
260  {
261  if (TYPE_STRING != t || !s->unique())
262  {
263  clear(TYPE_STRING);
264  s = new DataType<StringType>(v);
265  } else {
266  *s = v;
267  }
268  return *this;
269  }
270 
271  Element& operator=(StringType && v)
272  {
273  if (TYPE_STRING != t || !s->unique())
274  {
275  clear(TYPE_STRING);
276  s = new DataType<StringType>(v);
277  } else {
278  *s = v;
279  }
280  return *this;
281  }
282 
283  Element& operator=(const MapType & v)
284  {
285  if (TYPE_MAP != t || !m->unique())
286  {
287  clear(TYPE_MAP);
288  m = new DataType<MapType>(v);
289  } else {
290  *m = v;
291  }
292  return *this;
293  }
294 
295  Element& operator=(MapType && v)
296  {
297  if (TYPE_MAP != t || !m->unique())
298  {
299  clear(TYPE_MAP);
300  m = new DataType<MapType>(std::move(v));
301  } else {
302  *m = v;
303  }
304  return *this;
305  }
306 
307  Element& operator=(const ListType & v)
308  {
309  if (TYPE_LIST != t || !l->unique())
310  {
311  clear(TYPE_LIST);
312  l = new DataType<ListType>(v);
313  } else {
314  *l = v;
315  }
316  return *this;
317  }
318 
319  Element& operator=(ListType && v)
320  {
321  if (TYPE_LIST != t || !l->unique())
322  {
323  clear(TYPE_LIST);
324  l = new DataType<ListType>(std::move(v));
325  } else {
326  *l = v;
327  }
328  return *this;
329  }
330 
332  bool operator==(const Element& o) const;
333 
334 #if defined(__GNUC__) && __GNUC__ < 3
335  bool operator!=(const Element& o) const
336  {
337  return !(*this == o);
338  }
339 #endif // defined(__GNUC__) && __GNUC__ < 3
340 
342  template<class C>
343  bool operator!=(C c) const
344  {
345  return !(*this == c);
346  }
347 
349  bool operator==(int v) const
350  {
351  return (t == TYPE_INT && i == v);
352  }
353 
355  bool operator==(long v) const
356  {
357  return (t == TYPE_INT && i == v);
358  }
359 
361  bool operator==(long long v) const
362  {
363  return (t == TYPE_INT && i == v);
364  }
365 
367  bool operator==(FloatType v) const
368  {
369  return t == TYPE_FLOAT && Equal(f, v);
370  }
371 
373  bool operator==(PtrType v) const
374  {
375  return t == TYPE_PTR && p == v;
376  }
377 
379  bool operator==(const char * v) const
380  {
381  if(t == TYPE_STRING)
382  return (*s == v);
383  return false;
384  }
385 
387  bool operator==(const StringType& v) const
388  {
389  if(t == TYPE_STRING)
390  return (*s == v);
391  return false;
392  }
393 
395  bool operator==(const MapType& v) const
396  {
397  if(t == TYPE_MAP)
398  return (*m == v);
399  return false;
400  }
401 
403  bool operator==(const ListType& v) const
404  {
405  if (t == TYPE_LIST)
406  return (*l == v);
407  return false;
408  }
409 
411  Type getType() const { return t; }
413  bool isNone() const { return (t == TYPE_NONE); }
415  bool isInt() const { return (t == TYPE_INT); }
417  bool isFloat() const { return (t == TYPE_FLOAT); }
419  bool isPtr() const { return (t == TYPE_PTR); }
421  bool isNum() const { return ((t == TYPE_FLOAT) || (t == TYPE_INT)); }
423  bool isString() const { return (t == TYPE_STRING); }
425  bool isMap() const { return (t == TYPE_MAP); }
427  bool isList() const { return (t == TYPE_LIST); }
428 
430  IntType asInt() const
431  {
432  if (t == TYPE_INT) return i;
433  throw WrongTypeException();
434  }
435  IntType Int() const
436  {
437  return i;
438  }
440  FloatType asFloat() const
441  {
442  if (t == TYPE_FLOAT) return f;
443  throw WrongTypeException();
444  }
445  FloatType Float() const
446  {
447  return f;
448  }
450  PtrType asPtr() const
451  {
452  if (t == TYPE_PTR) return p;
453  throw WrongTypeException();
454  }
455  PtrType Ptr() const
456  {
457  return p;
458  }
460  FloatType asNum() const
461  {
462  if (t == TYPE_FLOAT) return f;
463  if (t == TYPE_INT) return FloatType(i);
464  throw WrongTypeException();
465  }
467  const std::string& asString() const
468  {
469  if (t == TYPE_STRING) return *s;
470  throw WrongTypeException();
471  }
473  std::string& asString()
474  {
475  if (t == TYPE_STRING) return *(s = s->makeUnique());
476  throw WrongTypeException();
477  }
478  const StringType& String() const
479  {
480  return *s;
481  }
482  StringType& String()
483  {
484  return *(s = s->makeUnique());
485  }
486 
493  StringType&& moveString() {
494  if (t != TYPE_STRING) throw WrongTypeException();
495  s = s->makeUnique();
496  return s->move();
497  }
498 
500  const MapType& asMap() const
501  {
502  if (t == TYPE_MAP) return *m;
503  throw WrongTypeException();
504  }
506  MapType& asMap()
507  {
508  if (t == TYPE_MAP) return *(m = m->makeUnique());
509  throw WrongTypeException();
510  }
511  const MapType& Map() const
512  {
513  return *m;
514  }
515  MapType& Map()
516  {
517  return *(m = m->makeUnique());
518  }
519 
526  MapType&& moveMap() {
527  if (t != TYPE_MAP) throw WrongTypeException();
528  m = m->makeUnique();
529  return m->move();
530  }
531 
533  const ListType& asList() const
534  {
535  if (t == TYPE_LIST) return *l;
536  throw WrongTypeException();
537  }
539  ListType& asList()
540  {
541  if (t == TYPE_LIST) return *(l = l->makeUnique());
542  throw WrongTypeException();
543  }
544  const ListType& List() const
545  {
546  return *l;
547  }
548  ListType& List()
549  {
550  return *(l = l->makeUnique());
551  }
552 
559  ListType&& moveList() {
560  if (t != TYPE_LIST) throw WrongTypeException();
561  l = l->makeUnique();
562  return l->move();
563  }
564 
565  static const char * typeName(Type);
566 
567 protected:
568 
569  template<class C>
570  class DataType
571  {
572  public:
573  DataType() : _refcount(1), _data(nullptr) {}
574 
575  explicit DataType(const C& c) : _refcount(1), _data(c) {}
576  explicit DataType(C&& c) : _refcount(1), _data(std::move(c)) {}
577  DataType(const DataType&) = delete;
578 
579  DataType& operator=(const C& c) {_data = c; return *this;}
580  DataType& operator=(const C&& c) {_data = std::move(c); return *this;}
581  DataType& operator=(const DataType&) = delete;
582 
583  bool operator==(const C& c) const {return _data == c;}
584 
585  void ref() {++_refcount;}
586  void unref() {if(--_refcount == 0) delete this;}
587 
588  bool unique() const {return _refcount == 1;}
589  DataType* makeUnique()
590  {
591  if(unique())
592  return this;
593  unref(); // _refcount > 1, so this is fine
594  return new DataType(_data);
595  }
596 
597  operator C&() {return _data;}
604  C&& move() {
605  return std::move(_data);
606  }
607 // operator const C&() const {return _data;}
608 
609  private:
610 
611  unsigned long _refcount;
612  C _data;
613  };
614 
615  Type t;
616  union {
617  IntType i;
618  FloatType f;
619  void* p;
623  };
624 };
625 
626 } } // namespace Atlas::Message
627 
628 
629 #endif // ATLAS_MESSAGE_ELEMENT_H
An exception class issued when the wrong type is requested in as().
Definition: Element.h:20
PtrType asPtr() const
Retrieve the current value as a pointer.
Definition: Element.h:450
FloatType asNum() const
Retrieve the current value as a number.
Definition: Element.h:460
Element(const MapType &v)
Set type to MapType, and value to v.
Definition: Element.h:142
bool operator==(long long v) const
Check for equality with a int.
Definition: Element.h:361
ListType && moveList()
Definition: Element.h:559
bool isString() const
Check whether the current type is std::string.
Definition: Element.h:423
Element(const StringType &v)
Set type to std::string, and value to v.
Definition: Element.h:129
Element(const char *v)
Set type to std::string, and value to v.
Definition: Element.h:118
bool operator==(PtrType v) const
Check for equality with a pointer.
Definition: Element.h:373
const std::string & asString() const
Retrieve the current value as a const std::string reference.
Definition: Element.h:467
Element(MapType &&v)
Set type to MapType, and move v.
Definition: Element.h:148
Element(float v)
Set type to double, and value to v.
Definition: Element.h:100
StringType && moveString()
Definition: Element.h:493
Element()
Construct an empty object.
Definition: Element.h:58
bool isPtr() const
Check whether the current type is pointer.
Definition: Element.h:419
MapType & asMap()
Retrieve the current value as a non-const MapType reference.
Definition: Element.h:506
bool isNum() const
Check whether the current type is numeric.
Definition: Element.h:421
bool operator==(const char *v) const
Check for equality with a const char *.
Definition: Element.h:379
Element(bool v)
Set type to int, and value to v.
Definition: Element.h:88
IntType asInt() const
Retrieve the current value as a int.
Definition: Element.h:430
std::string & asString()
Retrieve the current value as a non-const std::string reference.
Definition: Element.h:473
Element(FloatType v)
Set type to double, and value to v.
Definition: Element.h:106
Element(ListType &&v)
Set type to ListType, and move v.
Definition: Element.h:161
Element(StringType &&v)
Set type to std::string, and move v.
Definition: Element.h:135
Element(int v)
Set type to int, and value to v.
Definition: Element.h:77
FloatType asFloat() const
Retrieve the current value as a double.
Definition: Element.h:440
Type getType() const
Get the current type.
Definition: Element.h:411
bool operator!=(C c) const
Check for inequality with anything we can check equality with.
Definition: Element.h:343
bool isNone() const
Check whether the current type is nothing.
Definition: Element.h:413
Element(long long v)
Set type to int, and value to v.
Definition: Element.h:94
MapType && moveMap()
Definition: Element.h:526
bool operator==(const MapType &v) const
Check for equality with a MapType.
Definition: Element.h:395
const ListType & asList() const
Retrieve the current value as a const ListType reference.
Definition: Element.h:533
bool isFloat() const
Check whether the current type is double.
Definition: Element.h:417
bool operator==(const StringType &v) const
Check for equality with a std::string.
Definition: Element.h:387
bool isInt() const
Check whether the current type is int.
Definition: Element.h:415
bool operator==(long v) const
Check for equality with a int.
Definition: Element.h:355
Element(const ListType &v)
Set type to ListType, and value to v.
Definition: Element.h:155
bool operator==(FloatType v) const
Check for equality with a double.
Definition: Element.h:367
bool operator==(int v) const
Check for equality with a int.
Definition: Element.h:349
bool isMap() const
Check whether the current type is MapType.
Definition: Element.h:425
bool operator==(const ListType &v) const
Check for equality with a ListType.
Definition: Element.h:403
Element(PtrType v)
Set type to PtrType, and value to v.
Definition: Element.h:112
Definition: Bridge.h:20
const MapType & asMap() const
Retrieve the current value as a const MapType reference.
Definition: Element.h:500
ListType & asList()
Retrieve the current value as a non-const ListType reference.
Definition: Element.h:539
bool isList() const
Check whether the current type is ListType.
Definition: Element.h:427