TypeUtils.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_TYPE_UTILS
33 #define DRAIN_TYPE_UTILS
34 
35 #include <limits>
36 #include <set>
37 #include <typeinfo>
38 
39 
40 // #include "Type.h"
41 #include "RegExp.h"
42 
43 namespace drain {
44 
45 
46 struct TypeUtils {
47 
48 
50 
53  static
54  const std::type_info & guessType(const std::string & value);
55 
57 
60  template <class C>
61  static
62  const std::type_info & guessArrayType(const C & container);
63 
64  static
65  const drain::RegExp trueRegExp; // ignore case
66 
67  static
68  const drain::RegExp falseRegExp; // ignore case
69 
70  // TODO: better whitespace
71  static
72  const drain::RegExp numeralRegExp;
73 
74 };
75 
76 
77 /*
78  * \tparam C - contrainer, esp. std::list or std::vector
79  */
80 template <class C>
81 const std::type_info & TypeUtils::guessArrayType(const C & l){
82 
83 
84  typedef std::set<const std::type_info *> typeset;
85 
86  typeset s;
87  for (typename C::const_iterator it = l.begin(); it != l.end(); ++it) {
88  s.insert(& guessType(*it));
89  }
90 
92  if (s.find(& typeid(std::string)) != s.end())
93  return typeid(std::string);
94 
96  if (s.find(& typeid(double)) != s.end())
97  return typeid(double);
98 
99  if (s.find(& typeid(int)) != s.end())
100  return typeid(int);
101 
103  if (s.find(& typeid(bool)) != s.end())
104  return typeid(bool);
105 
106  // General fallback solution
107  return typeid(std::string);
108 
109 }
110 
111 
112 
114 class typesetter {
115 public:
116 
121  template <class S, class T>
122  static
123  void callback(T & target){
124  target.template setType<S>();
125  }
126 };
127 
128 
130 
138 class sizeGetter {
139 
140 public:
141 
142  typedef std::size_t value_t;
143 
148  template <class S, class T>
149  static inline
150  T callback(){
151  return static_cast<T>(getSize<S>()); // static cast unneeded in these ?
152  }
153 
154 protected:
155 
156  // Must be here to get template<void> implemented
157  template <class S>
158  static inline
159  size_t getSize(){
160  return sizeof(S);
161  }
162 
163 };
164 
165 template <>
166 inline
167 size_t sizeGetter::getSize<void>(){
168  return 0;
169 }
170 // todo:: std::string?
171 
172 
173 
174 
175 
176 
177 
179 
183 /*
184 class complexNameOLD {
185 
186 public:
187 
188  typedef std::string value_t;
189 
190  // \tparam S - type to be analyzed (argument)
191  // \tparam T - return type (practically value_t)
192  template <class S, class T>
193  static
194  T callback(){
195  //const std::type_info & t = typeid(S);
196  std::stringstream sstr;
197  if (std::numeric_limits<S>::is_specialized){
198  if (std::numeric_limits<S>::is_integer)
199  if (std::numeric_limits<S>::is_signed)
200  sstr << "signed integer";
201  else
202  sstr << "unsigned integer";
203  else
204  sstr << "float";
205  }
206  else {
207  sstr << " non-numeric";
208  }
209  //sstr << '(' << (sizeof(S)*8) << ')';
210  sstr << " (" << (8 * sizeGetter::callback<S, std::size_t>()) << " bits)";
211  //sstr << ' ' << simpleName::callback<S,T>();
212  return sstr.str();
213  }
214 
215 };
216 */
217 
218 
219 class compactName {
220 
221 public:
222 
223  typedef const std::string & value_t;
224 
229  template <class S, class T>
230  static
231  T callback(){
232 
233  static std::string s;
234 
235  if (s.empty()){
236  std::stringstream sstr;
237  size_t n = sizeGetter::callback<S, std::size_t>();
238  if (std::numeric_limits<S>::is_specialized){
239  if (std::numeric_limits<S>::is_integer){
240  if (!std::numeric_limits<S>::is_signed)
241  sstr << 'u';
242  // sstr << ' ';
243  if (n==1)
244  sstr << "char";
245  else
246  sstr << "int";
247  }
248  else
249  sstr << "float";
250  }
251  else {
252  if (typeid(S) == typeid(bool))
253  sstr << "bool";
254  else if (n==0)
255  sstr << "void";
256  else
257  sstr << "other"; // pointer, for example?
258  }
259  //sstr << (8 * n);
260  s = sstr.str();
261  }
262 
263  return s;
264 
265  }
266 
267 };
268 
269 class complexName {
270 
271 public:
272 
273  //typedef std::string value_t;
274  typedef const std::string & value_t;
275 
280  template <class S, class T>
281  static
282  T callback(){
283  // typedef std::numeric_limits<S> nlim;
284  // return numInfo<nlim::is_specialized, nlim::is_integer, nlim::is_signed>::s;
285  static std::string s;
286 
287  if (s.empty()){
288  std::stringstream sstr;
289  size_t n = sizeGetter::callback<S, std::size_t>();
290  if (std::numeric_limits<S>::is_specialized){
291  if (std::numeric_limits<S>::is_integer){
292  if (std::numeric_limits<S>::is_signed)
293  sstr << "signed";
294  else
295  sstr << "unsigned";
296  sstr << ' ';
297  if (n==1)
298  sstr << "char";
299  else
300  sstr << "integer";
301  }
302  else
303  sstr << "float";
304  }
305  else {
306  if (typeid(S) == typeid(bool))
307  sstr << "bool";
308  else if (n==0)
309  sstr << "void"; // "uninitialized";
310  else
311  sstr << "non-numeric";
312  }
313  sstr << " (" << (8 * n) << "b)";
314  s = sstr.str();
315  }
316 
317  return s;
318 
319  }
320 
321 
322 
323 };
324 
325 // Experimental template exercise... (works ok)
363 class nameGetter {
365 
366 public:
367 
368  typedef const char * value_t;
369 
370  template <class S, class T>
371  static inline
372  T callback(){
373  return typeid(S).name();
374  }
375 
376 };
377 
378 /*
379  * Usage:
380  *
381  * Type::call<drain::typeIsFundamental>(t)
382  *
383  */
385 
386 public:
387 
388  typedef bool value_t;
389 
394  template <class S, class T>
395  static inline
396  T callback(){ return std::is_fundamental<S>::value; }
397 
398 };
399 
403 class isSigned { // F2
404 
405 public:
406 
407  typedef bool value_t;
408 
413  template <class S, class T>
414  static inline
415  T callback(){
416  return static_cast<T>( std::numeric_limits<S>::is_signed);
417  }
418 
419 };
420 
421 
423 
430 
431 public:
432 
433  typedef bool value_t;
434 
439  template <class S, class T>
440  static inline
441  T callback(){ return std::numeric_limits<S>::is_specialized; }
442 
443 };
444 
450 class typeIsInteger { // F2
451 
452 public:
453 
454  typedef bool value_t;
455 
460  template <class S, class T>
461  static inline
462  T callback(){ return std::numeric_limits<S>::is_integer; }
463 
464 };
465 
471 class typeIsFloat { // F2
472 
473 public:
474 
475  typedef bool value_t;
476 
481  template <class S, class T>
482  static inline
483  T callback(){
484  return (typeid(S)==typeid(float)) || (typeid(S)==typeid(double));
485  //return std::numeric_limits<S>::is_float;
486  }
487  // { return (typeid(S)==typeid(float)) || (typeid(S)==typeid(double)); }
488 
489 };
490 
491 
493 
500 
501 public:
502 
503  typedef bool value_t;
504 
509  template <class S, class D>
510  static inline
511  D callback(){
512  return (typeid(S) == typeid(char)) || (typeid(S) == typeid(unsigned char)) || (typeid(S) == typeid(short)) || (typeid(S) == typeid(unsigned short));
513  }
514 };
515 
516 
518 
521 template <class S>
522 struct typeLimits {
523 
524  static inline
525  long int getMinI(){
526  return static_cast<long int>(std::numeric_limits<S>::min());
527  }
528 
529  static inline
530  unsigned long int getMaxI(){
531  return static_cast<unsigned long int>(std::numeric_limits<S>::max());
532  }
533 
534  static inline
535  double getMaxF(){
536  return static_cast<double>(std::numeric_limits<S>::max());
537  }
538 
539 };
540 
541 
542 template <> inline long int typeLimits<void>::getMinI(){ return 0l; }
543 template <> inline unsigned long int typeLimits<void>::getMaxI(){ return 0l; }
544 template <> inline double typeLimits<void>::getMaxF(){ return 0.0; }
545 
546 template <> inline long int typeLimits<std::string>::getMinI(){ return 0l; }
547 template <> inline unsigned long int typeLimits<std::string>::getMaxI(){ return 0l; }
548 template <> inline double typeLimits<std::string>::getMaxF(){ return 0.0; }
549 
550 
552 
558 class typeMin {
559 
560 public:
561 
562  //typedef T value_t;
563 
568  template <class S, class D>
569  static inline
570  D callback(){
571  if (std::numeric_limits<S>::is_integer)
572  return static_cast<D>(+typeLimits<S>::getMinI());
573  else
574  return static_cast<D>(-typeLimits<S>::getMaxF());
575  }
576 };
577 
578 
580 
586 class typeMax {
587 
588 public:
589 
590  //typedef T value_t;
591 
596  template <class S, class D>
597  static inline
598  D callback(){
599  if (std::numeric_limits<S>::is_integer)
600  return static_cast<D>(+typeLimits<S>::getMaxI());
601  else
602  return static_cast<D>(+typeLimits<S>::getMaxF());
603  }
604 };
605 
607 
616 
617 public:
618 
619  typedef double value_t;
620 
625  template <class S, class D>
626  static inline
627  D callback(){
628  if (typeIsSmallInt::callback<S,bool>())
629  return static_cast<D>(typeLimits<S>::getMaxI());
630  else
631  return static_cast<D>(1.0);
632  }
633 };
634 
635 
637 
651 // THIS WORKS WELL!
652 template <class D>
653 class typeLimiter {
654 
655 public:
656 
658  typedef D (*value_t)(D);
659 
664  template <class S, class T>
665  static inline
666  T callback(){
667  if (std::numeric_limits<S>::is_integer)
668  return &typeLimiter<D>::limitInteger<S,D>;
669  else
670  return &typeLimiter<D>::limitFloat<S,D>;
671  }
672 
673 
674 protected:
675 
677 
683  template <class S, class T>
684  static
685  T limitInteger(T x){
686 
687  static const T minValue = static_cast<T>(typeLimits<S>::getMinI());
688  static const T maxValue = static_cast<T>(typeLimits<S>::getMaxI());
689  if (x < minValue)
690  return minValue;
691  else if (x > maxValue)
692  return maxValue;
693 
694  return x;
695  }
696 
698 
702  template <class S, class T>
703  static
704  T limitFloat(T x){
705 
706  static const T maxValue = static_cast<T>(typeLimits<S>::getMaxF());
707  // notice minus sign
708  if (x < -maxValue)
709  return -maxValue;
710  else if (x > maxValue)
711  return maxValue;
712 
713  return x;
714  }
715 
716 
717 
718 };
719 
720 
721 
722 } // drain::
723 
724 #endif /* TypeUTILS_H_ */
Definition: RegExp.h:58
Returns the basic type (integer, float, bool, string, void) as a string.
Definition: TypeUtils.h:219
static T callback()
Definition: TypeUtils.h:231
Definition: TypeUtils.h:269
static T callback()
Definition: TypeUtils.h:282
Definition: TypeUtils.h:403
static T callback()
Definition: TypeUtils.h:415
Returns the sizeof() of a type. Accepts void (and returns size 0), which is not supported by std::num...
Definition: TypeUtils.h:138
static T callback()
Definition: TypeUtils.h:150
Definition: TypeUtils.h:471
static T callback()
Definition: TypeUtils.h:483
Definition: TypeUtils.h:384
static T callback()
Definition: TypeUtils.h:396
Definition: TypeUtils.h:450
static T callback()
Definition: TypeUtils.h:462
Checks if type is numeric.
Definition: TypeUtils.h:429
static T callback()
Definition: TypeUtils.h:441
The maximum value of a type given as type_info, char or std::string.
Definition: TypeUtils.h:499
static D callback()
Definition: TypeUtils.h:511
Class for ensuring that variable of type D remains within limits of type S.
Definition: TypeUtils.h:653
static T limitFloat(T x)
Definition: TypeUtils.h:704
static T limitInteger(T x)
Definition: TypeUtils.h:685
D(* value_t)(D)
Definition that simplifies.
Definition: TypeUtils.h:658
static T callback()
Definition: TypeUtils.h:666
The maximum value of a type given as type_info, char or std::string.
Definition: TypeUtils.h:586
static D callback()
Definition: TypeUtils.h:598
The minimum value of a type given as type_info, char or std::string.
Definition: TypeUtils.h:558
static D callback()
Definition: TypeUtils.h:570
The maximum value of a.
Definition: TypeUtils.h:615
static D callback()
Definition: TypeUtils.h:627
Utility for implementing setType(const std::type_info &t) in classes supporting setType<T>().
Definition: TypeUtils.h:114
static void callback(T &target)
Definition: TypeUtils.h:123
Definition: DataSelector.cpp:1277
Definition: TypeUtils.h:46
static const std::type_info & guessArrayType(const C &container)
Given a vector or list of strings, suggest a matching storage type (int, double, std::string).
Definition: TypeUtils.h:81
static const std::type_info & guessType(const std::string &value)
Given a string, check if it could be stored as int or double instead of std::string .
Definition: TypeUtils.cpp:49
Definition: TypeUtils.h:522