Evo C++ Library v0.5.1
var.h
Go to the documentation of this file.
1 // Evo C++ Library
2 /* Copyright 2019 Justin Crowell
3 Distributed under the BSD 2-Clause License -- see included file LICENSE.txt for details.
4 */
6 
7 #pragma once
8 #ifndef INCL_evo_var_h
9 #define INCL_evo_var_h
10 
11 #include "string.h"
12 #include "substring.h"
13 #include "list.h"
14 #include "maplist.h"
15 
16 #if defined(EVO_CPP11)
17  #include <initializer_list>
18 #endif
19 
20 namespace evo {
23 
25 
157 class Var {
158 public:
159  typedef SizeT Size;
161  typedef List<Var> ListType;
162 
164  enum Type {
173  };
174 
175 #if defined(EVO_CPP11)
176 
179  Var(std::initializer_list<Var> init) : type_(tNULL) {
180  assert( init.size() < IntegerT<ListType::Size>::MAX );
181  ListType& items = list();
182  items.reserve((typename ListType::Size)init.size());
183  for (const auto& val : init)
184  items.add(val);
185  }
186 
190  Var(Var&& src) {
191  type_ = src.type_;
192  switch (type_) {
193  case tOBJECT:
194  memcpy(buf_obj_, src.buf_obj_, sizeof(ObjectType));
195  break;
196  case tLIST:
197  memcpy(buf_list_, src.buf_list_, sizeof(ListType));
198  break;
199  case tSTRING:
200  memcpy(buf_str_, src.buf_str_, sizeof(String));
201  break;
202  case tFLOAT:
203  buf_float_ = src.buf_float_;
204  break;
205  case tUNSIGNED:
206  buf_uint_ = src.buf_uint_;
207  break;
208  case tINTEGER:
209  buf_int_ = src.buf_int_;
210  break;
211  case tBOOL:
212  buf_bool_ = src.buf_bool_;
213  break;
214  case tNULL:
215  break;
216  }
217  src.type_ = tNULL;
218  }
219 
224  Var& operator=(Var&& src) {
225  free();
226  type_ = src.type_;
227  switch (type_) {
228  case tOBJECT:
229  memcpy(buf_obj_, src.buf_obj_, sizeof(ObjectType));
230  break;
231  case tLIST:
232  memcpy(buf_list_, src.buf_list_, sizeof(ListType));
233  break;
234  case tSTRING:
235  memcpy(buf_str_, src.buf_str_, sizeof(String));
236  break;
237  case tFLOAT:
238  buf_float_ = src.buf_float_;
239  break;
240  case tUNSIGNED:
241  buf_uint_ = src.buf_uint_;
242  break;
243  case tINTEGER:
244  buf_int_ = src.buf_int_;
245  break;
246  case tBOOL:
247  buf_bool_ = src.buf_bool_;
248  break;
249  case tNULL:
250  break;
251  }
252  src.type_ = tNULL;
253  return *this;
254  }
255 #endif
256 
258  Var() : type_(tNULL) {
259  }
260 
264  Var(const Var& src) {
265  type_ = src.type_;
266  switch (type_) {
267  case tOBJECT: {
268  const ObjectType* src_ptr = (const ObjectType*)src.buf_obj_;
269  new((ObjectType*)buf_obj_) ObjectType(*src_ptr);
270  break;
271  }
272  case tLIST: {
273  const ListType* src_ptr = (const ListType*)src.buf_list_;
274  new((ListType*)buf_list_) ListType(*src_ptr);
275  break;
276  }
277  case tSTRING: {
278  const String* src_ptr = (const String*)src.buf_str_;
279  new((String*)buf_str_) String(*src_ptr);
280  break;
281  }
282  case tFLOAT:
283  buf_float_ = src.buf_float_;
284  break;
285  case tUNSIGNED:
286  buf_uint_ = src.buf_uint_;
287  break;
288  case tINTEGER:
289  buf_int_ = src.buf_int_;
290  break;
291  case tBOOL:
292  buf_bool_ = src.buf_bool_;
293  break;
294  case tNULL:
295  break;
296  }
297  }
298 
304  Var(const ObjectType& val) : type_(tNULL) {
305  object() = val;
306  }
307 
313  Var(const ListType& val) : type_(tNULL) {
314  list() = val;
315  }
316 
322  Var(const String& val) : type_(tNULL) {
323  string() = val;
324  }
325 
331  Var(const StringBase& val) : type_(tNULL) {
332  string() = val;
333  }
334 
340  Var(const char* val) : type_(tNULL) {
341  String& str = string();
342  if (val != NULL)
343  str = val;
344  }
345 
349  Var(double val) : type_(tNULL) {
350  numf() = val;
351  }
352 
356  Var(ushort val) : type_(tNULL) {
357  numu() = val;
358  }
359 
363  Var(uint val) : type_(tNULL) {
364  numu() = val;
365  }
366 
370  Var(ulong val) : type_(tNULL) {
371  numu() = val;
372  }
373 
377  Var(ulongl val) : type_(tNULL) {
378  numu() = val;
379  }
380 
384  Var(short val) : type_(tNULL) {
385  numi() = val;
386  }
387 
391  Var(int val) : type_(tNULL) {
392  numi() = val;
393  }
394 
398  Var(long val) : type_(tNULL) {
399  numi() = val;
400  }
401 
405  Var(longl val) : type_(tNULL) {
406  numi() = val;
407  }
408 
412  Var(bool val) : type_(tNULL) {
413  boolref() = val;
414  }
415 
417  Var(ValNull) : type_(tNULL) {
418  }
419 
421  ~Var() {
422  free();
423  }
424 
428  Type type() const {
429  return type_;
430  }
431 
437  bool is_container() const {
438  switch (type_) {
439  case tOBJECT:
440  case tLIST:
441  return true;
442  default:
443  break;
444  }
445  return false;
446  }
447 
453  bool is_object() const {
454  return (type_ == tOBJECT);
455  }
456 
462  bool is_list() const {
463  return (type_ == tLIST);
464  }
465 
471  bool is_string() const {
472  return (type_ == tSTRING);
473  }
474 
478  bool is_number() const {
479  switch (type_) {
480  case tFLOAT:
481  case tUNSIGNED:
482  case tINTEGER:
483  return true;
484  default:
485  break;
486  }
487  return false;
488  }
489 
493  bool is_float() const {
494  return (type_ == tFLOAT);
495  }
496 
500  bool is_integer() const {
501  switch (type_) {
502  case tUNSIGNED:
503  case tINTEGER:
504  return true;
505  default:
506  break;
507  }
508  return false;
509  }
510 
514  bool is_unsigned() const {
515  return (type_ == tUNSIGNED);
516  }
517 
521  bool is_signed() const {
522  return (type_ == tINTEGER);
523  }
524 
528  bool is_bool() const {
529  return (type_ == tBOOL);
530  }
531 
538  bool shared() const {
539  switch (type_) {
540  case tOBJECT: {
541  const ObjectType* p = (const ObjectType*)buf_obj_;
542  return p->shared();
543  }
544  case tLIST: {
545  const ListType* p = (const ListType*)buf_list_;
546  return p->shared();
547  }
548  case tSTRING: {
549  const String* p = (const String*)buf_str_;
550  return p->shared();
551  }
552  default:
553  break;
554  }
555  return false;
556  }
557 
565  bool shared_scan() const {
566  switch (type_) {
567  case tOBJECT: {
568  const ObjectType* p = (const ObjectType*)buf_obj_;
569  const ObjectType& obj = *p;
570  if (obj.shared())
571  return true;
572  for (ObjectType::Iter iter(obj); iter; ++iter)
573  if (iter->key().shared() || iter->value().shared_scan())
574  return true;
575  break;
576  }
577  case tLIST: {
578  const ListType* p = (const ListType*)buf_list_;
579  const ListType& list = *p;
580  if (list.shared())
581  return true;
582  for (ListType::Iter iter(list); iter; ++iter)
583  if (iter->shared_scan())
584  return true;
585  break;
586  }
587  case tSTRING: {
588  const String* p = (const String*)buf_str_;
589  return p->shared();
590  }
591  default:
592  break;
593  }
594  return false;
595  }
596 
600  bool null() const {
601  switch (type_) {
602  case tOBJECT: {
603  const ObjectType* p = (const ObjectType*)buf_obj_;
604  return p->null();
605  }
606  case tLIST: {
607  const ListType* p = (const ListType*)buf_list_;
608  return p->null();
609  }
610  case tSTRING: {
611  const String* p = (const String*)buf_str_;
612  return p->null();
613  }
614  case tNULL:
615  return true;
616  default:
617  break;
618  }
619  return false;
620  }
621 
627  bool empty() const {
628  switch (type_) {
629  case tOBJECT: {
630  const ObjectType* p = (const ObjectType*)buf_obj_;
631  return p->empty();
632  }
633  case tLIST: {
634  const ListType* p = (const ListType*)buf_list_;
635  return p->empty();
636  }
637  default:
638  break;
639  }
640  return true;
641  }
642 
646  Size size() const {
647  switch (type_) {
648  case tOBJECT: {
649  const ObjectType* p = (const ObjectType*)buf_obj_;
650  return p->size();
651  }
652  case tLIST: {
653  const ListType* p = (const ListType*)buf_list_;
654  return p->size();
655  }
656  default:
657  break;
658  }
659  return 0;
660  }
661 
665  Var& set() {
666  free();
667  type_ = tNULL;
668  return *this;
669  }
670 
676  Var& clear() {
677  switch (type_) {
678  case tOBJECT: {
679  ObjectType* p = (ObjectType*)buf_obj_;
680  p->clear();
681  break;
682  }
683  case tLIST: {
684  ListType* p = (ListType*)buf_list_;
685  p->clear();
686  break;
687  }
688  case tSTRING: {
689  String* p = (String*)buf_str_;
690  p->clear();
691  break;
692  }
693  case tFLOAT:
694  buf_float_ = 0.0;
695  break;
696  case tUNSIGNED:
697  buf_uint_ = 0;
698  break;
699  case tINTEGER:
700  buf_int_ = 0;
701  break;
702  case tBOOL:
703  buf_bool_ = false;
704  break;
705  default:
706  break;
707  }
708  return *this;
709  }
710 
718  switch (type_) {
719  case tOBJECT: {
720  ObjectType* p = (ObjectType*)buf_obj_;
721  p->unshare();
722  break;
723  }
724  case tLIST: {
725  ListType* p = (ListType*)buf_list_;
726  p->unshare();
727  break;
728  }
729  case tSTRING: {
730  String* p = (String*)buf_str_;
731  p->unshare();
732  break;
733  }
734  default:
735  break;
736  }
737  return *this;
738  }
739 
748  switch (type_) {
749  case tOBJECT: {
750  ObjectType* p = (ObjectType*)buf_obj_;
751  ObjectType& obj = *p;
752  obj.unshare();
753  for (ObjectType::IterM iter(obj); iter; ++iter) {
754  ((String&)iter->key()).unshare(); // key is const to prevent reordering, need to override const to unshare()
755  iter->value().unshare_all();
756  }
757  break;
758  }
759  case tLIST: {
760  ListType* p = (ListType*)buf_list_;
761  ListType& list = *p;
762  list.unshare();
763  for (ListType::IterM iter(list); iter; ++iter)
764  iter->unshare_all();
765  break;
766  }
767  case tSTRING: {
768  String* p = (String*)buf_str_;
769  p->unshare();
770  break;
771  }
772  default:
773  break;
774  }
775  return *this;
776  }
777 
788  const Var& childref(const StringBase& key) const {
789  if (type_ == tOBJECT) {
790  const ObjectType* p = (ObjectType*)buf_obj_;
791  const Var* v = p->find(key);
792  if (v != NULL)
793  return *v;
794  }
795  return null_var();
796  }
797 
808  const Var& childref(Size index) const {
809  if (type_ == tLIST) {
810  const ListType* l = (ListType*)buf_list_;
811  if (l != NULL && index < l->size())
812  return l->item(index);
813  }
814  return null_var();
815  }
816 
820  const Var* child(const StringBase& key) const {
821  if (type_ == tOBJECT) {
822  const ObjectType* p = (const ObjectType*)buf_obj_;
823  return p->find(key);
824  }
825  return NULL;
826  }
827 
831  const Var* child(Size index) const {
832  if (type_ == tLIST) {
833  const ListType* l = (const ListType*)buf_list_;
834  if (l != NULL && index < l->size())
835  return &l->item(index);
836  }
837  return NULL;
838  }
839 
843  Var* childM(const StringBase& key) {
844  if (type_ == tOBJECT) {
845  ObjectType* p = (ObjectType*)buf_obj_;
846  return p->findM(key);
847  }
848  return NULL;
849  }
850 
854  Var* childM(Size index) {
855  if (type_ == tLIST) {
856  ListType* l = (ListType*)buf_list_;
857  return &l->itemM(index);
858  }
859  return NULL;
860  }
861 
867  ObjectType& object() {
868  ObjectType* ptr = (ObjectType*)buf_obj_;
869  switch (type_) {
870  case tOBJECT:
871  return *ptr;
872  case tLIST: {
873  ListType* p = (ListType*)buf_list_;
874  p->~ListType();
875  break;
876  }
877  case tSTRING: {
878  String* p = (String*)buf_str_;
879  p->~String();
880  break;
881  }
882  default:
883  break;
884  }
885  type_ = tOBJECT;
886  new(ptr) ObjectType();
887  ptr->setempty();
888  return *ptr;
889  }
890 
896  ListType& list() {
897  ListType* ptr = (ListType*)buf_obj_;
898  switch (type_) {
899  case tOBJECT: {
900  ObjectType* p = (ObjectType*)buf_obj_;
901  p->~ObjectType();
902  break;
903  }
904  case tLIST:
905  return *ptr;
906  case tSTRING: {
907  String* p = (String*)buf_str_;
908  p->~String();
909  break;
910  }
911  default:
912  break;
913  }
914  type_ = tLIST;
915  new(ptr) ListType();
916  ptr->setempty();
917  return *ptr;
918  }
919 
926  String* ptr = (String*)buf_str_;
927  switch (type_) {
928  case tOBJECT: {
929  ObjectType* p = (ObjectType*)buf_obj_;
930  p->~ObjectType();
931  break;
932  }
933  case tLIST: {
934  ListType* p = (ListType*)buf_list_;
935  p->~ListType();
936  break;
937  }
938  case tSTRING:
939  return *ptr;
940  default:
941  break;
942  }
943  type_ = tSTRING;
944  new(ptr) String();
945  ptr->setempty();
946  return *ptr;
947  }
948 
956  uint64& numu() {
957  switch (type_) {
958  case tOBJECT: {
959  ObjectType* p = (ObjectType*)buf_obj_;
960  p->~ObjectType();
961  break;
962  }
963  case tLIST: {
964  ListType* p = (ListType*)buf_list_;
965  p->~ListType();
966  break;
967  }
968  case tSTRING: {
969  String* p = (String*)buf_str_;
970  p->~String();
971  break;
972  }
973  case tFLOAT: {
974  const uint64 num = (uint64)buf_float_;
975  type_ = tUNSIGNED;
976  buf_uint_ = num;
977  return buf_uint_;
978  }
979  case tINTEGER:
980  type_ = tUNSIGNED;
981  case tUNSIGNED:
982  return buf_uint_;
983  case tBOOL:
984  case tNULL:
985  break;
986  }
987  type_ = tUNSIGNED;
988  buf_uint_ = 0;
989  return buf_uint_;
990  }
991 
999  int64& numi() {
1000  switch (type_) {
1001  case tOBJECT: {
1002  ObjectType* p = (ObjectType*)buf_obj_;
1003  p->~ObjectType();
1004  break;
1005  }
1006  case tLIST: {
1007  ListType* p = (ListType*)buf_list_;
1008  p->~ListType();
1009  break;
1010  }
1011  case tSTRING: {
1012  String* p = (String*)buf_str_;
1013  p->~String();
1014  break;
1015  }
1016  case tFLOAT: {
1017  const int64 num = (int64)buf_float_;
1018  type_ = tINTEGER;
1019  buf_int_ = num;
1020  return buf_int_;
1021  }
1022  case tUNSIGNED:
1023  type_ = tINTEGER;
1024  case tINTEGER:
1025  return buf_int_;
1026  case tBOOL:
1027  case tNULL:
1028  break;
1029  }
1030  type_ = tINTEGER;
1031  buf_int_ = 0;
1032  return buf_int_;
1033  }
1034 
1041  double& numf() {
1042  switch (type_) {
1043  case tOBJECT: {
1044  ObjectType* p = (ObjectType*)buf_obj_;
1045  p->~ObjectType();
1046  break;
1047  }
1048  case tLIST: {
1049  ListType* p = (ListType*)buf_list_;
1050  p->~ListType();
1051  break;
1052  }
1053  case tSTRING: {
1054  String* p = (String*)buf_str_;
1055  p->~String();
1056  break;
1057  }
1058  case tFLOAT:
1059  return buf_float_;
1060  case tUNSIGNED: {
1061  const double num = (double)buf_uint_;
1062  type_ = tFLOAT;
1063  buf_float_ = num;
1064  return buf_float_;
1065  }
1066  case tINTEGER: {
1067  const double num = (double)buf_int_;
1068  type_ = tFLOAT;
1069  buf_float_ = num;
1070  return buf_float_;
1071  }
1072  case tBOOL:
1073  case tNULL:
1074  break;
1075  }
1076  type_ = tFLOAT;
1077  buf_float_ = 0.0;
1078  return buf_float_;
1079  }
1080 
1086  bool& boolref() {
1087  switch (type_) {
1088  case tOBJECT: {
1089  ObjectType* p = (ObjectType*)buf_obj_;
1090  p->~ObjectType();
1091  break;
1092  }
1093  case tLIST: {
1094  ListType* p = (ListType*)buf_list_;
1095  p->~ListType();
1096  break;
1097  }
1098  case tSTRING: {
1099  String* p = (String*)buf_str_;
1100  p->~String();
1101  break;
1102  }
1103  case tUNSIGNED:
1104  case tINTEGER:
1105  case tFLOAT:
1106  case tNULL:
1107  break;
1108  case tBOOL:
1109  return buf_bool_;
1110  }
1111  type_ = tBOOL;
1112  buf_bool_ = false;
1113  return buf_bool_;
1114  }
1115 
1123  bool get_val(String& val) const {
1124  switch (type_) {
1125  case tOBJECT: {
1126  const ObjectType* p = (const ObjectType*)buf_obj_;
1127  if (p->null()) {
1128  val.set();
1129  return true;
1130  }
1131  break;
1132  }
1133  case tLIST: {
1134  const ListType* p = (const ListType*)buf_list_;
1135  if (p->null()) {
1136  val.set();
1137  return true;
1138  }
1139  break;
1140  }
1141  case tSTRING: {
1142  const String* p = (const String*)buf_str_;
1143  val = *p;
1144  return true;
1145  }
1146  case tFLOAT:
1147  val.setn(buf_float_);
1148  return true;
1149  case tUNSIGNED:
1150  val.setn(buf_uint_);
1151  return true;
1152  case tINTEGER:
1153  val.setn(buf_int_);
1154  return true;
1155  case tBOOL:
1156  if (buf_bool_)
1157  val.set("true", 4);
1158  else
1159  val.set("false", 5);
1160  return true;
1161  case tNULL:
1162  break;
1163  }
1164  return false;
1165  }
1166 
1172  const ObjectType& get_object() const {
1173  if (type_ != tOBJECT) {
1174  static const ObjectType DEF;
1175  return DEF;
1176  }
1177  const ObjectType* p = (const ObjectType*)buf_obj_;
1178  return *p;
1179  }
1180 
1186  const ListType& get_list() const {
1187  if (type_ != tLIST) {
1188  static const ListType DEF;
1189  return DEF;
1190  }
1191  const ListType* p = (const ListType*)buf_list_;
1192  return *p;
1193  }
1194 
1200  const String& get_str() const {
1201  if (type_ != tSTRING) {
1202  static const String DEF;
1203  return DEF;
1204  }
1205  const String* p = (const String*)buf_str_;
1206  return *p;
1207  }
1208 
1215  double get_float() const {
1216  switch (type_) {
1217  case tSTRING: {
1218  const String* p = (const String*)buf_str_;
1219  return p->getnumf<double>();
1220  }
1221  case tFLOAT:
1222  return buf_float_;
1223  case tUNSIGNED:
1224  return (double)buf_uint_;
1225  case tINTEGER:
1226  return (double)buf_int_;
1227  case tBOOL:
1228  return (double)buf_bool_;
1229  default:
1230  break;
1231  }
1232  return 0.0;
1233  }
1234 
1242  uint64 get_uint() const {
1243  switch (type_) {
1244  case tSTRING: {
1245  const String* p = (const String*)buf_str_;
1246  return p->getnum<uint64>();
1247  }
1248  case tFLOAT:
1249  return (uint64)buf_float_;
1250  case tUNSIGNED:
1251  case tINTEGER:
1252  return buf_uint_;
1253  case tBOOL:
1254  return (uint64)buf_bool_;
1255  default:
1256  break;
1257  }
1258  return 0;
1259  }
1260 
1268  int64 get_int() const {
1269  switch (type_) {
1270  case tSTRING: {
1271  const String* p = (const String*)buf_str_;
1272  return p->getnum<int64>();
1273  }
1274  case tFLOAT:
1275  return (int64)buf_float_;
1276  case tUNSIGNED:
1277  case tINTEGER:
1278  return buf_int_;
1279  case tBOOL:
1280  return (int64)buf_bool_;
1281  default:
1282  break;
1283  }
1284  return 0;
1285  }
1286 
1293  bool get_bool() const {
1294  switch (type_) {
1295  case tSTRING: {
1296  const String* p = (const String*)buf_str_;
1297  return p->getbool<bool>();
1298  }
1299  case tFLOAT:
1300  return (buf_float_ != 0.0);
1301  case tUNSIGNED:
1302  case tINTEGER:
1303  return (buf_int_ != 0);
1304  case tBOOL:
1305  return buf_bool_;
1306  default:
1307  break;
1308  }
1309  return false;
1310  }
1311 
1318  Var& operator=(const Var& src) {
1319  free();
1320  type_ = src.type_;
1321  switch (type_) {
1322  case tOBJECT: {
1323  const ObjectType* src_p = (const ObjectType*)src.buf_obj_;
1324  new((ObjectType*)buf_obj_) ObjectType(*src_p);
1325  break;
1326  }
1327  case tLIST: {
1328  const ListType* src_p = (const ListType*)src.buf_list_;
1329  new((ListType*)buf_list_) ListType(*src_p);
1330  break;
1331  }
1332  case tSTRING: {
1333  const String* src_p = (const String*)src.buf_str_;
1334  new((String*)buf_str_) String(*src_p);
1335  break;
1336  }
1337  case tFLOAT:
1338  buf_float_ = src.buf_float_;
1339  break;
1340  case tUNSIGNED:
1341  buf_uint_ = src.buf_uint_;
1342  break;
1343  case tINTEGER:
1344  buf_int_ = src.buf_int_;
1345  break;
1346  case tBOOL:
1347  buf_bool_ = src.buf_bool_;
1348  break;
1349  case tNULL:
1350  break;
1351  }
1352  return *this;
1353  }
1354 
1361  Var& operator=(const ObjectType& val) {
1362  object() = val;
1363  return *this;
1364  }
1365 
1372  Var& operator=(const ListType& val) {
1373  list() = val;
1374  return *this;
1375  }
1376 
1383  Var& operator=(const String& val) {
1384  string() = val;
1385  return *this;
1386  }
1387 
1394  Var& operator=(const StringBase& val) {
1395  string() = val;
1396  return *this;
1397  }
1398 
1405  Var& operator=(const char* val) {
1406  String& str = string();
1407  if (val == NULL)
1408  str.clear();
1409  else
1410  str = val;
1411  return *this;
1412  }
1413 
1418  Var& operator=(double val) {
1419  numf() = val;
1420  return *this;
1421  }
1422 
1427  Var& operator=(ushort val) {
1428  numu() = val;
1429  return *this;
1430  }
1431 
1436  Var& operator=(uint val) {
1437  numu() = val;
1438  return *this;
1439  }
1440 
1445  Var& operator=(ulong val) {
1446  numu() = val;
1447  return *this;
1448  }
1449 
1454  Var& operator=(ulongl val) {
1455  numu() = val;
1456  return *this;
1457  }
1458 
1463  Var& operator=(short val) {
1464  numi() = val;
1465  return *this;
1466  }
1467 
1472  Var& operator=(int val) {
1473  numi() = val;
1474  return *this;
1475  }
1476 
1481  Var& operator=(long val) {
1482  numi() = val;
1483  return *this;
1484  }
1485 
1490  Var& operator=(longl val) {
1491  numi() = val;
1492  return *this;
1493  }
1494 
1499  Var& operator=(bool val) {
1500  boolref() = val;
1501  return *this;
1502  }
1503 
1508  set();
1509  return *this;
1510  }
1511 
1519  Var& operator[](const StringBase& key) {
1520  return object()[key];
1521  }
1522 
1530  Var& operator[](Size index) {
1531  return list().addmin(index + 1).itemM(index);
1532  }
1533 
1544  template<class T>
1545  T& dump(T& out, const NewlineValue& newline=NL, uint indent=0) const {
1546  dump_impl(out, newline, indent);
1547  return out;
1548  }
1549 
1550 private:
1551  Type type_;
1552 
1553  union {
1554  // Map/List size not affected by item/value size, sizeof(Var) not yet known
1556  char buf_list_[sizeof(List<char>)];
1557  char buf_str_[sizeof(String)];
1558  double buf_float_;
1559  uint64 buf_uint_;
1560  int64 buf_int_;
1562  };
1563 
1564  void free() {
1565  switch (type_) {
1566  case tOBJECT: {
1567  ObjectType* p = (ObjectType*)buf_obj_;
1568  p->~ObjectType();
1569  break;
1570  }
1571  case tLIST: {
1572  ListType* p = (ListType*)buf_list_;
1573  p->~ListType();
1574  break;
1575  }
1576  case tSTRING: {
1577  String* p = (String*)buf_str_;
1578  p->~String();
1579  break;
1580  }
1581  default:
1582  break;
1583  }
1584  }
1585 
1586  const Var& null_var() const {
1587  static const Var NULL_VAR;
1588  return NULL_VAR;
1589  }
1590 
1591  template<class T>
1592  void dump_val(T& out, char end_delim) const {
1593  switch (type_) {
1594  case tSTRING: {
1595  const String* p = (const String*)buf_str_;
1596  const String& str = *p;
1597  out.writequoted(str.data(), str.size(), end_delim);
1598  break;
1599  }
1600  case tFLOAT:
1601  out << buf_float_;
1602  break;
1603  case tUNSIGNED:
1604  out << buf_uint_;
1605  break;
1606  case tINTEGER:
1607  out << buf_int_;
1608  break;
1609  case tBOOL:
1610  if (buf_bool_)
1611  out.writetext("true", 4);
1612  else
1613  out.writetext("false", 5);
1614  break;
1615  case tNULL:
1616  out.writetext("null", 4);
1617  break;
1618  default:
1619  break; // COV: never happens
1620  }
1621  }
1622 
1623  template<class T, class TNL>
1624  void dump_impl(T& out, const TNL& newline, uint indent, bool first=true) const {
1625  switch (type_) {
1626  case tOBJECT: {
1627  const ObjectType* p = (const ObjectType*)buf_obj_;
1628  const ObjectType& obj = *p;
1629  if (obj.empty()) {
1630  out << "{}";
1631  } else {
1632  indent += 2;
1633  out << '{' << newline;
1634  char delim = ',';
1635  typename ObjectType::Iter iter(obj);
1636  if (iter) {
1637  for (;;) {
1638  const typename ObjectType::Iter::Item& item = *iter;
1639  if (!++iter)
1640  delim = '}';
1641 
1642  out.writechar(' ', indent);
1643  const String& key = item.key();
1644  out.writequoted(key.data(), key.size(), ':', true);
1645  out << ':';
1646 
1647  const Var& val = item.value();
1648  if (val.is_container())
1649  val.dump_impl(out, newline, indent, false);
1650  else
1651  val.dump_val(out, delim);
1652 
1653  if (delim != ',')
1654  break;
1655  out << ',' << newline;
1656  }
1657  }
1658  out << newline;
1659  indent -= 2;
1660  out.writechar(' ', indent);
1661  out << '}';
1662  }
1663  break;
1664  }
1665  case tLIST: {
1666  const ListType* p = (const ListType*)buf_list_;
1667  const ListType& list = *p;
1668  if (list.empty()) {
1669  out << "[]";
1670  } else {
1671  out << '[';
1672  char delim = ',';
1673  typename ListType::Iter iter(list);
1674  if (iter) {
1675  for (;;) {
1676  const Var& val = *iter;
1677  if (!++iter)
1678  delim = ']';
1679  if (val.is_container())
1680  val.dump_impl(out, newline, indent, false);
1681  else
1682  val.dump_val(out, delim);
1683 
1684  if (delim != ',')
1685  break;
1686  out << ',';
1687  }
1688  }
1689  out << ']';
1690  }
1691  break;
1692  }
1693  default:
1694  dump_val(out, ',');
1695  break;
1696  }
1697  if (first)
1698  out << newline;
1699  }
1700 };
1701 
1703 #if defined(EVO_CPP11)
1704 
1709 class VarObject : public Var {
1710 public:
1712  struct InitPair {
1715 
1716  template<class T>
1717  InitPair(const String& key, const T& value) : key(key), value(value) {
1718  }
1719 
1720  template<class T>
1721  InitPair(const StringBase& key, const T& value) : key(key), value(value) {
1722  }
1723 
1724  template<class T>
1725  InitPair(const char* key, const T& value) : key(key), value(value) {
1726  }
1727  };
1728 
1731  object();
1732  }
1733 
1737  VarObject(std::initializer_list<InitPair> init) {
1738  assert( init.size() < IntegerT<ObjectType::Size>::MAX );
1739  ObjectType& map = object();
1740  map.reserve((typename ObjectType::Size)init.size());
1741  for (const auto& val : init)
1742  map[val.key] = val.value;
1743  }
1744 
1748  VarObject(VarObject&& src) : Var(std::move(src)) {
1749  }
1750 
1756  return Var::operator=(std::move(src));
1757  }
1758 
1759  // Disable copying
1760  VarObject(const VarObject&) = delete;
1761  VarObject& operator=(const VarObject&) = delete;
1762 };
1763 
1768 typedef Var VarList;
1769 #endif
1770 
1772 }
1773 #endif
Var & operator=(ushort val)
Assignment operator to set as unsigned integer value (ushort).
Definition: var.h:1427
Var & operator=(const Var &src)
Assignment copy operator.
Definition: var.h:1318
Size size() const
Get size.
Definition: list.h:759
const Var * child(Size index) const
Find child in list using index (const).
Definition: var.h:831
Var(uint val)
Constructor to initialize as unsigned integer value (uint).
Definition: var.h:363
Var * childM(const StringBase &key)
Find child in object using key (mutable).
Definition: var.h:843
double buf_float_
Definition: var.h:1558
Var & operator[](const StringBase &key)
Object field access operator.
Definition: var.h:1519
Integer value (unsigned)
Definition: var.h:169
bool buf_bool_
Definition: var.h:1561
bool is_signed() const
Get whether a signed integer number type (tINTEGER).
Definition: var.h:521
Var & operator=(Var &&src)
Move assignment operator (C++11).
Definition: var.h:224
Holds a Newline value that can be null, which implicitly converts to NL_SYS (system default newline)...
Definition: sys.h:813
VarObject(std::initializer_list< InitPair > init)
Sequence constructor for object initializer.
Definition: var.h:1737
Evo SubString container.
char buf_list_[sizeof(List< char >)]
Definition: var.h:1556
Evo String container.
bool shared() const
Get whether shared.
Definition: maplist.h:381
Var & operator=(ValNull)
Assignment operator to set as null using vNULL.
Definition: var.h:1507
Null value
Definition: var.h:172
double & numf()
Get floating-point number reference, recreate as floating-point if needed.
Definition: var.h:1041
uint64 get_uint() const
Get unsigned integer number value (const).
Definition: var.h:1242
Var(const String &val)
Constructor to copy from a string value.
Definition: var.h:322
~Var()
Destructor.
Definition: var.h:421
T first(T val1, T val2)
Definition: alg.h:85
Random access iterator.
Definition: iter.h:904
Size writequoted(const char *buf, Size size, char delim, bool optional=false)
Write (append) quoted output to string.
Definition: string.h:4305
Var(const ObjectType &val)
Constructor to copy from an object map type.
Definition: var.h:304
ValNull
Unique null value type and value (vNULL).
Definition: sys.h:1096
Var & unshare()
Unshare current value.
Definition: var.h:717
ObjectType & object()
Get object reference, recreate as object if needed.
Definition: var.h:867
const Var & childref(const StringBase &key) const
Get child in object using key, default to null instance (const).
Definition: var.h:788
Var & operator=(short val)
Assignment operator to set as signed integer value (short).
Definition: var.h:1463
const Var * child(const StringBase &key) const
Find child in object using key (const).
Definition: var.h:820
VarObject()
Default constructor creates an empty object.
Definition: var.h:1730
ThisType & unshare()
Make data unique by allocating new buffer, if needed (modifier).
Definition: maplist.h:513
const ListType & get_list() const
Get read-only list reference (const).
Definition: var.h:1186
Var & operator=(longl val)
Assignment operator to set as signed integer value (longl).
Definition: var.h:1490
Explicit variant of Var used for initializing as an object with an initializer list of key/value pair...
Definition: var.h:1709
Var(bool val)
Constructor to initialize as boolean value (bool).
Definition: var.h:412
bool is_container() const
Get whether a container type (object or list).
Definition: var.h:437
String & clear()
Clear by removing all items.
Definition: string.h:4975
Var(long val)
Constructor to initialize as integer value (long).
Definition: var.h:398
String key
Field key string.
Definition: var.h:1713
Evo MapList container.
bool empty() const
Get whether empty.
Definition: var.h:627
bool get_bool() const
Get boolean value (const).
Definition: var.h:1293
bool getbool(Error &error) const
Convert to bool value for given boolean type.
Definition: string.h:4006
Basic integer type.
Definition: type.h:980
Var & operator=(VarObject &&src)
Move assignment operator.
Definition: var.h:1755
const Item & item(Key index) const
Get item at position (const).
Definition: list.h:804
bool is_number() const
Get whether a number type (tFLOAT, tUNSIGNED, tINTEGER).
Definition: var.h:478
MapList< String, Var > ObjectType
Object map type.
Definition: var.h:160
Var & operator=(ulongl val)
Assignment operator to set as unsigned integer value (ulongl).
Definition: var.h:1454
Var & operator=(bool val)
Assignment operator to set as boolean value (bool).
Definition: var.h:1499
TSize Size
List size integer type
Definition: list.h:247
Var & operator=(const ObjectType &val)
Assignment operator to copy from object map type.
Definition: var.h:1361
bool is_integer() const
Get whether an integer number type (tUNSIGNED or tINTEGER).
Definition: var.h:500
Var & operator=(double val)
Assignment operator to set as floating-point value.
Definition: var.h:1418
Var & clear()
Clear current value.
Definition: var.h:676
bool is_list() const
Get whether a list type (tLIST).
Definition: var.h:462
bool get_val(String &val) const
Get value as a string (const).
Definition: var.h:1123
int64 & numi()
Get signed integer number reference, recreate as signed integer if not an integer.
Definition: var.h:999
Var(longl val)
Constructor to initialize as integer value (longl).
Definition: var.h:405
Floating-point value.
Definition: var.h:168
Var(const char *val)
Constructor to copy from an string value.
Definition: var.h:340
ThisType & setempty()
Set as empty but not null.
Definition: maplist.h:364
int64 get_int() const
Get signed integer number value (const).
Definition: var.h:1268
const char * data() const
Get string pointer (const).
Definition: string.h:1533
bool empty() const
Get whether empty.
Definition: list.h:753
ThisType & clear()
Clear by removing all items.
Definition: maplist.h:370
String container.
Definition: string.h:674
Var & unshare_all()
Unshare current value and all nested objects, lists, and strings.
Definition: var.h:747
bool null() const
Get whether null.
Definition: list.h:745
Initializer key/value pair.
Definition: var.h:1712
InitPair(const String &key, const T &value)
Definition: var.h:1717
Size size() const
Get size as number of children.
Definition: var.h:646
ListType & addmin(Size minsize)
Append new items up to a given minimum size (modifier).
Definition: list.h:2005
InitPair(const char *key, const T &value)
Definition: var.h:1725
const Value & value() const
Get value for pair (second value) (const).
Definition: pair.h:138
bool is_object() const
Get whether an object type (tOBJECT).
Definition: var.h:453
Var(std::initializer_list< Var > init)
Sequence constructor (C++11).
Definition: var.h:179
Evo List container.
Var & operator[](Size index)
List item access operator.
Definition: var.h:1530
String & setn(int num, int base=fDEC)
Set as formatted signed number (modifier).
Definition: string.h:1117
General purpose variable that can hold a basic value (string, number, bool, etc) or children with nes...
Definition: var.h:157
ListType & clear()
Clear by removing all items.
Definition: list.h:574
Object with key/value fields.
Definition: var.h:165
String & setempty()
Set as empty but not null.
Definition: string.h:982
Var(short val)
Constructor to initialize as integer value (short).
Definition: var.h:384
const String & get_str() const
Get read-only string value reference (const).
Definition: var.h:1200
SizeT Size
Size type used.
Definition: var.h:159
Var value
Field value.
Definition: var.h:1714
bool shared() const
Get whether shared.
Definition: list.h:767
static const NewlineDefault & NL
Default newline type.
Definition: sys.h:785
Var & operator=(uint val)
Assignment operator to set as unsigned integer value (uint).
Definition: var.h:1436
Var()
Default constructor sets as null.
Definition: var.h:258
bool is_bool() const
Get whether a boolean type (tBOOL).
Definition: var.h:528
const Var & childref(Size index) const
Get child in list using index, default to null instance (const).
Definition: var.h:808
Var(ushort val)
Constructor to initialize as unsigned integer value (ushort).
Definition: var.h:356
ListType & setempty()
Set as empty but not null.
Definition: list.h:735
Evo C++ Library namespace.
Definition: alg.h:11
Type
Variable type.
Definition: var.h:164
Var & operator=(const StringBase &val)
Assignment operator to copy from string value.
Definition: var.h:1394
TSize Size
Size type for size values (must be unsigned integer) – default: SizeT.
Definition: map.h:134
Var(ulongl val)
Constructor to initialize as unsigned integer value (ulongl).
Definition: var.h:377
char buf_str_[sizeof(String)]
Definition: var.h:1557
bool is_float() const
Get whether a floating-point number type (tFLOAT).
Definition: var.h:493
Var(const ListType &val)
Constructor to copy from an object list type.
Definition: var.h:313
const Key & key() const
Get key for pair (first value) (const).
Definition: pair.h:114
uint64 buf_uint_
Definition: var.h:1559
List of values
Definition: var.h:166
T getnumf(Error &error) const
Convert to floating point number value for given type.
Definition: string.h:4084
String & unshare()
Make data unique by allocating new buffer, if needed (modifier).
Definition: string.h:5031
String & string()
Get string reference, recreate as string if needed.
Definition: var.h:925
Boolean value.
Definition: var.h:171
int64 buf_int_
Definition: var.h:1560
Size size() const
Get map size (number of items).
Definition: map.h:272
bool is_string() const
Get whether a string type (tSTRING).
Definition: var.h:471
Map implemented as an ordered list.
Definition: maplist.h:229
InitPair(const StringBase &key, const T &value)
Definition: var.h:1721
bool & boolref()
Get bool reference, recreate as bool if needed.
Definition: var.h:1086
String value
Definition: var.h:167
VarObject(VarObject &&src)
Move constructor.
Definition: var.h:1748
Var * childM(Size index)
Find child in list using index (mutable).
Definition: var.h:854
Value * findM(const Key &key)
Find (lookup) value for given key (mutable).
Definition: maplist.h:443
T getnum(Error &error, int base=0) const
Convert to number value for given integer type.
Definition: string.h:4045
Var(int val)
Constructor to initialize as integer value (int).
Definition: var.h:391
Var(ValNull)
Constructor to initialize as as null with vNULL as argument.
Definition: var.h:417
Var(Var &&src)
Move constructor (C++11).
Definition: var.h:190
bool shared_scan() const
Get whether this or any nested key or value has any shared data.
Definition: var.h:565
Var & operator=(const char *val)
Assignment operator to copy from terminated string value.
Definition: var.h:1405
Var(ulong val)
Constructor to initialize as unsigned integer value (ulong).
Definition: var.h:370
const ObjectType & get_object() const
Get read-only object reference (const).
Definition: var.h:1172
bool empty() const
Get whether map is empty (size is 0).
Definition: map.h:266
Var(double val)
Constructor to initialize as floating-point value.
Definition: var.h:349
Sequential list container with random access.
Definition: list.h:240
bool shared() const
Get whether this has shared data.
Definition: var.h:538
const Value * find(const Key &key) const
Find (lookup) value for given key (const).
Definition: maplist.h:437
Var(const Var &src)
Copy constructor.
Definition: var.h:264
Var & operator=(const ListType &val)
Assignment operator to copy from list type.
Definition: var.h:1372
ListType & unshare()
Make data unique by allocating new buffer, if needed (modifier).
Definition: list.h:1783
String & set()
Set as null and empty.
Definition: string.h:995
uint64 & numu()
Get unsigned integer number reference, recreate as unsigned integer if not an integer.
Definition: var.h:956
T & itemM(Key index)
Get item at position (mutable).
Definition: list.h:1487
char buf_obj_[sizeof(MapList< String, char >)]
Definition: var.h:1555
Var & operator=(long val)
Assignment operator to set as signed integer value (long).
Definition: var.h:1481
Stores a key/value pair of independent objects or values.
Definition: pair.h:32
List< Var > ListType
Item list type.
Definition: var.h:161
uint32 SizeT
Default Evo container size type.
Definition: sys.h:729
Integer value (signed)
Definition: var.h:170
Var & operator=(const String &val)
Assignment operator to copy from string value.
Definition: var.h:1383
bool null() const
Get whether null.
Definition: var.h:600
double get_float() const
Get value as a floating-point number (const).
Definition: var.h:1215
Base for all Evo list types (used internally).
Definition: sys.h:976
Var & operator=(ulong val)
Assignment operator to set as unsigned integer value (ulong).
Definition: var.h:1445
bool is_unsigned() const
Get whether an unsigned integer number type (tUNSIGNED).
Definition: var.h:514
T & dump(T &out, const NewlineValue &newline=NL, uint indent=0) const
Dump all children and values to stream or string.
Definition: var.h:1545
bool null() const
Get whether map is null.
Definition: maplist.h:378
Var VarList
Alias for Var, useful for explicitly passing a list to a VarObject field value (C++11).
Definition: var.h:1768
ListType & list()
Get list reference, recreate as list if needed.
Definition: var.h:896
Var & operator=(int val)
Assignment operator to set as signed integer value (int).
Definition: var.h:1472
Type type() const
Get current type.
Definition: var.h:428
Var(const StringBase &val)
Constructor to copy from a string value.
Definition: var.h:331