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 
87  Element(long long v)
88  : t(TYPE_INT), i(v)
89  {
90  }
91 
93  Element(bool v)
94  : t(TYPE_INT), i(v)
95  {
96  }
97 
99  Element(FloatType v)
100  : t(TYPE_FLOAT), f(v)
101  {
102  }
103 
105  Element(PtrType v)
106  : t(TYPE_PTR), p(v)
107  {
108  }
109 
111  Element(const char* v)
112  : t(TYPE_STRING)
113  {
114  if(v) {
115  s = new DataType<StringType>(v);
116  }
117  else
118  s = new DataType<StringType>();
119  }
120 
122  Element(const StringType& v)
123  : t(TYPE_STRING)
124  {
125  s = new DataType<StringType>(v);
126  }
128  Element(StringType&& v)
129  : t(TYPE_STRING)
130  {
131  s = new DataType<StringType>(std::move(v));
132  }
133 
135  Element(const MapType& v)
136  : t(TYPE_MAP)
137  {
138  m = new DataType<MapType>(v);
139  }
141  Element(MapType&& v)
142  : t(TYPE_MAP)
143  {
144  m = new DataType<MapType>(std::move(v));
145  }
146 
148  Element(const ListType& v)
149  : t(TYPE_LIST)
150  {
151  l = new DataType<ListType>(v);
152  }
154  Element(ListType&& v)
155  : t(TYPE_LIST)
156  {
157  l = new DataType<ListType>(std::move(v));
158  }
159 
161  Element& operator=(const Element& obj);
162 
168  Element& operator=(Element&& obj) noexcept;
169 
170  Element& operator=(int v)
171  {
172  if (TYPE_INT != t)
173  {
174  clear(TYPE_INT);
175  }
176  i = v;
177  return *this;
178  }
179 
180  Element& operator=(long v)
181  {
182  if (TYPE_INT != t)
183  {
184  clear(TYPE_INT);
185  }
186  i = v;
187  return *this;
188  }
189 
190  Element& operator=(long long v)
191  {
192  if (TYPE_INT != t)
193  {
194  clear(TYPE_INT);
195  }
196  i = v;
197  return *this;
198  }
199 
200  Element& operator=(bool v)
201  {
202  if (TYPE_INT != t)
203  {
204  clear(TYPE_INT);
205  }
206  i = v;
207  return *this;
208  }
209 
210  Element& operator=(FloatType v)
211  {
212  if (TYPE_FLOAT != t)
213  {
214  clear(TYPE_FLOAT);
215  }
216  f = v;
217  return *this;
218  }
219 
220  Element& operator=(PtrType v)
221  {
222  if (TYPE_PTR != t)
223  {
224  clear(TYPE_PTR);
225  }
226  p = v;
227  return *this;
228  }
229 
230  Element& operator=(const char * v)
231  {
232  if (TYPE_STRING != t || !s->unique())
233  {
234  clear(TYPE_STRING);
235  s = new DataType<StringType>(std::string(v));
236  } else {
237  *s = StringType(v);
238  }
239  return *this;
240  }
241 
242  Element& operator=(const StringType & v)
243  {
244  if (TYPE_STRING != t || !s->unique())
245  {
246  clear(TYPE_STRING);
247  s = new DataType<StringType>(v);
248  } else {
249  *s = v;
250  }
251  return *this;
252  }
253 
254  Element& operator=(StringType && v)
255  {
256  if (TYPE_STRING != t || !s->unique())
257  {
258  clear(TYPE_STRING);
259  s = new DataType<StringType>(v);
260  } else {
261  *s = v;
262  }
263  return *this;
264  }
265 
266  Element& operator=(const MapType & v)
267  {
268  if (TYPE_MAP != t || !m->unique())
269  {
270  clear(TYPE_MAP);
271  m = new DataType<MapType>(v);
272  } else {
273  *m = v;
274  }
275  return *this;
276  }
277 
278  Element& operator=(MapType && v)
279  {
280  if (TYPE_MAP != t || !m->unique())
281  {
282  clear(TYPE_MAP);
283  m = new DataType<MapType>(std::move(v));
284  } else {
285  *m = v;
286  }
287  return *this;
288  }
289 
290  Element& operator=(const ListType & v)
291  {
292  if (TYPE_LIST != t || !l->unique())
293  {
294  clear(TYPE_LIST);
295  l = new DataType<ListType>(v);
296  } else {
297  *l = v;
298  }
299  return *this;
300  }
301 
302  Element& operator=(ListType && v)
303  {
304  if (TYPE_LIST != t || !l->unique())
305  {
306  clear(TYPE_LIST);
307  l = new DataType<ListType>(std::move(v));
308  } else {
309  *l = v;
310  }
311  return *this;
312  }
313 
315  bool operator==(const Element& o) const;
316 
318  template<class C>
319  bool operator!=(C c) const
320  {
321  return !(*this == c);
322  }
323 
325  bool operator==(int v) const
326  {
327  return (t == TYPE_INT && i == v);
328  }
329 
331  bool operator==(long v) const
332  {
333  return (t == TYPE_INT && i == v);
334  }
335 
336  bool operator==(long long v) const
337  {
338  return (t == TYPE_INT && i == v);
339  }
341  bool operator==(FloatType v) const
342  {
343  return t == TYPE_FLOAT && Equal(f, v);
344  }
345 
347  bool operator==(PtrType v) const
348  {
349  return t == TYPE_PTR && p == v;
350  }
351 
353  bool operator==(const char * v) const
354  {
355  if(t == TYPE_STRING)
356  return (*s == v);
357  return false;
358  }
359 
361  bool operator==(const StringType& v) const
362  {
363  if(t == TYPE_STRING)
364  return (*s == v);
365  return false;
366  }
367 
369  bool operator==(const MapType& v) const
370  {
371  if(t == TYPE_MAP)
372  return (*m == v);
373  return false;
374  }
375 
377  bool operator==(const ListType& v) const
378  {
379  if (t == TYPE_LIST)
380  return (*l == v);
381  return false;
382  }
383 
385  Type getType() const { return t; }
387  bool isNone() const { return (t == TYPE_NONE); }
389  bool isInt() const { return (t == TYPE_INT); }
391  bool isFloat() const { return (t == TYPE_FLOAT); }
393  bool isPtr() const { return (t == TYPE_PTR); }
395  bool isNum() const { return ((t == TYPE_FLOAT) || (t == TYPE_INT)); }
397  bool isString() const { return (t == TYPE_STRING); }
399  bool isMap() const { return (t == TYPE_MAP); }
401  bool isList() const { return (t == TYPE_LIST); }
402 
404  IntType asInt() const
405  {
406  if (t == TYPE_INT) return i;
407  throw WrongTypeException();
408  }
409  IntType Int() const
410  {
411  return i;
412  }
414  FloatType asFloat() const
415  {
416  if (t == TYPE_FLOAT) return f;
417  throw WrongTypeException();
418  }
419  FloatType Float() const
420  {
421  return f;
422  }
424  PtrType asPtr() const
425  {
426  if (t == TYPE_PTR) return p;
427  throw WrongTypeException();
428  }
429  PtrType Ptr() const
430  {
431  return p;
432  }
434  FloatType asNum() const
435  {
436  if (t == TYPE_FLOAT) return f;
437  if (t == TYPE_INT) return FloatType(i);
438  throw WrongTypeException();
439  }
441  const std::string& asString() const
442  {
443  if (t == TYPE_STRING) return *s;
444  throw WrongTypeException();
445  }
447  std::string& asString()
448  {
449  if (t == TYPE_STRING) return *(s = s->makeUnique());
450  throw WrongTypeException();
451  }
452  const StringType& String() const
453  {
454  return *s;
455  }
456  StringType& String()
457  {
458  return *(s = s->makeUnique());
459  }
460 
467  StringType&& moveString() {
468  if (t != TYPE_STRING) throw WrongTypeException();
469  s = s->makeUnique();
470  return s->move();
471  }
472 
474  const MapType& asMap() const
475  {
476  if (t == TYPE_MAP) return *m;
477  throw WrongTypeException();
478  }
480  MapType& asMap()
481  {
482  if (t == TYPE_MAP) return *(m = m->makeUnique());
483  throw WrongTypeException();
484  }
485  const MapType& Map() const
486  {
487  return *m;
488  }
489  MapType& Map()
490  {
491  return *(m = m->makeUnique());
492  }
493 
500  MapType&& moveMap() {
501  if (t != TYPE_MAP) throw WrongTypeException();
502  m = m->makeUnique();
503  return m->move();
504  }
505 
507  const ListType& asList() const
508  {
509  if (t == TYPE_LIST) return *l;
510  throw WrongTypeException();
511  }
513  ListType& asList()
514  {
515  if (t == TYPE_LIST) return *(l = l->makeUnique());
516  throw WrongTypeException();
517  }
518  const ListType& List() const
519  {
520  return *l;
521  }
522  ListType& List()
523  {
524  return *(l = l->makeUnique());
525  }
526 
533  ListType&& moveList() {
534  if (t != TYPE_LIST) throw WrongTypeException();
535  l = l->makeUnique();
536  return l->move();
537  }
538 
539  static const char * typeName(Type);
540 
541 protected:
542 
543  template<class C>
544  class DataType
545  {
546  public:
547  DataType() : _refcount(1), _data(nullptr) {}
548 
549  explicit DataType(const C& c) : _refcount(1), _data(c) {}
550  explicit DataType(C&& c) : _refcount(1), _data(std::move(c)) {}
551  DataType(const DataType&) = delete;
552 
553  DataType& operator=(const C& c) {_data = c; return *this;}
554  DataType& operator=(const C&& c) {_data = std::move(c); return *this;}
555  DataType& operator=(const DataType&) = delete;
556 
557  bool operator==(const C& c) const {return _data == c;}
558 
559  void ref() {++_refcount;}
560  void unref() {if(--_refcount == 0) delete this;}
561 
562  bool unique() const {return _refcount == 1;}
563  DataType* makeUnique()
564  {
565  if(unique())
566  return this;
567  unref(); // _refcount > 1, so this is fine
568  return new DataType(_data);
569  }
570 
571  operator C&() {return _data;}
578  C&& move() {
579  return std::move(_data);
580  }
581 // operator const C&() const {return _data;}
582 
583  private:
584 
585  unsigned long _refcount;
586  C _data;
587  };
588 
589  Type t;
590  union {
591  IntType i;
592  FloatType f;
593  void* p;
594  DataType<StringType>* s;
595  DataType<MapType>* m;
596  DataType<ListType>* l;
597  };
598 };
599 
600 } } // namespace Atlas::Message
601 
602 
603 #endif // ATLAS_MESSAGE_ELEMENT_H
bool operator==(FloatType v) const
Check for equality with a double.
Definition: Element.h:341
ListType & asList()
Retrieve the current value as a non-const ListType reference.
Definition: Element.h:513
Element(const StringType &v)
Set type to std::string, and value to v.
Definition: Element.h:122
bool operator==(const StringType &v) const
Check for equality with a std::string.
Definition: Element.h:361
Element(FloatType v)
Set type to double, and value to v.
Definition: Element.h:99
bool isString() const
Check whether the current type is std::string.
Definition: Element.h:397
const std::string & asString() const
Retrieve the current value as a const std::string reference.
Definition: Element.h:441
Element(bool v)
Set type to int, and value to v.
Definition: Element.h:93
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:395
Element(ListType &&v)
Set type to ListType, and move v.
Definition: Element.h:154
PtrType asPtr() const
Retrieve the current value as a pointer.
Definition: Element.h:424
FloatType asFloat() const
Retrieve the current value as a double.
Definition: Element.h:414
FloatType asNum() const
Retrieve the current value as a number.
Definition: Element.h:434
Element(const char *v)
Set type to std::string, and value to v.
Definition: Element.h:111
bool isFloat() const
Check whether the current type is double.
Definition: Element.h:391
Element(int v)
Set type to int, and value to v.
Definition: Element.h:77
bool isPtr() const
Check whether the current type is pointer.
Definition: Element.h:393
const MapType & asMap() const
Retrieve the current value as a const MapType reference.
Definition: Element.h:474
bool operator==(int v) const
Check for equality with a int.
Definition: Element.h:325
Element(StringType &&v)
Set type to std::string, and move v.
Definition: Element.h:128
Type getType() const
Get the current type.
Definition: Element.h:385
MapType && moveMap()
Definition: Element.h:500
Element(PtrType v)
Set type to PtrType, and value to v.
Definition: Element.h:105
MapType & asMap()
Retrieve the current value as a non-const MapType reference.
Definition: Element.h:480
bool operator==(const MapType &v) const
Check for equality with a MapType.
Definition: Element.h:369
std::string & asString()
Retrieve the current value as a non-const std::string reference.
Definition: Element.h:447
bool operator==(const ListType &v) const
Check for equality with a ListType.
Definition: Element.h:377
StringType && moveString()
Definition: Element.h:467
bool operator==(PtrType v) const
Check for equality with a pointer.
Definition: Element.h:347
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:507
Element()
Construct an empty object.
Definition: Element.h:58
bool isMap() const
Check whether the current type is MapType.
Definition: Element.h:399
bool operator!=(C c) const
Check for inequality with anything we can check equality with.
Definition: Element.h:319
Element(const ListType &v)
Set type to ListType, and value to v.
Definition: Element.h:148
bool isList() const
Check whether the current type is ListType.
Definition: Element.h:401
bool operator==(const char *v) const
Check for equality with a const char *.
Definition: Element.h:353
Element(MapType &&v)
Set type to MapType, and move v.
Definition: Element.h:141
IntType asInt() const
Retrieve the current value as a int.
Definition: Element.h:404
Element(const MapType &v)
Set type to MapType, and value to v.
Definition: Element.h:135
ListType && moveList()
Definition: Element.h:533
bool operator==(long v) const
Check for equality with a int.
Definition: Element.h:331
bool isNone() const
Check whether the current type is nothing.
Definition: Element.h:387
bool isInt() const
Check whether the current type is int.
Definition: Element.h:389
An exception class issued when the wrong type is requested in as().
Definition: Element.h:21
Definition: Bridge.h:20