Castable.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 
32 #ifndef DRAIN_CASTABLE2
33 #define DRAIN_CASTABLE2 "drain::Castable"
34 
35 #include <string.h> // Old C
36 #include <cstddef>
37 #include <typeinfo>
38 #include <stdexcept>
39 #include <iostream>
40 #include <vector>
41 #include <list>
42 #include <set>
43 #include <string>
44 
45 #include "Caster.h"
46 #include "Sprinter.h"
47 #include "String.h"
48 #include "UniTuple.h"
49 
50 
51 namespace drain {
52 
53 // Forward declaration
54 // class Variable;
55 
56 // Forward declaration
57 // class Referencer;
58 
60 
76 class Castable {
77 
78 // Optionally, constructors of this base class could be protected.
79 public:
80 
81  inline
82  Castable() : fillArray(false), elementCount(0){
83  setSeparator();
84  caster.unsetType();
85  };
86 
88  inline
89  Castable(const Castable &c) : fillArray(false), elementCount(0) {
90  copyFormat(c); // modifies elementCount = misleading; rename?
91  setPtr(c.caster.ptr, c.caster.getType(), c.elementCount);
92  }
93 
95  template <class F>
96  Castable(F &p) : fillArray(false), elementCount(0) {
97  setSeparator();
98  setPtr(p);
99  }
100 
101  // Obsolete?
105  template <class F>
106  Castable(F *p) : fillArray(false), elementCount(0) {
107  setSeparator();
108  setPtr(p, typeid(F));
109  // std::cerr << "Castable(F *p) type=" << typeid(F).name() << " value=" << *p << " (" << (double)*p << ")" << std::endl;
110  }
111 
112 
113  inline virtual
114  ~Castable(){};
115 
116 
117  virtual inline
118  bool typeIsSet() const {
119  return caster.typeIsSet();
120  };
121 
123 
131  bool empty() const;
132 
134  virtual inline
135  const std::type_info & getType() const {
136  return caster.getType();
137  };
138 
140  inline
141  bool isValid() const {
142  return (caster.typeIsSet()) && (caster.ptr != nullptr);
143  };
144 
145 
147  virtual inline
148  bool isLinking() const { // rename: external?
149  return isValid(); // return false, if nullptr
150  // return true;
151  }
152 
154 
159  virtual inline
160  bool isVariable() const { // needed?
161  return false;
162  }
163 
165  inline
166  bool isCharArrayString() const {
167  return ((caster.getType() == typeid(char)) && (outputSeparator=='\0')); // "close enough" guess, or a definition?
168  };
169 
171  inline
172  bool isStlString() const {
173  return (caster.getType() == typeid(std::string));
174  };
175 
177  inline
178  bool isString() const {
179  return (isCharArrayString() || isStlString());
180  };
181 
182 
184 
189  virtual inline
190  size_t getElementCount() const {
191  return elementCount;
192  }
193 
195 
200  inline
201  size_t getElementSize() const {
202  return caster.getElementSize();
203  };
204 
206 
210  virtual inline
211  size_t getSize() const {
212  return elementCount * caster.getElementSize();
213  }
214 
215 
216 
218  inline
219  Castable & setFill(bool fill=true){
220  fillArray = fill;
221  return *this;
222  }
223 
225  // Has been protected, even private. Why? Essentially setting a value.
226  void clear();
227 
231  inline
232  void reset(){
233  caster.unsetType();
234  updateSize(0);
235  setSeparator(',');
236  }
237 
239 
242  std::string getTypeName() const { // todo: support const string & in Type::call
243  if (isCharArrayString()){
244  static const std::string s("char-array");
245  return s;
246  }
247  else {
248  return Type::call<drain::simpleName>(getType());
249  }
250  }
251 
252 
253 public:
254 
255 
256  template <class T>
257  Castable &operator=(const T &x){
258  //std::cout << "op= " << x << " -> " << Type::getTypeChar(getType()) << ',' << getElementCount() << std::endl;
259  assign(x);
260  return *this;
261  }
262 
266  inline
267  Castable & operator=(const char *c){
268  assignString(c);
269  return *this;
270  }
271 
272 
273  template <class T>
274  Castable & operator=(const T *x){
275  throw std::runtime_error("Castable & operator=(const T *x): unsupported");
276  return *this;
277  }
278 
280 
283  inline
285  if (&c != this){
286  assignCastable(c);
287  }
288  return *this;
289  }
290 
291 
292  /*
293  inline
294  Castable &operator=(const Variable &c){
295  return assignCastable(c);
296  }
297 
298  inline
299  Castable &operator=(const Referencer &c){
300  return assignCastable(c);
301  }
302  */
303 
304  // Special handler for string assignment
305  inline
306  void assign(const std::string &c){
307  assignString(c);
308  }
309 
310 
311  inline
312  void assign(const char *c){
313  assignString(c);
314  }
315 
316  // "NEW"
317  inline
318  void assign(const Castable &c){
319  assignCastable(c);
320  }
321 
322  template <class T>
323  inline
324  void assign(const T *p){
325  if (p == nullptr)
326  reset();
327  else
328  throw std::runtime_error("Castable & assign(const T *p): unsupported");
329  }
330 
332 
335  template <class T>
336  void assign(const T &x){
337  // std::cout << "assign " << x << " -> " << Type::getTypeChar(getType()) << ',' << getElementCount() << std::endl;
338  suggestType(typeid(T));
339  if (isString()){
340  //std::cout << __FUNCTION__ << ':' << x << " -> " << Type::getTypeChar(getType()) << ',' << getElementCount() << '\n';
341  assignToString(x);
342  }
343  else if (typeIsSet()){
344  if (fillArray){
345  for (size_t i = 0; i<getElementCount(); ++i){
346  caster.put(getPtr(i), x);
347  }
348  }
349  else {
350  requestSize(1);
351  caster.put(x);
352  }
353  }
354  else {
355  throw std::runtime_error(std::string(__FUNCTION__) + ": type is unset");
356  }
357 
358 
359  }
360 
361 
362 
364  template<typename T>
365  // Castable & operator=(std::initializer_list<T> l){
366  void assign(std::initializer_list<T> l){
367  assignContainer(l);
368  //return *this;
369  }
370 
372  template <class T>
373  inline
374  // Castable &operator=(const std::list<T> & l){
375  void assign(const std::list<T> & l){
376  assignContainer(l);
377  // return *this;
378  }
379 
381  template <class T>
382  inline
383  // Castable &operator=(const std::vector<T> & v){
384  void assign(const std::vector<T> & v){
385  assignContainer(v);
386  // return *this;
387  }
388 
390  template <class T>
391  inline
392  // Castable &operator=(const std::set<T> & s){
393  void assign(const std::set<T> & s){
394  assignContainer(s);
395  //return *this;
396  }
397 
398 
400  Castable & assignCastable(const Castable &c);
401 
402 
403 
404  template <class T>
405  inline
406  Castable &operator<<(const T &x){
407  append(x);
408  return *this;
409  }
410 
411 
413  /*
414  * Note: if both source and target are strings, does not split it like with Variable::operator=(const char *).
415  */
416  template <class T>
417  inline
418  //Castable &operator<<(const T &x){
419  void append(const T &x){
420  suggestType(typeid(T));
421  if (isString()){
422  appendToString(x);
423  }
424  else {
425  appendToElementArray(x);
426  }
427  //return *this;
428  }
429 
431  inline
432  // Castable &operator<<
433  void append(const char *s){
434  //return *this << (std::string(s));
435  append(std::string(s));
436  }
437 
439  template <class T>
440  inline
441  void append(const std::list<T> & l){
442  assignContainer(l, true);
443  //return *this;
444  }
445 
447  template <class T>
448  inline
449  // Castable &operator<<
450  void append(const std::vector<T> & v){
451  assignContainer(v, true);
453  }
454 
456  template <class T>
457  inline // Castable &operator<<
458  void append(const std::set<T> & s){
459  assignContainer(s, true);
460  // return *this;
461  }
462 
463  template <class T>
464  inline
465  T get(size_t i) const {
466  if (i >= elementCount)
467  throw std::runtime_error("Castable::get() index overflow");
468  return caster.get<T>(getPtr(i));
469  }
470 
471 
473 
476  inline
477  operator std::string() const {
478  return toStr();
479  }
480 
483  // Thanks to Mikael Kilpeläinen.
496  template <class T>
497  operator T() const {
498  if (isCharArrayString()){
499  T x;
500  std::stringstream sstr;
501  sstr << getCharArray();
502  sstr >> x;
503  return x;
504  }
505  else
506  return caster.get<T>(); //caster.get<T>(ptr);
507  }
508 
509  template <class T, size_t N>
510  operator UniTuple<T,N>() const {
511  UniTuple<T,N> result;
512  result.assignSequence(*this, true);
513  }
514 
515 
516  inline
517  bool operator==(const Castable &c) const {
518  // std::cerr << __FILE__ << __LINE__ << __FUNCTION__ << std::endl;
519  //throw std::runtime_error("Castable: operator== not implemented.");
520 
521  if (!this->typeIsSet()){
522  return !c.typeIsSet(); // is "same"... (?)
523  }
524 
525  if (!c.typeIsSet()){
526  return false; // could return false for both?
527  }
528 
529  if (this->isString() || c.isString()){ // NOTE: precision loss in rounding numbers
530  return (this->toStr() == c.toStr());
531  }
532 
533  if (this->getElementCount() != c.getElementCount()){
534  return false;
535  }
536 
537 
538  for (size_t i = 0; i<this->getElementCount(); ++i){
539  if (! caster.compare(getPtr(i), c.caster, c.getPtr(i))){
540  return false;
541  }
542  }
543 
544  return true;
545  }
546 
548  inline
549  bool operator==(const char * s) const {
550  if (isCharArrayString()) // 2021
551  return (strcmp(getCharArray(), s) == 0);
552  else {
553  // Note: caster.get<std::string>() returns only the first element!
554  // std::cerr << __FILE__ << __LINE__ << __FUNCTION__ << toStr() << " vs " << caster.get<std::string>() << std::endl;
555  return (toStr() == s);
556  }
557  //return (caster.get<std::string>() == s);
558  }
559 
561 
566  inline
567  bool operator==(const nullptr_t ptr) const {
568  return getType() == typeid(void);
569  }
570 
571  /*
572  inline // 2024
573  bool operator==(const std::string & s) const {
574  return (caster.get<std::string>() == s);
575  }
576  */
577 
579  template <class T>
580  bool operator==(const T &x) const {
581  if (isCharArrayString()){ // 2024/04
582  std::stringstream sstr(getCharArray());
583  T c;
584  sstr >> c;
585  return (c == x);
586  }
587  else {
588  return (caster.get<T>() == x);
589  }
590  }
591 
592  template <class T, size_t N>
593  bool operator==(const UniTuple<T,N> & x) const {
594  if (isString()){ // 2024/04
595  // std::cerr << __FILE__ << ':' << __FUNCTION__ << " '" << this->toStr() << "' == '" << x.toStr(',') << "'" << std::endl;
596  return (this->toStr() == x.toStr(',')); // consider separator, but this->outputSeparator is null for char array str...
597  }
598  else if (elementCount == N){
599  for (size_t i=0; i<N; ++i){
600  if (x[i] != this->get<T>(i)){
601  return false;
602  }
603  }
604  return true;
605  }
606  else {
607  return false;
608  }
609 
610  }
611 
612 
613 
615 
618  template <class T>
619  bool operator!=(const T &x) const {
620  return ! this->operator==(x);
621  }
622 
623  bool operator!=(const char *x) const {
624  return ! this->operator==(x);
625  }
626 
627 
629  // strings?
630  template <class T>
631  bool operator<(const T &x) const {
632  return (caster.get<T>() < x);
633  }
634 
636  template <class T>
637  bool operator>(const T &x) const {
638  return (caster.get<T>() > x);
639  }
640 
642  // strings?
643  template <class T>
644  bool operator<=(const T &x) const {
645  return (caster.get<T>() <= x);
646  }
647 
649  template <class T>
650  bool operator>=(const T &x) const {
651  return (caster.get<T>() >= x);
652  }
653 
655 
658  inline
659  Castable & setSeparator(char c = ','){
662  return *this;
663  }
664 
666 
670  inline
671  void setInputSeparator(char c = ','){
672  inputSeparator = c;
673  }
674 
676 
680  inline
681  void setOutputSeparator(char c = ','){
682  outputSeparator = c;
683  }
684 
686 
690  inline
692  return inputSeparator;
693  }
694 
696 
700  inline
702  return outputSeparator;
703  }
704 
705 
706  std::ostream & toStream(std::ostream & ostr = std::cout, char separator='\0') const;
707 
708  std::istream & fromStream(std::istream & istr);
709 
710 
711  std::string toStr() const;
712 
714  void typeInfo(std::ostream & ostr) const;
715 
717  // Writes a bit longer type indentifier and size in bytes, for example "unsigned int(8) for char and "signed int(16) for signed short int."
718  virtual
719  void info(std::ostream & ostr = std::cout) const;
720 
721  // void debug(std::ostream & ostr = std::cout) const;
722 
723 
724 
726 
731  template <class T>
732  void toSequence(T & container, char separator = 0) const { // FIX raise
733 
734  container.clear();
735 
736  if (isString()){
737  if (!separator)
738  separator = this->outputSeparator;
739  StringTools::split(toStr(), container, separator," \t\n");
740  }
741  else {
742  for (size_t i = 0; i < getElementCount(); ++i) {
744  container.insert(container.end(), caster.get<typename T::value_type>(getPtr(i)) );
745  }
746  }
747 
748 
749  }
750 
751 
752 
753  template <class T>
754  void toMap(T & map, char separator = 0, char equalSign = '=') const {
755 
756  map.clear();
757 
758  if (isString()){
759  // This part could be in StringTools?
760  typedef std::list<std::string> entryList;
761  entryList entries;
762  toSequence(entries, separator);
763 
764  for (entryList::const_iterator it = entries.begin(); it!=entries.end(); ++it){
765  //typename T::value_type entry;
766  typename T::key_type key;
767  typename T::mapped_type data;
768  drain::StringTools::split2(*it, key, data, std::string(1, equalSign)); // TRIM?
769  map[key] = data;
770  }
771  }
772  else {
773  for (size_t i = 0; i < getElementCount(); ++i){
774  //typename T::value_type entry;
775  typename T::key_type key;
776  typename T::mapped_type data;
777  std::stringstream sstr;
778  sstr << i;
779  sstr >> key; // entry.first;
780  std::stringstream sstr2;
781  //sstr2 << caster.get<typename T::value_type>(getPtr(i)); // weirds
782  sstr2 << caster.get<typename T::mapped_type>(getPtr(i)); // weirds
783  sstr2 >> data;
784  map[key] = data;
785  }
786  }
787 
788 
789  }
790 
791 
793 
796  inline
797  char * getPtr(size_t i = 0) {
798  return &((char *)caster.ptr)[i*caster.getElementSize()];
799  }
800 
801  inline
802  const char * getPtr(size_t i = 0) const {
803  return &((const char *)caster.ptr)[i*caster.getElementSize()];
804  }
805 
806 
808  void copyFormat(const Castable & c){
809  this->elementCount = c.elementCount;
810  this->inputSeparator = c.inputSeparator;
812  this->fillArray = c.fillArray;
813  }
814 
815 
816  virtual inline
817  bool requestType(const std::type_info & t){
818  return (getType() == t);
819  }
820 
822 
825  virtual inline
826  bool suggestType(const std::type_info & t){
827  return (getType() == t);
828  }
829 
831  bool fillArray = false;
832 
833 protected:
834 
835  virtual
836  void updateSize(size_t elems){
837  elementCount = elems;
838  }
839 
840 protected:
841 
842  Caster caster;
843 
844 
845 
847  template <class F>
848  inline // FINAL
849  void setType(){
851  setType(typeid(F));
852  }
853 
855  virtual inline // virtual? Variable may need
856  void setType(const std::type_info &t){
857  setSeparator(','); // ?
858  caster.setType(t);
859  //elementCount = 1; ?
860  }
861 
863 
866  virtual inline
867  bool requestSize(size_t elementCount){
868  return (getElementCount() == elementCount);
869  }
870 
871 
873  template <class F>
874  inline
875  void setPtr(void *p){
876  caster.link(p);
877  elementCount = 1;
878  }
879 
880 
882  template <class F>
883  void setPtr(F &p){
884  if ((!std::is_arithmetic<F>::value) && (typeid(F)!=typeid(std::string))){
885  throw std::runtime_error(std::string(__FUNCTION__) + ": unsupported type: " + typeid(F).name());
886  }
887  caster.link(p); // could use setPtr(void *p, const std::type_info &t) ?
888  elementCount = 1;
889  }
890 
892  /*
893  * Function of this kind must be available for general (8bit) memory allocators.
894  */
895  inline
896  void setPtr(void *p, const std::type_info &t, size_t count=1){
897  //if (t == typeid(void))
898  // throw std::runtime_error(std::string(__FUNCTION__) + ": explicit void type given");
899  caster.link(p, t);
900  elementCount = count;
901  }
902 
904 
907  /*
908  template <class F>
909  // void setPtr(std::pair<F,F> &p){
910  setPtr(&p, typeid(F), 2);
911  //caster.link((F*)&v);
912  fillArray = true; // if a scalar is assigned, assign to both elements
913  //elementCount = 2;
914  }
915  */
916 
918 
921  template <class F, size_t N>
922  void setPtr(UniTuple<F,N> & tuple){
923  setPtr(tuple.begin(), typeid(F), N);
924  fillArray = true; // (?) if a scalar is assigned, assign to all elements
925  }
926 
927 
928 
929 
931  void relink(Castable & c);
932 
933 
934  /*
935  inline
936  void setPtr(const Castable &c){
937  //caster.link0((const Caster &)c);
938 
939  caster.ptr = c.caster.ptr;
940  caster.setType(c.getType());
941 
942  elementCount = c.elementCount; // TODO
943  outputSeparator = c.outputSeparator; // ?
944  }
945 
947  inline
948  void setPtr(Castable &c){
949  caster.link0((Caster &)c);
950  // caster.ptr = c.caster.ptr;
951  // caster.setType(c.getType());
952  elementCount = c.elementCount; // TODO
953  outputSeparator = c.outputSeparator; // ?
954  }
955  */
956 
958  // IMPORTANT!
959  inline
960  void castElement(size_t i, const Caster &c, void *p) const {
961  c.translate(caster, getPtr(i), p);
962  }
963 
964 
965  // Destination type (current type) specific assign operations
966 
967 
968 
970 
975  template <class T>
976  void appendToString(const T & x){
977 
978  std::stringstream sstr;
979 
980  // drain::Sprinter::toStream(sstr, *this, drain::Sprinter::plainLayout);
981  toStream(sstr);
982 
983  if (inputSeparator && (getElementCount()>1)){
984  sstr << inputSeparator;
985  }
986  sstr << x;
987 
988  std::string s = sstr.str();
989 
990  suggestType(typeid(std::string));
991 
992  if (isStlString()){
993  caster.put(s);
994  //caster.put(ptr, s);
995  }
996  else if (isCharArrayString()){
997  assignToCharArray(s);
998  }
999  else {
1000  throw std::runtime_error(std::string(__FUNCTION__) + ": type is not a string: " + typeid(T).name());
1001  }
1002  }
1003 
1004 
1005  template <class T>
1006  void assignToString(const T & x){
1007 
1008  /*
1009  if (x == nullptr){
1010  //suggestType(typeid(void));
1011  suggestType(typeid(void));
1012  //experimental
1013  return;
1014  }
1015  */
1016 
1017  suggestType(typeid(std::string));
1018 
1019  if (isStlString()){
1020  caster.put(x);
1021  //caster.put(ptr, x);
1022  }
1023  else if (isCharArrayString()){
1024  requestSize(0); // works only for Variable, ok
1025  clear(); // works always (but if elementCount)
1026  appendToString(x);
1027  }
1028  else {
1029  throw std::runtime_error(std::string(__FUNCTION__) + ": type is std::string");
1030  }
1031  }
1032 
1033  void assignToCharArray(const std::string & s);
1034 
1035  inline
1036  void assignToCharArray(const char *s){
1037  assignToCharArray(std::string(s));
1038  }
1039 
1041 
1044  template <class T>
1045  void assignToCharArray(const T & s){
1046  std::stringstream sstr;
1047  sstr << s;
1048  assignToCharArray(sstr.str());
1049  }
1050 
1051 
1052  inline
1053  void appendToElementArray(const char *s){
1054  appendToElementArray(std::string(s));
1055  }
1056 
1057  template <class T>
1058  void appendToElementArray(const T & s){
1059 
1060  suggestType(typeid(T)); // check return code?
1061  if (!typeIsSet()){
1062  throw std::runtime_error(std::string(__FUNCTION__) + ": type is unset");
1063  return;
1064  }
1065 
1066  // Check if now type==string...
1067  if (isString()){
1068  throw std::runtime_error(std::string(__FUNCTION__) + ": type is std::string (not implemented yet)");
1069  //return;
1070  }
1071 
1072  // Extend array.
1074  if (empty()){
1075  throw std::runtime_error(std::string(__FUNCTION__) + ": still empty after resize request(+1)");
1076  return;
1077  }
1078 
1079  // TODO: what if non-empty but fixed?
1080 
1081  caster.put(getPtr(getElementCount()-1), s);
1082 
1083  }
1084 
1085 
1086 
1087 public:
1088  /* public NEW 2021 (experimental)
1089  *
1090  * useful in "stream" definitions:
1091  * drain::Referencer(range.tuple()).setSeparator(':').setFill().assignString(ftor);
1092  *
1093  */
1094 
1095 
1097 
1098  void assignString(const std::string &s);
1099 
1100  // NEW 2024
1101  template <class T, size_t N>
1102  inline
1103  void assign(const UniTuple<T,N> & tuple){
1104  assignContainer(tuple);
1105  }
1106 
1108  template <class T>
1109  void assignContainer(const T & v, bool append=false) {
1110 
1111  if (!append){
1112  if (isStlString())
1113  clear();
1114  else
1115  requestSize(0);
1116  }
1117 
1118  suggestType(typeid(typename T::value_type));
1119  // Note: sequence of strings, will request string type...
1120 
1121  if (isString()){
1122  std::stringstream sstr;
1123  if (append){
1125  //toStream(sstr); // outputsepp?
1126  if (inputSeparator)
1127  sstr << inputSeparator;
1128  }
1129  StringTools::join(v, sstr, inputSeparator); // implement!
1130  assignToString(sstr.str());
1131  }
1132  else if (caster.typeIsSet()){
1133 
1134  if (append){
1135  for (typename T::const_iterator it = v.begin(); it != v.end(); ++it){
1136  appendToElementArray(*it);
1137  }
1138  }
1139  else {
1140  requestSize(v.size());
1141  typename T::const_iterator it = v.begin();
1142  typename T::const_iterator itLast = it;
1143  for (size_t i = 0; i<getElementCount(); ++i){
1144  if (it == v.end()){
1145  if (fillArray)
1146  it = itLast; //v.begin(); WHAT if empty?
1147  else
1148  return;
1149  }
1150  else {
1151  itLast = it;
1152  }
1153  caster.put(getPtr(i), *it);
1154  ++it;
1155  }
1156  }
1157  }
1158  else {
1159  throw std::runtime_error(std::string(__FILE__) + ": type unset, cannot assign");
1160  }
1161 
1162  }
1163 
1164 
1166 
1169  /* OLD
1170  inline
1171  const char * getCharArray() const {
1172 
1173  if (!isCharArrayString())
1174  throw std::runtime_error("getCharArray: type not char array...");
1175 
1176  if (empty()){
1177  static const char * empty = "";
1178  return empty;
1179  // throw std::runtime_error("getCharArray: empty array, no even null char");
1180  }
1181 
1182  if (*getPtr(getElementCount()-1) != '\0')
1183  throw std::runtime_error("getCharArray: no terminating null char");
1184 
1185  return getPtr();
1186 
1187  }
1188  */
1189 
1191 
1197  // NEW
1198 
1199 public:
1200 
1201  const char * getCharArray() const;
1202 
1203 protected:
1204 
1206  // void *ptr;
1207 
1210 
1213 
1216 
1217 
1218 };
1219 
1220 
1221 
1223 template <>
1224 std::ostream & Sprinter::toStream(std::ostream & ostr, const drain::Castable & x, const SprinterLayout & layout);
1225 
1226 
1227 
1228 inline
1229 std::ostream & operator<<(std::ostream &ostr, const Castable &c){
1230  return c.toStream(ostr);
1231  //return Sprinter::toStream(ostr, c, Sprinter::plainLayout);
1232 }
1233 
1234 /* UNDER CONSTR..
1235 inline
1236 std::istream & operator>>(std::istream & istr, Castable &c){
1237  return c.fromStream(istr);
1238 }
1239 */
1240 
1242 template <class T>
1243 inline
1244 T & operator+=(T & x, const Castable &c){
1245  x += c.get<T>(0);
1246  return x;
1247 }
1248 
1250 template <class T>
1251 inline
1252 T & operator-=(T & x, const Castable &c){
1253  x -= c.get<T>(0);
1254  return x;
1255 }
1256 
1258 template <class T>
1259 inline
1260 T & operator*=(T & x, const Castable &c){
1261  x *= c.get<T>(0);
1262  return x;
1263 }
1264 
1266 template <class T>
1267 inline
1268 T & operator/=(T & x, const Castable &c){
1269  x /= c.get<T>(0);
1270  return x;
1271 }
1272 
1273 
1274 
1275 template <>
1276 const std::string TypeName<Castable>::name;
1277 
1278 /*
1279 template <class T, size_t N=2>
1280 template <class T2>
1281 UniTuple<T,N> & UniTuple<T,N>::set(const Castable & t){
1282  // assignSequence(t, true); // by default LENIENT, or how should it be?
1283  return *this;
1284 }
1285 */
1286 
1287 
1288 } // namespace drain
1289 
1290 
1291 #endif
1292 
1293 // Drain
Definition: Castable.h:76
void setPtr(UniTuple< F, N > &tuple)
Stores the pair as an array of two elements.
Definition: Castable.h:922
void setPtr(void *p, const std::type_info &t, size_t count=1)
Sets the data pointer and its explicit type.
Definition: Castable.h:896
void append(const std::set< T > &s)
Appends elements of a set.
Definition: Castable.h:458
Castable & setSeparator(char c=',')
The character used between array elements in output stream.
Definition: Castable.h:659
bool isCharArrayString() const
Returns true, if type is C char array and outputSepator is the null char.
Definition: Castable.h:166
virtual bool isLinking() const
Return true, if the referenced variable is external. Inherited classes - like Variable - may have int...
Definition: Castable.h:148
virtual const std::type_info & getType() const
Return the storage type (base type) of the referenced variable.
Definition: Castable.h:135
void append(const std::list< T > &l)
Appends elements of std::list.
Definition: Castable.h:441
Castable & operator=(const Castable &c)
Copies the value referred to by Castable. Notice that if type is unset (void), no operation is perfor...
Definition: Castable.h:284
bool operator==(const nullptr_t ptr) const
Experimental. Notice that if type is set, false is returned also for an empty array.
Definition: Castable.h:567
void copyFormat(const Castable &c)
Copies array layout and formatting: separators, element count, fillArray flag.
Definition: Castable.h:808
void assignString(const std::string &s)
Input type specific assign operations.
Definition: Castable.cpp:365
bool operator<(const T &x) const
Compares a value to inner data.
Definition: Castable.h:631
Castable(const Castable &c)
Copy constructor: copies the layout and the pointer to the target.
Definition: Castable.h:89
bool operator<=(const T &x) const
Compares a value to inner data.
Definition: Castable.h:644
Castable & setFill(bool fill=true)
Set or unset filling (padding) an array if input set is smaller.
Definition: Castable.h:219
void typeInfo(std::ostream &ostr) const
Writes a string of type indentifier char and size in bytes, for example [C@8] for unsigned char and [...
Definition: Castable.cpp:220
virtual size_t getElementCount() const
Returns the length of the array, the number of elements in this entry.
Definition: Castable.h:190
virtual void info(std::ostream &ostr=std::cout) const
Print value, type and element count.
Definition: Castable.cpp:233
virtual bool suggestType(const std::type_info &t)
Request to change in type. For Castable, simply returns true if the current type was requested.
Definition: Castable.h:826
void assign(const std::vector< T > &v)
Copies elements of a vector.
Definition: Castable.h:384
void append(const char *s)
Appends the string or appends the array by one element.
Definition: Castable.h:433
bool isValid() const
Return true, if the pointer is set.
Definition: Castable.h:141
char getOutputSeparator()
Definition: Castable.h:701
bool empty() const
Returns true, if string is empty or array size is zero. (In future, semantics may change: 0 for scala...
Definition: Castable.cpp:36
void assign(const std::list< T > &l)
Copies elements of a list.
Definition: Castable.h:375
virtual bool isVariable() const
Returns true, if the class contains an own data array.
Definition: Castable.h:160
void setPtr(F &p)
Stores the pointer and its storage type F.
Definition: Castable.h:883
size_t elementCount
Pointer to the data variable.
Definition: Castable.h:1209
bool isStlString() const
Returns true, if type is std::string .
Definition: Castable.h:172
std::string getTypeName() const
Returns the name of the current storage type.
Definition: Castable.h:242
void assignToCharArray(const T &s)
Input anything to char array string.
Definition: Castable.h:1045
void assignContainer(const T &v, bool append=false)
Assigns a STL Sequence, element by element.
Definition: Castable.h:1109
char getInputSeparator()
Definition: Castable.h:691
void appendToString(const T &x)
Append to std::string or char array.
Definition: Castable.h:976
void assign(const T &x)
Copies an arbitrary base type or std::string value.
Definition: Castable.h:336
Castable & assignCastable(const Castable &c)
Copy data from Castable. Perhaps copy size and type, too.
Definition: Castable.cpp:256
size_t getElementSize() const
Return the size of the current storage type, in bytes.
Definition: Castable.h:201
void assign(const std::set< T > &s)
Copies elements of a set.
Definition: Castable.h:393
bool operator==(const char *s) const
Compare as a character string.
Definition: Castable.h:549
char * getPtr(size_t i=0)
Returns pointer to the array of chars without validity check.
Definition: Castable.h:797
bool fillArray
If array, assigning a scalar will fill up the current array.
Definition: Castable.h:831
void toSequence(T &container, char separator=0) const
Converts data to a STL Sequence, for example std::set, std::list or std::vector .
Definition: Castable.h:732
bool operator>(const T &x) const
Compares a value with inner data.
Definition: Castable.h:637
char outputSeparator
Element separator usein in writing and reading character strings (streams).
Definition: Castable.h:1215
bool isString() const
Returns true, if type is C char array or std::string .
Definition: Castable.h:178
void setPtr(void *p)
Stores the pointer and its storage type F. Assumes elementCount=1.
Definition: Castable.h:875
const char * getCharArray() const
Returns pointer to the array of chars, checks validity first.
Definition: Castable.cpp:93
void append(const std::vector< T > &v)
Appends elements of a vector.
Definition: Castable.h:450
virtual void setType(const std::type_info &t)
Sets the storage type. If a target value is available, use setPtr() directly.
Definition: Castable.h:856
char inputSeparator
Element separator usein in reading a char sequence to an (numeric) array.
Definition: Castable.h:1212
Castable & operator=(const char *c)
Definition: Castable.h:267
void clear()
Clears strings, or for scalars and arrays, sets all the values to zero. Does not change type.
Definition: Castable.cpp:81
bool operator==(const T &x) const
Compares a value to internal data.
Definition: Castable.h:580
void setType()
Sets the storage type. If a target value is available, use setPtr() directly.
Definition: Castable.h:849
void append(const T &x)
Appends the string or appends the array by one element.
Definition: Castable.h:419
void reset()
Definition: Castable.h:232
void relink(Castable &c)
Copies the link and element count.
Definition: Castable.cpp:69
void castElement(size_t i, const Caster &c, void *p) const
Let Caster c convert my element #i to target *p.
Definition: Castable.h:960
void setOutputSeparator(char c=',')
Definition: Castable.h:681
Castable(F &p)
Constructor for an object pointing to a variable.
Definition: Castable.h:96
bool operator>=(const T &x) const
Compares a value with inner data.
Definition: Castable.h:650
virtual size_t getSize() const
Returns the size in bytes of the target: (elementCount * elementSize)
Definition: Castable.h:211
bool operator!=(const T &x) const
Compares a value to inner data.
Definition: Castable.h:619
virtual bool requestSize(size_t elementCount)
Request to change the array size. For Castable (and Reference) does nothing and returns false.
Definition: Castable.h:867
void setInputSeparator(char c=',')
Definition: Castable.h:671
void assign(std::initializer_list< T > l)
Copies elements of a list.
Definition: Castable.h:366
Definition: Caster.h:67
const std::type_info & getType() const
Returns type_info of the current type.
Definition: Caster.h:144
T get(const void *p) const
Default implementation throws an error. See specialized implementation below.
Definition: Caster.h:194
void unsetType()
calls void setType<void>().
Definition: Caster.cpp:134
size_t getElementSize() const
Returns the size of the base type (size of an element, not of element array).
Definition: Caster.h:151
void setType(const std::type_info &t)
Calls setType<T>() for which typeid(T) = t.
Definition: Caster.h:119
void translate(const Caster &c, const void *ptrC, void *ptr) const
Convert from str pointer and Caster.
Definition: Caster.h:208
void * ptr
Future member: enables setting Caster type.
Definition: Caster.h:247
void put(void *p, const T &x) const
Default conversion (for unconventional types). Uses std::stringstream for conversion.
Definition: Caster.h:157
static const SprinterLayout plainLayout
Display plain values, concatenating them with comma (except for strings).
Definition: Sprinter.h:209
static std::ostream & toStream(std::ostream &ostr, const std::initializer_list< T > &x, const SprinterLayout &layout=defaultLayout)
New (experimental)
Definition: Sprinter.h:420
static bool split2(const std::string &s, T1 &first, T2 &second, const C &separators, const std::string &trimChars=" \t\n")
Splits and trims a given std::string to a std Sequence.
static std::ostream & join(const T &container, std::ostream &ostr, char separator=0)
Writes a STL Container (list, vector, set) to a stream, using an optional separator char (e....
Definition: String.h:202
static void split(const std::string &s, T &sequence, const C &separators, const std::string &trimChars=" \t\n")
Splits and trims a given std::string to a std Sequence.
Definition: String.h:309
tuplebase_t & assignSequence(T &sequence, bool LENIENT=false)
Proposed for tuples only; derived classes should not shadow this.
Definition: TupleBase.h:244
Tuple of N elements of type T.
Definition: UniTuple.h:65
Definition: DataSelector.cpp:1277
T & operator*=(T &x, const Castable &c)
Arithmetics: addition.
Definition: Castable.h:1260
T & operator+=(T &x, const Castable &c)
Arithmetics: addition.
Definition: Castable.h:1244
T & operator/=(T &x, const Castable &c)
Arithmetics: subtraction.
Definition: Castable.h:1268
T & operator-=(T &x, const Castable &c)
Arithmetics: subtraction.
Definition: Castable.h:1252
Definition: Sprinter.h:137
static const std::string name
Default implementation: name returned by std::type_info::name()
Definition: Type.h:558