Loading...
Searching...
No Matches
TypeUtils.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31
32#ifndef DRAIN_TYPE_UTILS
33#define DRAIN_TYPE_UTILS
34
35#include <cmath>
36#include <limits>
37#include <set>
38#include <typeinfo>
39
40
41#include "Type.h"
42#include "RegExp.h"
43
44namespace drain {
45
46
47
49
52template <class S>
53struct typeLimits {
54
55 static inline
56 long int getMinI(){
57 return static_cast<long int>(std::numeric_limits<S>::min());
58 }
59
60 static inline
61 unsigned long int getMaxI(){
62 return static_cast<unsigned long int>(std::numeric_limits<S>::max());
63 }
64
65 static inline
66 double getMaxF(){
67 return static_cast<double>(std::numeric_limits<S>::max());
68 }
69
70};
71
72
73template <> inline long int typeLimits<void>::getMinI(){ return 0l; }
74template <> inline unsigned long int typeLimits<void>::getMaxI(){ return 0l; }
75template <> inline double typeLimits<void>::getMaxF(){ return 0.0; }
76
77template <> inline long int typeLimits<std::string>::getMinI(){ return 0l; }
78template <> inline unsigned long int typeLimits<std::string>::getMaxI(){ return 0l; }
79template <> inline double typeLimits<std::string>::getMaxF(){ return 0.0; }
80
82
96// THIS WORKS WELL!
97template <class D>
99
100public:
101
103 typedef D (*value_t)(D);
104
109 template <class S, class T>
110 static inline
112 if (std::numeric_limits<S>::is_integer)
113 return &typeLimiter<D>::limitInteger<S,D>;
114 else
115 return &typeLimiter<D>::limitFloat<S,D>;
116 }
117
118
119protected:
120
122
128 template <class S, class T>
129 static
131
132 static const T minValue = static_cast<T>(typeLimits<S>::getMinI());
133 static const T maxValue = static_cast<T>(typeLimits<S>::getMaxI());
134 if (x < minValue)
135 return minValue;
136 else if (x > maxValue)
137 return maxValue;
138
139 return x;
140 }
141
143
147 template <class S, class T>
148 static
150
151 static const T maxValue = static_cast<T>(typeLimits<S>::getMaxF());
152 // notice minus sign
153 if (x < -maxValue)
154 return -maxValue;
155 else if (x > maxValue)
156 return maxValue;
157
158 return x;
159 }
160
161
162
163};
164
165struct TypeUtils {
166
167
169
172 static
173 const std::type_info & guessType(const std::string & value);
174
176
179 static
180 const std::type_info & guessType(double d, const std::type_info & type = typeid(unsigned char));
181
182
183
185
188 template <class C>
189 static
190 const std::type_info & guessArrayType(const C & container);
191
192
197 template <typename T, typename S>
198 static inline
199 bool isWithinRange(const S & x){
200 // Call limit(), eg. check if 352 stays within [0,256[
201 return (Type::call<typeLimiter<S> >(typeid(T))(x) == x);
202 }
203
208 template <typename S>
209 static inline
210 bool isWithinRange(const S & x, const std::type_info & type){
211 // Call limit(), eg. check if 352 stays within uchar range [0,256[
212 return (Type::call<typeLimiter<S> >(type)(x) == x);
213 }
214
215 // * \tparam S - source type, typically with a large value range, double for example
216
218
222 template <typename T=unsigned char>
223 static inline
224 const std::type_info & minimizeIntType(double value){
225 // a bit clumsy, as calls Type::call().
226 return minimizeIntType(value, typeid(T));
227 }
228
230
234 static
235 const std::type_info & minimizeIntType(double value, const std::type_info & type = typeid(unsigned char));
236
237
238 static
239 const drain::RegExp trueRegExp; // ignore case
240
241 static
242 const drain::RegExp falseRegExp; // ignore case
243
244 // TODO: better whitespace
245 static
246 const drain::RegExp numeralRegExp;
247
248};
249
250
251
256/*
257template <typename T=unsigned char>
258const std::type_info & TypeUtils::minimizeIntType(double d){ // , const std::type_info & type = typeid(unsigned char)){
259
260 // const bool IS_INTEGER = (d == ::trunc(d));
261
262 if (d != ::trunc(d)){
263 return typeid(double); // later, also float option?
264 }
265
266
267 if (isWithinRange<T>(d)){
268 return typeid(T);
269 }
270
271 static const std::type_info & type = typeid(T);
272
273 // Type::call<isSigned>(type)
274 // Later, directly "inline" through type specification ?
275 if (std::numeric_limits<T>::is_signed){
276 // throw std::runtime_error(StringBuilder<' '>(__FUNCTION__, " requested signed type: ", TypeName<T>::str()));
277 if (&type == &typeid(signed char)){
278 return minimizeIntType<signed short>(d);
279 }
280 else if (&type == &typeid(signed short)){
281 return minimizeIntType<signed int>(d);
282 }
283 else if (&type == &typeid(signed int)){
284 return minimizeIntType<signed long>(d);
285 }
286 }
287 else {
288 if (&type == &typeid(unsigned char)){
289 return minimizeIntType<unsigned short>(d);
290 }
291 else if (&type == &typeid(unsigned short)){
292 return minimizeIntType<unsigned int>(d);
293 }
294 else if (&type == &typeid(unsigned int)){
295 return minimizeIntType<unsigned long>(d);
296 }
297 }
298
299 return typeid(double);
300
301}
302*/
303
304
305
306/*
307 * \tparam C - contrainer, esp. std::list or std::vector
308 */
309template <class C>
310const std::type_info & TypeUtils::guessArrayType(const C & l){
311
312
313 typedef std::set<const std::type_info *> typeset;
314
315 typeset s;
316 for (typename C::const_iterator it = l.begin(); it != l.end(); ++it) {
317 s.insert(& guessType(*it));
318 }
319
321 if (s.find(& typeid(std::string)) != s.end())
322 return typeid(std::string);
323
325 if (s.find(& typeid(double)) != s.end())
326 return typeid(double);
327
328 if (s.find(& typeid(int)) != s.end())
329 return typeid(int);
330
332 if (s.find(& typeid(bool)) != s.end())
333 return typeid(bool);
334
335 // General fallback solution
336 return typeid(std::string);
337
338}
339
340
341
343
345public:
346
351 template <class S, class T>
352 static
353 void callback(T & target){
354 target.template setType<S>();
355 }
356};
357
358
360
369
370public:
371
372 typedef std::size_t value_t;
373
378 template <class S, class T>
379 static inline
381 return static_cast<T>(getSize<S>()); // static cast unneeded in these ?
382 }
383
384protected:
385
386 // Must be here to get template<void> implemented
387 template <class S>
388 static inline
389 size_t getSize(){
390 return sizeof(S);
391 }
392
393};
394
395template <>
396inline
397size_t sizeGetter::getSize<void>(){
398 return 0;
399}
400// todo:: std::string?
401
402
403
404
405
406
407
409
414
415public:
416
417 typedef const std::string & value_t;
418
423 template <class S, class T>
424 static
426
427 static std::string s;
428
429 if (s.empty()){
430 std::stringstream sstr;
431 size_t n = sizeGetter::callback<S, std::size_t>();
432 if (std::numeric_limits<S>::is_specialized){
433 if (std::numeric_limits<S>::is_integer){
434 if (!std::numeric_limits<S>::is_signed)
435 sstr << 'u';
436 // sstr << ' ';
437 if (n==1)
438 sstr << "char";
439 else
440 sstr << "int";
441 }
442 else
443 sstr << "float";
444 }
445 else {
446 if (typeid(S) == typeid(bool))
447 sstr << "bool";
448 else if (n==0)
449 sstr << "void";
450 else
451 sstr << "other"; // pointer, for example?
452 }
453 //sstr << (8 * n);
454 s = sstr.str();
455 }
456
457 return s;
458
459 }
460
461};
462
464
465public:
466
467 //typedef std::string value_t;
468 typedef const std::string & value_t;
469
474 template <class S, class T>
475 static
477 // typedef std::numeric_limits<S> nlim;
478 // return numInfo<nlim::is_specialized, nlim::is_integer, nlim::is_signed>::s;
479 static std::string s;
480
481 if (s.empty()){
482 std::stringstream sstr;
483 size_t n = sizeGetter::callback<S, std::size_t>();
484 if (std::numeric_limits<S>::is_specialized){
485 if (std::numeric_limits<S>::is_integer){
486 if (std::numeric_limits<S>::is_signed)
487 sstr << "signed";
488 else
489 sstr << "unsigned";
490 sstr << ' ';
491 if (n==1)
492 sstr << "char";
493 else
494 sstr << "integer";
495 }
496 else
497 sstr << "float";
498 }
499 else {
500 if (typeid(S) == typeid(bool))
501 sstr << "bool";
502 else if (n==0)
503 sstr << "void"; // "uninitialized";
504 else
505 sstr << "non-numeric";
506 }
507 sstr << " (" << (8 * n) << "b)";
508 s = sstr.str();
509 }
510
511 return s;
512
513 }
514
515
516
517};
518
519
520
521
524
525public:
526
527 typedef const char * value_t;
528
529 template <class S, class T>
530 static inline
531 T callback(){
532 return typeid(S).name();
533 }
534
535};
536
537/*
538 * Usage:
539 *
540 * Type::call<drain::typeIsFundamental>(t)
541 *
542 */
544
545public:
546
547 typedef bool value_t;
548
553 template <class S, class T>
554 static inline
555 T callback(){ return std::is_fundamental<S>::value; }
556
557};
558
562class isSigned { // F2
563
564public:
565
566 typedef bool value_t;
567
572 template <class S, class T>
573 static inline
575 return static_cast<T>( std::numeric_limits<S>::is_signed);
576 }
577
578};
579
580
582
589
590public:
591
592 typedef bool value_t;
593
598 template <class S, class T>
599 static inline
600 T callback(){ return std::numeric_limits<S>::is_specialized; }
601
602};
603
609class typeIsInteger { // F2
610
611public:
612
613 typedef bool value_t;
614
619 template <class S, class T>
620 static inline
621 T callback(){ return std::numeric_limits<S>::is_integer; }
622
623};
624
630class typeIsFloat { // F2
631
632public:
633
634 typedef bool value_t;
635
640 template <class S, class T>
641 static inline
643 return (typeid(S)==typeid(float)) || (typeid(S)==typeid(double));
644 //return std::numeric_limits<S>::is_float;
645 }
646 // { return (typeid(S)==typeid(float)) || (typeid(S)==typeid(double)); }
647
648};
649
650
652
659
660public:
661
662 typedef bool value_t;
663
668 template <class S, class D>
669 static inline
671 return (typeid(S) == typeid(char)) || (typeid(S) == typeid(unsigned char)) || (typeid(S) == typeid(short)) || (typeid(S) == typeid(unsigned short));
672 }
673};
674
675
676
677
679
685class typeMin {
686
687public:
688
689 //typedef T value_t;
690
695 template <class S, class D>
696 static inline
698 if (std::numeric_limits<S>::is_integer)
699 return static_cast<D>(+typeLimits<S>::getMinI());
700 else
701 return static_cast<D>(-typeLimits<S>::getMaxF());
702 }
703};
704
705
707
713class typeMax {
714
715public:
716
717 //typedef T value_t;
718
723 template <class S, class D>
724 static inline
726 if (std::numeric_limits<S>::is_integer)
727 return static_cast<D>(+typeLimits<S>::getMaxI());
728 else
729 return static_cast<D>(+typeLimits<S>::getMaxF());
730 }
731};
732
734
743
744public:
745
746 typedef double value_t;
747
752 template <class S, class D>
753 static inline
755 if (typeIsSmallInt::callback<S,bool>())
756 return static_cast<D>(typeLimits<S>::getMaxI());
757 else
758 return static_cast<D>(1.0);
759 }
760};
761
762
763
764// Experimental template exercise... (works ok)
801} // drain::
802
803#endif /* TypeUTILS_H_ */
Definition RegExp.h:58
static T call(const std::type_info &t)
Calls a static function that has no parameters.
Definition Type.h:224
Returns the basic type (integer, float, bool, string, void) as a string.
Definition TypeUtils.h:413
static T callback()
Definition TypeUtils.h:425
Definition TypeUtils.h:463
static T callback()
Definition TypeUtils.h:476
Definition TypeUtils.h:562
static T callback()
Definition TypeUtils.h:574
Returns the compiler specific ie. non-standard name of the type.
Definition TypeUtils.h:523
Returns the sizeof() of a type. Accepts void (and returns size 0), which is not supported by std::num...
Definition TypeUtils.h:368
static T callback()
Definition TypeUtils.h:380
Definition TypeUtils.h:630
static T callback()
Definition TypeUtils.h:642
Definition TypeUtils.h:543
static T callback()
Definition TypeUtils.h:555
Definition TypeUtils.h:609
static T callback()
Definition TypeUtils.h:621
Checks if type is numeric.
Definition TypeUtils.h:588
static T callback()
Definition TypeUtils.h:600
The maximum value of a type given as type_info, char or std::string.
Definition TypeUtils.h:658
static D callback()
Definition TypeUtils.h:670
Class for ensuring that variable of type D remains within limits of type S.
Definition TypeUtils.h:98
static T limitFloat(T x)
Definition TypeUtils.h:149
static T limitInteger(T x)
Definition TypeUtils.h:130
D(* value_t)(D)
Definition that simplifies.
Definition TypeUtils.h:103
static T callback()
Definition TypeUtils.h:111
The maximum value of a type given as type_info, char or std::string.
Definition TypeUtils.h:713
static D callback()
Definition TypeUtils.h:725
The minimum value of a type given as type_info, char or std::string.
Definition TypeUtils.h:685
static D callback()
Definition TypeUtils.h:697
The maximum value of a.
Definition TypeUtils.h:742
static D callback()
Definition TypeUtils.h:754
Utility for implementing setType(const std::type_info &t) in classes supporting setType<T>().
Definition TypeUtils.h:344
static void callback(T &target)
Definition TypeUtils.h:353
Definition DataSelector.cpp:1277
Definition TypeUtils.h:165
static const std::type_info & guessType(double d, const std::type_info &type=typeid(unsigned char))
Returns the (loosely) minimal type that could store the value without precision loss.
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:310
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:52
static const std::type_info & minimizeIntType(double value)
Return a minimal numeric type, that can contain a numeric value.
Definition TypeUtils.h:224
static bool isWithinRange(const S &x, const std::type_info &type)
Definition TypeUtils.h:210
static bool isWithinRange(const S &x)
Definition TypeUtils.h:199
Definition TypeUtils.h:53