libutil++  1.9.3
 All Classes Functions Variables
Variant.cpp
1 /*
2 ** libutil++
3 ** $Id: Variant.cpp 1892 2017-06-23 17:23:36Z sella $
4 ** Copyright (c) 2011-2016 Digital Genesis, LLC. All Rights Reserved.
5 ** Released under the LGPL Version 2.1 License.
6 ** http://www.digitalgenesis.com
7 */
8 
9 static const char rcsid[] __attribute__((used)) = "$Id: Variant.cpp 1892 2017-06-23 17:23:36Z sella $";
10 
11 #include "Variant.h"
12 
13 #include "../util/String.h"
14 #include "../util/MessagePack.h"
15 #include "../util/CommonMacro.h"
16 
17 using namespace sella::variant;
18 
19 const int Variant::TypeAuto;
20 const int Variant::TypeNull;
21 const int Variant::TypeBoolean;
22 const int Variant::TypeSigned;
23 const int Variant::TypeUnsigned;
24 const int Variant::TypeDouble;
25 const int Variant::TypeString;
26 const int Variant::TypeUUID;
27 const int Variant::TypeBinary;
28 const int Variant::TypePointer;
29 const int Variant::TypeIPAddress;
30 const int Variant::TypeIPPrefix;
31 const int Variant::TypeInterval;
32 const int Variant::TypeTime;
33 const int Variant::TypeDate;
34 const int Variant::TypeTimeStamp ;
35 const int Variant::TypeVector;
36 const int Variant::TypeObject;
37 const int Variant::TypeJSON;
38 const int Variant::TypeQuoted;
39 const int Variant::TypeNonQuoted;
40 const int Variant::JSON;
41 const int Variant::CJSON;
42 const int Variant::MSGPACK;
43 const int Variant::XML;
44 const int Variant::CSV;
45 const int Variant::IterScalar;
46 const int Variant::IterVector;
47 const int Variant::IterObject;
48 
49 Variant::Variant() throw () :
50  value(null()),
51  type(TypeNull)
52 { }
53 
54 Variant::Variant(const std::shared_ptr<Nullable> &value) throw (TypeCastException) :
55  value(value),
56  type(this->value->getType())
57 { }
58 
59 Variant::Variant(std::shared_ptr<Nullable> &&value) throw (TypeCastException) :
60  value(std::move(value)),
61  type(this->value->getType())
62 { }
63 
64 Variant::Variant(const std::string &value, int type) throw (TypeCastException) {
65  if (type == TypeString) {
66  this->value = std::make_shared<String>(value);
67  this->type = TypeString;
68  } else {
69  parse(value, type);
70  }
71 }
72 
73 Variant::Variant(std::string &&value, int type) throw (TypeCastException) {
74  if (type == TypeString) {
75  this->value = std::make_shared<String>(std::move(value));
76  this->type = TypeString;
77  } else {
78  parse(value, type);
79  }
80 }
81 
82 Variant::Variant(const char *value, int type) throw (TypeCastException) {
83  if (type == TypeString) {
84  this->value = std::make_shared<String>(value);
85  this->type = TypeString;
86  } else {
87  parse(value, type);
88  }
89 }
90 
91 Variant::Variant(uint32_t size, uint8_t *buffer) throw (TypeCastException) {
92  this->unmsgpack(buffer, size);
93 }
94 
95 Variant::Variant(const sella::util::UUID &value) throw () :
96  value(std::make_shared<UUID>(value)),
97  type(TypeUUID)
98 { }
99 
100 Variant::Variant(sella::util::UUID &&value) throw () :
101  value(std::make_shared<UUID>(std::move(value))),
102  type(TypeUUID)
103 {
104  value.clear();
105 }
106 
107 Variant::Variant(uuid_t &value) throw () :
108  value(std::make_shared<UUID>(value)),
109  type(TypeUUID)
110 { }
111 
112 Variant::Variant(void *ptr) throw () :
113  value(std::make_shared<Pointer>(ptr)),
114  type(TypePointer)
115 { }
116 
117 Variant::Variant(const sella::net::IPAddress &value) throw () :
118  value(std::make_shared<IPAddress>(value)),
119  type(TypeIPAddress)
120 { }
121 
122 Variant::Variant(sella::net::IPAddress &&value) throw () :
123  value(std::make_shared<IPAddress>(std::move(value))),
124  type(TypeIPAddress)
125 {
126  value.clear();
127 }
128 
129 Variant::Variant(const sella::net::IPPrefix &value) throw () :
130  value(std::make_shared<IPPrefix>(value)),
131  type(TypeIPPrefix)
132 { }
133 
134 Variant::Variant(sella::net::IPPrefix &&value) throw () :
135  value(std::make_shared<IPPrefix>(std::move(value))),
136  type(TypeIPPrefix)
137 {
138  value.clear();
139 }
140 
141 Variant::Variant(bool value) throw () :
142  value(std::make_shared<Boolean>(value)),
143  type(TypeBoolean)
144 { }
145 
146 Variant::Variant(uint8_t value) throw () :
147  value(std::make_shared<Unsigned>(value)),
148  type(TypeUnsigned)
149 { }
150 
151 Variant::Variant(uint16_t value) throw () :
152  value(std::make_shared<Unsigned>(value)),
153  type(TypeUnsigned)
154 { }
155 
156 Variant::Variant(unsigned int value) throw () :
157  value(std::make_shared<Unsigned>(value)),
158  type(TypeUnsigned)
159 { }
160 
161 Variant::Variant(uint64_t value) throw () :
162  value(std::make_shared<Unsigned>(value)),
163  type(TypeUnsigned)
164 { }
165 
166 Variant::Variant(int8_t value) throw () :
167  value(std::make_shared<Signed>(value)),
168  type(TypeSigned)
169 { }
170 
171 Variant::Variant(int16_t value) throw () :
172  value(std::make_shared<Signed>(value)),
173  type(TypeSigned)
174 { }
175 
176 Variant::Variant(int value) throw () :
177  value(std::make_shared<Signed>(value)),
178  type(TypeSigned)
179 { }
180 
181 Variant::Variant(int64_t value) throw () :
182  value(std::make_shared<Signed>(value)),
183  type(TypeSigned)
184 { }
185 
186 Variant::Variant(float value) throw () :
187  value(std::make_shared<Double>(value)),
188  type(TypeDouble)
189 { }
190 
191 Variant::Variant(double value) throw () :
192  value(std::make_shared<Double>(value)),
193  type(TypeDouble)
194 { }
195 
196 Variant::Variant(const std::vector<std::string> &token) throw (TypeCastException) {
197  if (token.empty()) {
198  THROW(TypeCastException, "empty token stream passed to variant");
199  }
200 
201  switch (token.front().at(0)) {
202  case '[':
203  this->value = std::make_shared<Vector>(std::vector<std::string>(token.begin() + 1, token.end()));
204  this->type = TypeVector;
205 
206  break;
207 
208  case '{':
209  this->value = std::make_shared<Object>(std::vector<std::string>(token.begin() + 1, token.end()));
210  this->type = TypeObject;
211 
212  break;
213 
214  default:
215  THROW(TypeCastException, "unknown token stream passed to variant (first token: %s)", token.front().c_str());
216  }
217 }
218 
219 #ifdef __LP64__
220 Variant::Variant(unsigned long long value) throw () :
221  value(std::make_shared<Unsigned>(value)),
222  type(TypeUnsigned)
223 { }
224 
225 Variant::Variant(long long value) throw () :
226  value(std::make_shared<Unsigned>(value)),
227  type(TypeSigned)
228 { }
229 #else
230 Variant::Variant(unsigned long value) throw () :
231  value(std::make_shared<Unsigned>(value)),
232  type(TypeUnsigned)
233 { }
234 
235 Variant::Variant(long value) throw () :
236  value(std::make_shared<Unsigned>(value)),
237  type(TypeSigned)
238 { }
239 #endif
240 
241 Variant::Variant(const Variant &other) throw () :
242  value(),
243  type(other.type)
244 {
245  switch (other.type) {
246  case TypeNull:
247  this->value = null();
248 
249  break;
250 
251  case TypeBoolean:
252  this->value = std::make_shared<Boolean>(other.get<Boolean>());
253 
254  break;
255 
256  case TypeSigned:
257  this->value = std::make_shared<Signed>(other.get<Signed>());
258 
259  break;
260 
261  case TypeUnsigned:
262  this->value = std::make_shared<Unsigned>(other.get<Unsigned>());
263 
264  break;
265 
266  case TypeDouble:
267  this->value = std::make_shared<Double>(other.get<Double>());
268 
269  break;
270 
271  case TypeString:
272  this->value = std::make_shared<String>(other.get<String>());
273 
274  break;
275 
276  case TypeUUID:
277  this->value = std::make_shared<UUID>(other.get<UUID>());
278 
279  break;
280 
281  case TypeBinary:
282  this->value = std::make_shared<Binary>(other.get<Binary>());
283 
284  break;
285 
286  case TypePointer:
287  this->value = std::make_shared<Pointer>(other.get<Pointer>());
288 
289  break;
290 
291  case TypeIPAddress:
292  this->value = std::make_shared<IPAddress>(other.get<IPAddress>());
293 
294  break;
295 
296  case TypeIPPrefix:
297  this->value = std::make_shared<IPPrefix>(other.get<IPPrefix>());
298 
299  break;
300 
301  case TypeInterval:
302  this->value = std::make_shared<Interval>(other.get<Interval>());
303 
304  break;
305 
306  case TypeTime:
307  this->value = std::make_shared<Time>(other.get<Time>());
308 
309  break;
310 
311  case TypeDate:
312  this->value = std::make_shared<Date>(other.get<Date>());
313 
314  break;
315 
316  case TypeTimeStamp:
317  this->value = std::make_shared<TimeStamp>(other.get<TimeStamp>());
318 
319  break;
320 
321  case TypeVector:
322  this->value = std::make_shared<Vector>(other.get<Vector>());
323 
324  break;
325 
326  case TypeObject:
327  this->value = std::make_shared<Object>(other.get<Object>());
328 
329  break;
330 
331  default:
332  fprintf(stderr, "DEBUG: Missing Type in switch statements.\n");
333  abort();
334  }
335 }
336 
337 Variant::Variant(Variant &&other) throw () {
338  this->swap(other);
339 }
340 
341 Variant::~Variant() throw () { }
342 
343 Variant::iterator Variant::begin() throw () {
344  iterator_t it;
345  it.v = NULL;
346 
347  if (this->type == TypeObject) {
348  it.type = IterObject;
349  it.oit = get<Object>().begin();
350  } else if (this->type == TypeVector) {
351  it.type = IterVector;
352  it.vit = get<Vector>().begin();
353  } else {
354  it.type = IterScalar;
355  it.v = this;
356  }
357 
358  return it;
359 }
360 
361 Variant::iterator Variant::end() throw () {
362  iterator_t it;
363  it.v = NULL;
364 
365  if (this->type == TypeObject) {
366  it.type = IterObject;
367  it.oit = get<Object>().end();
368  } else if (this->type == TypeVector) {
369  it.type = IterVector;
370  it.vit = get<Vector>().end();
371  } else {
372  it.type = IterScalar;
373  it.v = NULL;
374  }
375 
376  return it;
377 }
378 
379 int Variant::getType() const throw () {
380  return this->type;
381 }
382 
383 void Variant::setType(int type) throw (TypeCastException) {
384  if (this->type != type) {
385  switch (type) {
386  case TypeAuto:
387  case TypeNull:
388  this->value = null();
389  break;
390 
391  case TypeBoolean:
392  this->value = (isNull()) ? std::make_shared<Boolean>() : std::make_shared<Boolean>((bool) *this);
393  break;
394 
395  case TypeSigned:
396  this->value = (isNull()) ? std::make_shared<Signed>() : std::make_shared<Signed>((int64_t) *this);
397  break;
398 
399  case TypeUnsigned:
400  this->value = (isNull()) ? std::make_shared<Unsigned>() : std::make_shared<Unsigned>((uint64_t) *this);
401  break;
402 
403  case TypeDouble:
404  this->value = (isNull()) ? std::make_shared<Double>() : std::make_shared<Double>((double) *this);
405  break;
406 
407  case TypeUUID:
408  if (isString()) {
409  this->value = (isNull()) ? std::make_shared<UUID>() : std::make_shared<UUID>(str());
410  } else {
411  this->value = std::make_shared<UUID>(""); /* Force a new UUID (not null) */
412  }
413  break;
414 
415  case TypeString:
416  this->value = (isNull()) ? std::make_shared<String>() : std::make_shared<String>(str());
417  break;
418 
419  case TypeBinary:
420  this->value = (isNull()) ? std::make_shared<Binary>() : std::make_shared<Binary>(str());
421  break;
422 
423  case TypePointer:
424  this->value = (isNull()) ? std::make_shared<Pointer>() : std::make_shared<Pointer>(str());
425  break;
426 
427  case TypeIPAddress:
428  this->value = (isNull()) ? std::make_shared<IPAddress>() : std::make_shared<IPAddress>(str());
429  break;
430 
431  case TypeIPPrefix:
432  this->value = (isNull()) ? std::make_shared<IPPrefix>() : std::make_shared<IPPrefix>(str());
433  break;
434 
435  case TypeInterval:
436  this->value = (isNull()) ? std::make_shared<Interval>() : std::make_shared<Interval>(str());
437  break;
438 
439  case TypeTime:
440  this->value = (isNull()) ? std::make_shared<Time>() : std::make_shared<Time>(str());
441  break;
442 
443  case TypeDate:
444  this->value = (isNull()) ? std::make_shared<Date>() : std::make_shared<Date>(str());
445  break;
446 
447  case TypeTimeStamp:
448  this->value = (isNull()) ? std::make_shared<TimeStamp>() : std::make_shared<TimeStamp>(str());
449  break;
450 
451  case TypeVector:
452  this->value = std::make_shared<Vector>(""); /* Force an empty vector (not null) */
453 
454  break;
455 
456  case TypeObject:
457  this->value = std::make_shared<Object>(""); /* Force an empty object (not null) */
458  break;
459 
460  default:
461  THROW(TypeCastException, "unable to change type to %s(%d)", getTypeName(type), type);
462  }
463 
464  this->type = type;
465  }
466 }
467 
468 const char* Variant::getTypeName(int type) const throw () {
469  if (type < 0) {
470  type = this->type;
471  }
472 
473  switch (type) {
474  case TypeAuto:
475  return "auto";
476 
477  case TypeNull:
478  return "null";
479 
480  case TypeBoolean:
481  return "boolean";
482 
483  case TypeSigned:
484  return "signed";
485 
486  case TypeUnsigned:
487  return "unsigned";
488 
489  case TypeDouble:
490  return "double";
491 
492  case TypeString:
493  return "string";
494 
495  case TypeUUID:
496  return "uuid";
497 
498  case TypeBinary:
499  return "binary";
500 
501  case TypePointer:
502  return "pointer";
503 
504  case TypeIPAddress:
505  return "ipaddress";
506 
507  case TypeIPPrefix:
508  return "ipprefix";
509 
510  case TypeInterval:
511  return "interval";
512 
513  case TypeTime:
514  return "time";
515 
516  case TypeDate:
517  return "date";
518 
519  case TypeTimeStamp:
520  return "timestamp";
521 
522  case TypeVector:
523  return "vector";
524 
525  case TypeObject:
526  return "object";
527 
528  default:
529  fprintf(stderr, "DEBUG: Missing Type %d in switch statements.\n", type);
530  abort();
531  }
532 }
533 
534 Variant& Variant::parse(const std::string &value, int type) throw (TypeCastException) {
535  if (type == TypeAuto || type == TypeJSON || type == TypeQuoted || type == TypeNonQuoted) { /* Provide whitespace trimming for auto types. */
536  if (value.empty()) {
537  type = TypeString;
538  } else if (::isspace(value.front()) != 0 || ::isspace(value.back()) != 0) {
539  std::string trimmed = sella::util::String::trim(value);
540 
541  if (!trimmed.empty()) {
542  return parse(trimmed, type);
543  } else {
544  type = TypeString;
545  }
546  } else {
547  switch (type) {
548  case TypeAuto: /* Prioritized by most likely to match. */
549  if (Signed::isType(value)) {
550  type = TypeSigned;
551  #if 0 /* Will neve match, due to Signed. */
552  } else if (Unsigned::isType(value)) {
553  type = TypeUnsigned;
554  #endif
555  } else if (Boolean::isType(value)) {
556  type = TypeBoolean;
557  } else if (Double::isType(value)) {
558  type = TypeDouble;
559  } else if (Null::isType(value)) {
560  type = TypeNull;
561  } else if (UUID::isType(value)) {
562  type = TypeUUID;
563  } else if (IPPrefix::isType(value)) {
564  type = TypeIPPrefix;
565  } else if (IPAddress::isType(value)) {
566  type = TypeIPAddress;
567  } else if (Vector::isType(value)) {
568  type = TypeVector;
569  } else if (Object::isType(value)) {
570  type = TypeObject;
571  } else if (Binary::isType(value)) {
572  type = TypeBinary;
573  #if 0 /* Will never match, due to binary. */
574  } else if (Pointer::isType(value)) {
575  type = TypePointer;
576  #endif
577  } else if (Interval::isType(value)) {
578  type = TypeInterval;
579  } else if (Time::isType(value)) {
580  type = TypeTime;
581  } else if (Date::isType(value)) {
582  type = TypeDate;
583  } else if (TimeStamp::isType(value)) {
584  type = TypeTimeStamp;
585  } else {
586  type = TypeString;
587  }
588  break;
589 
590  case TypeJSON:
591  if (Object::isType(value)) {
592  type = TypeObject;
593  } else if (Vector::isType(value)) {
594  type = TypeVector;
595  } else {
596  type = TypeString;
597  }
598  break;
599 
600  case TypeQuoted: /* Prioritized by most likely to match. */
601  if (UUID::isType(value)) {
602  type = TypeUUID;
603  } else if (IPPrefix::isType(value)) {
604  type = TypeIPPrefix;
605  } else if (IPAddress::isType(value)) {
606  type = TypeIPAddress;
607  } else {
608  type = TypeString;
609  }
610  break;
611 
612  case TypeNonQuoted: /* Prioritized by most likely to match. */
613  if (Signed::isType(value)) {
614  type = TypeSigned;
615  } else if (Boolean::isType(value)) {
616  type = TypeBoolean;
617  } else if (Double::isType(value)) {
618  type = TypeDouble;
619  } else if (Null::isType(value)) {
620  type = TypeNull;
621  } else {
622  type = TypeString;
623  }
624  break;
625  }
626  }
627  }
628 
629  switch (type) {
630  case TypeNull:
631  this->value = null();
632  this->type = TypeNull;
633  break;
634 
635  case TypeBoolean:
636  this->value = std::make_shared<Boolean>(value);
637  this->type = TypeBoolean;
638  break;
639 
640  case TypeSigned:
641  try {
642  this->value = std::make_shared<Signed>(value);
643  this->type = TypeSigned;
644 
645  break;
646  } catch (TypeCastException &e) { } /* Fall thru is intentional */
647 
648  case TypeUnsigned:
649  this->value = std::make_shared<Unsigned>(value);
650  this->type = TypeUnsigned;
651  break;
652 
653  case TypeDouble:
654  this->value = std::make_shared<Double>(value);
655  this->type = TypeDouble;
656  break;
657 
658  case TypeUUID:
659  this->value = std::make_shared<UUID>(value);
660  this->type = TypeUUID;
661 
662  break;
663 
664  case TypeString:
665  this->value = std::make_shared<String>(value);
666  this->type = TypeString;
667  break;
668 
669  case TypeBinary:
670  this->value = std::make_shared<Binary>(value);
671  this->type = TypeBinary;
672  break;
673 
674  case TypePointer:
675  this->value = std::make_shared<Pointer>(value);
676  this->type = TypePointer;
677  break;
678 
679  case TypeIPAddress:
680  this->value = std::make_shared<IPAddress>(value);
681  this->type = TypeIPAddress;
682  break;
683 
684  case TypeIPPrefix:
685  this->value = std::make_shared<IPPrefix>(value);
686  this->type = TypeIPPrefix;
687  break;
688 
689  case TypeInterval:
690  this->value = std::make_shared<Interval>(value);
691  this->type = TypeInterval;
692  break;
693 
694  case TypeTime:
695  this->value = std::make_shared<Time>(value);
696  this->type = TypeTime;
697  break;
698 
699  case TypeDate:
700  this->value = std::make_shared<Date>(value);
701  this->type = TypeDate;
702  break;
703 
704  case TypeTimeStamp:
705  this->value = std::make_shared<TimeStamp>(value);
706  this->type = TypeTimeStamp;
707  break;
708 
709  case TypeVector:
710  this->value = std::make_shared<Vector>(value);
711  this->type = TypeVector;
712  break;
713 
714  case TypeObject:
715  this->value = std::make_shared<Object>(value);
716  this->type = TypeObject;
717  break;
718 
719  case TypeMsgPack:
720  this->unmsgpack(value);
721  break;
722 
723  default:
724  THROW(TypeCastException, "unknown scalar type %d supplied", type);
725  }
726 
727  return *this;
728 }
729 
730 bool Variant::erase(const Variant &value) throw () {
731  if (this->type == TypeObject && !isNull()) {
732  return get<Object>().erase(value.str());
733  } else if (this->type == TypeVector && !isNull()) {
734  return get<Vector>().erase(value);
735  }
736 
737  return false;
738 }
739 
740 bool Variant::erase(const std::string &value) throw () {
741  if (this->type == TypeObject && !isNull()) {
742  return get<Object>().erase(value);
743  } else if (this->type == TypeVector && !isNull()) {
744  return get<Vector>().erase(Variant(value));
745  }
746 
747  return false;
748 }
749 
750 bool Variant::erase(unsigned int index) throw () {
751  if (this->type == TypeVector && !isNull()) {
752  return get<Vector>().erase(index);
753  }
754 
755  return false;
756 }
757 
758 void Variant::shrink_to_fit() throw () {
759  switch (this->type) {
760  case TypeUUID:
761  return get<UUID>().shrink_to_fit();
762 
763  case TypeString:
764  return get<String>().shrink_to_fit();
765 
766  case TypeVector:
767  return get<Vector>().shrink_to_fit();
768 
769  default:
770  return get<Nullable>().shrink_to_fit();
771  }
772 }
773 
774 void Variant::sort(void) throw (UnsupportedOperatorException) {
775  if (this->type != TypeVector) {
776  THROW(TypeCastException, "operation only supported with type vector");
777  }
778 
779  std::vector<Variant> &v = get<Vector>().get();
780 
781  std::sort(v.begin(), v.end());
782 }
783 
784 void Variant::unique(void) throw (UnsupportedOperatorException) {
785  if (this->type != TypeVector) {
786  THROW(TypeCastException, "operation only supported with type vector");
787  }
788 
789  std::vector<Variant> &v = get<Vector>().get();
790 
791  v.erase(std::unique(v.begin(), v.end()), v.end());
792 }
793 
794 void Variant::zero() throw () {
795  switch (this->type) {
796  case TypeBoolean:
797  get<Boolean>() = false;
798  break;
799 
800  case TypeSigned:
801  get<Signed>() = 0;
802  break;
803 
804  case TypeUnsigned:
805  get<Unsigned>() = 0;
806  break;
807 
808  case TypeDouble:
809  get<Double>() = 0.0;
810  break;
811 
812  case TypeUUID:
813  get<UUID>().clear();
814  break;
815 
816  case TypeString:
817  get<String>().clear();
818  break;
819 
820  case TypeBinary:
821  get<Binary>().clear();
822  break;
823 
824  case TypePointer:
825  get<Pointer>() = 0x0;
826  break;
827 
828  case TypeIPAddress:
829  get<IPAddress>().clear();
830  break;
831 
832  case TypeIPPrefix:
833  get<IPPrefix>().clear();
834  break;
835 
836  case TypeInterval:
837  get<Interval>() = 0;
838  break;
839 
840  case TypeTime:
841  get<Time>() = 0;
842  break;
843 
844  case TypeDate:
845  get<Date>() = 0;
846  break;
847 
848  case TypeTimeStamp:
849  get<TimeStamp>() = 0;
850  break;
851 
852  case TypeVector:
853  get<Vector>().clear();
854  break;
855 
856  case TypeObject:
857  get<Object>().clear();
858  break;
859  }
860 }
861 
862 void Variant::clear() throw () {
863  value = null();
864  type = TypeNull;
865  cache.clear();
866 }
867 
868 size_t Variant::size() const throw () {
869  switch (this->type) {
870  case TypeObject:
871  return get<Object>().size();
872  case TypeVector:
873  return get<Vector>().size();
874  case TypeString:
875  return get<String>().size();
876  case TypeBinary:
877  return get<Binary>().size();
878  }
879 
880  return 0;
881 }
882 
883 bool Variant::empty() const throw () {
884  switch (this->type) {
885  case TypeObject:
886  return get<Object>().empty();
887  case TypeVector:
888  return get<Vector>().empty();
889  case TypeString:
890  return get<String>().empty();
891  case TypeBinary:
892  return get<Binary>().empty();
893  case TypeNull:
894  return true;
895  }
896 
897  return false;
898 }
899 
900 bool Variant::isScalar() const throw () {
901  return !(isVector() || isObject());
902 }
903 
904 bool Variant::isNumeric() const throw () {
905  return (isSigned() || isUnsigned() || isDouble());
906 }
907 
908 bool Variant::isTemporal() const throw () {
909  return (isInterval() || isTime() || isDate() || isTimeStamp());
910 }
911 
912 bool Variant::isNetwork() const throw () {
913  return (isIPAddress() || isIPPrefix());
914 }
915 
916 bool Variant::isNull() const throw () {
917  return (this->value == NULL || this->value->isNull());
918 }
919 
920 bool Variant::isBoolean() const throw () {
921  return (this->type == TypeBoolean);
922 }
923 
924 bool Variant::isSigned() const throw () {
925  return (this->type == TypeSigned);
926 }
927 
928 bool Variant::isUnsigned() const throw () {
929  return (this->type == TypeUnsigned);
930 }
931 
932 bool Variant::isDouble() const throw () {
933  return (this->type == TypeDouble);
934 }
935 
936 bool Variant::isString() const throw () {
937  return (this->type == TypeString);
938 }
939 
940 bool Variant::isUUID() const throw () {
941  return (this->type == TypeUUID);
942 }
943 
944 bool Variant::isBinary() const throw () {
945  return (this->type == TypeBinary);
946 }
947 
948 bool Variant::isPointer() const throw () {
949  return (this->type == TypePointer);
950 }
951 
952 bool Variant::isIPAddress() const throw () {
953  return (this->type == TypeIPAddress);
954 }
955 
956 bool Variant::isIPPrefix() const throw () {
957  return (this->type == TypeIPPrefix);
958 }
959 
960 bool Variant::isInterval() const throw () {
961  return (this->type == TypeInterval);
962 }
963 
964 bool Variant::isTime() const throw () {
965  return (this->type == TypeTime);
966 }
967 
968 bool Variant::isDate() const throw () {
969  return (this->type == TypeDate);
970 }
971 
972 bool Variant::isTimeStamp() const throw () {
973  return (this->type == TypeTimeStamp);
974 }
975 
976 bool Variant::isVector() const throw () {
977  return (this->type == TypeVector);
978 }
979 
980 bool Variant::isObject() const throw () {
981  return (this->type == TypeObject);
982 }
983 
984 const std::vector<Variant>& Variant::asVector(void) const throw (TypeCastException) {
985  return this->cast<const std::vector<Variant>&>();
986 }
987 
988 std::vector<Variant>& Variant::asVector(void) throw (TypeCastException) {
989  return this->cast<std::vector<Variant>&>();
990 }
991 
992 const std::map<std::string, Variant>& Variant::asMap(void) const throw (TypeCastException) {
993  return this->cast<const std::map<std::string, Variant>&>();
994 }
995 
996 std::map<std::string, Variant>& Variant::asMap(void) throw (TypeCastException) {
997  return this->cast<std::map<std::string, Variant>&>();
998 }
999 
1000 Variant& Variant::unjson(const std::string &json) throw (TypeCastException) { /* Bypasses most of the regex calls that parse uses. */
1001  return parse(json, TypeJSON);
1002 }
1003 
1004 const std::string& Variant::str(int type) const throw () {
1005  std::string buf;
1006 
1007  switch (type) {
1008  case JSON:
1009  if (this->type == TypeString) { /* Optimization */
1010  return this->get<sella::variant::String>().get();
1011  }
1012 
1013  buf = this->value->str(JSON);
1014  break;
1015 
1016  case CJSON:
1017  buf = this->value->str(CJSON);
1018  break;
1019 
1020  case MSGPACK: {
1021  msgpack(buf);
1022  break;
1023  }
1024 
1025  case XML:
1026  buf.append("<root>").append(this->value->str(XML)).append("</root>");
1027  break;
1028 
1029  case CSV:
1030  buf = this->value->str(CSV);
1031  break;
1032  }
1033 
1034  cache.swap(buf);
1035 
1036  return cache;
1037 }
1038 
1039 const char* Variant::c_str(int type) const throw () {
1040  return str(type).c_str();
1041 }
1042 
1043 size_t Variant::msgpack(std::string &buffer, uint32_t size) const throw (TypeCastException) {
1044  size_t c;
1045 
1046  if (size == 0) {
1047  uint8_t buf[(512 * 1024)]; /* 512KB */
1048 
1049  if ((c = msgpack(buf, (uint32_t) sizeof(buf))) > 0) {
1050  buffer.assign((const char*) buf, c);
1051  }
1052  } else {
1053  uint8_t *buf = (uint8_t*) malloc(size);
1054 
1055  try {
1056  if ((c = msgpack(buf, size)) > 0) {
1057  buffer.assign((const char*) buf, c);
1058  }
1059  } catch (sella::Exception &e) {
1060  free(buf);
1061 
1062  RETHROW(TypeCastException, e);
1063  }
1064 
1065  free(buf);
1066  }
1067 
1068  return c;
1069 }
1070 
1071 size_t Variant::msgpack(uint8_t *buffer, uint32_t size) const throw (TypeCastException) {
1072 #if 1 /* Faster */
1073  uint32_t offset = 0;
1074 
1075  sella::util::MessagePack mpack(buffer, size, 0, size);
1076 
1077  this->value->msgpack(mpack, offset);
1078 
1079  return offset;
1080 #else /* Slower */
1081  uint32_t offset = 0, c = 0;
1082 
1083  sella::util::MessagePack mpack(buffer, size, 0, size);
1084 
1085  if (UNLIKELY(this->isNull())) {
1086  return mpack.append(offset);
1087  }
1088 
1089  switch (this->type) {
1090  case TypeBoolean:
1091  c = mpack.append(offset, get<Boolean>().get());
1092  break;
1093 
1094  case TypeSigned:
1095  c = mpack.append(offset, get<Signed>().get());
1096  break;
1097 
1098  case TypeUnsigned:
1099  c = mpack.append(offset, get<Unsigned>().get());
1100  break;
1101 
1102  case TypeDouble:
1103  c = mpack.append(offset, get<Double>().get());
1104  break;
1105 
1106  case TypeUUID:
1107  c = mpack.append(offset, get<UUID>().get().str());
1108  break;
1109 
1110  case TypeString:
1111  c = mpack.append(offset, get<String>().get());
1112  break;
1113 
1114  case TypeBinary:
1115  c = get<Binary>().msgpack(mpack, offset);
1116  break;
1117 
1118  case TypePointer:
1119  c = mpack.append(offset, (uint64_t) get<Pointer>().get());
1120  break;
1121 
1122  case TypeIPAddress:
1123  c = mpack.append(offset, get<IPAddress>().get().str());
1124  break;
1125 
1126  case TypeIPPrefix:
1127  c = mpack.append(offset, get<IPPrefix>().get().str());
1128  break;
1129 
1130  case TypeInterval:
1131  c = mpack.append(offset, get<Interval>().str(JSON));
1132  break;
1133 
1134  case TypeTime:
1135  c = mpack.append(offset, get<Time>().str(JSON));
1136  break;
1137 
1138  case TypeDate:
1139  c = mpack.append(offset, get<Date>().str(JSON));
1140  break;
1141 
1142  case TypeTimeStamp:
1143  c = mpack.append(offset, get<TimeStamp>().str(JSON));
1144  break;
1145 
1146  case TypeVector:
1147  c = get<Vector>().msgpack(mpack, offset);
1148  break;
1149 
1150  case TypeObject:
1151  c = get<Object>().msgpack(mpack, offset);
1152  break;
1153  }
1154 
1155  if (this->type != TypeObject && this->type != TypeVector && this->type != TypeBinary) {
1156  offset += c;
1157  }
1158 
1159  if (UNLIKELY(c == 0)) {
1160  THROW(TypeCastException, "Failed to append '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
1161  }
1162 
1163  return offset;
1164 #endif
1165 }
1166 
1167 Variant& Variant::unmsgpack(const std::string &msgpack) throw (TypeCastException) {
1168  return unmsgpack((uint8_t*) msgpack.data(), msgpack.size());
1169 }
1170 
1171 Variant& Variant::unmsgpack(uint8_t *buffer, uint32_t size) throw (TypeCastException) {
1172  uint32_t offset = 0;
1173 
1174  if (UNLIKELY(size < 1)) { /* Gracefully handle empty buffer */
1175  clear();
1176 
1177  return *this;
1178  }
1179 
1180  union {
1181  bool b;
1182  int64_t s;
1183  uint64_t u;
1184  double d;
1185  } u;
1186 
1187  try {
1188  sella::util::MessagePack mpack(buffer, size);
1189 
1190  switch (mpack.typeof(offset)) {
1191  case sella::util::MessagePack::TYPE_NULL:
1192  this->value = null();
1193  this->type = TypeNull;
1194  break;
1195 
1196  case sella::util::MessagePack::TYPE_BOOLEAN:
1197  if (mpack.decode(u.b, offset)) {
1198  this->value = std::make_shared<Boolean>(u.b);
1199  this->type = TypeBoolean;
1200  } else {
1201  THROW(TypeCastException, "Failed to decode boolean");
1202  }
1203  break;
1204 
1205  case sella::util::MessagePack::TYPE_SIGNED:
1206  if (mpack.decode(u.s, offset)) {
1207  this->value = std::make_shared<Signed>(u.s);
1208  this->type = TypeSigned;
1209  } else {
1210  THROW(TypeCastException, "Failed to decode signed");
1211  }
1212  break;
1213 
1214  case sella::util::MessagePack::TYPE_UNSIGNED:
1215  if (mpack.decode(u.u, offset)) {
1216  this->value = std::make_shared<Unsigned>(u.u);
1217  this->type = TypeUnsigned;
1218  } else {
1219  THROW(TypeCastException, "Failed to decode unsigned");
1220  }
1221  break;
1222 
1223  case sella::util::MessagePack::TYPE_FLOAT:
1224  if (mpack.decode(u.d, offset)) {
1225  this->value = std::make_shared<Double>(u.d);
1226  this->type = TypeDouble;
1227  } else {
1228  THROW(TypeCastException, "Failed to decode double");
1229  }
1230  break;
1231 
1232  case sella::util::MessagePack::TYPE_STRING: {
1233  std::string str;
1234 
1235  if (mpack.decode(str, offset)) {
1236  this->value = std::make_shared<String>(std::move(str));
1237  this->type = TypeString;
1238  } else {
1239  THROW(TypeCastException, "Failed to decode string");
1240  }
1241  break;
1242  }
1243 
1244  case sella::util::MessagePack::TYPE_VECTOR:
1245  this->value = std::make_shared<Vector>(mpack, offset);
1246  this->type = TypeVector;
1247  break;
1248 
1249  case sella::util::MessagePack::TYPE_OBJECT:
1250  this->value = std::make_shared<Object>(mpack, offset);
1251  this->type = TypeObject;
1252  break;
1253 
1254  default:
1255  THROW(TypeCastException, "Unsupported type %u in input", mpack.typeof(offset));
1256  }
1257  } catch (sella::util::MemoryException &e) {
1258  RETHROW(TypeCastException, e);
1259  }
1260 
1261  return *this;
1262 }
1263 
1264 size_t Variant::msgpackBufferSize(void) const throw () {
1265  size_t size = 0;
1266 
1267  if (this->value) {
1268  this->value->msgpackBufferSize(size);
1269  } else {
1270  size = 1;
1271  }
1272 
1273  return size;
1274 }
1275 
1276 void Variant::swap(Variant& other) {
1277  int type = other.type;
1278  other.type = this->type;
1279  this->type = type;
1280 
1281  this->value.swap(other.value);
1282  this->cache.swap(other.cache);
1283 }
1284 
1285 /*
1286 ** vim: noet ts=3 sw=3
1287 */