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//DRAIN_TYPENAME_T(std::initializer_list, T);
48//DRAIN_TYPENAME_T(std::vector, T);
49
51
54template <class S>
55struct typeLimits {
56
57 static inline
58 long int getMinI(){
59 return static_cast<long int>(std::numeric_limits<S>::min());
60 }
61
62 static inline
63 unsigned long int getMaxI(){
64 return static_cast<unsigned long int>(std::numeric_limits<S>::max());
65 }
66
67 static inline
68 double getMaxF(){
69 return static_cast<double>(std::numeric_limits<S>::max());
70 }
71
72};
73
74
75template <> inline long int typeLimits<void>::getMinI(){ return 0l; }
76template <> inline unsigned long int typeLimits<void>::getMaxI(){ return 0l; }
77template <> inline double typeLimits<void>::getMaxF(){ return 0.0; }
78
79template <> inline long int typeLimits<std::string>::getMinI(){ return 0l; }
80template <> inline unsigned long int typeLimits<std::string>::getMaxI(){ return 0l; }
81template <> inline double typeLimits<std::string>::getMaxF(){ return 0.0; }
82
84
98// THIS WORKS WELL!
99template <class D>
101
102public:
103
105 typedef D (*value_t)(D);
106
111 template <class S, class T>
112 static inline
114 if (std::numeric_limits<S>::is_integer)
115 return &typeLimiter<D>::limitInteger<S,D>;
116 else
117 return &typeLimiter<D>::limitFloat<S,D>;
118 }
119
120
121protected:
122
124
130 template <class S, class T>
131 static
133
134 static const T minValue = static_cast<T>(typeLimits<S>::getMinI());
135 static const T maxValue = static_cast<T>(typeLimits<S>::getMaxI());
136 if (x < minValue)
137 return minValue;
138 else if (x > maxValue)
139 return maxValue;
140
141 return x;
142 }
143
145
149 template <class S, class T>
150 static
152
153 static const T maxValue = static_cast<T>(typeLimits<S>::getMaxF());
154 // notice minus sign
155 if (x < -maxValue)
156 return -maxValue;
157 else if (x > maxValue)
158 return maxValue;
159
160 return x;
161 }
162
163
164
165};
166
167struct TypeUtils {
168
169
171
174 static
175 const std::type_info & guessType(const std::string & value);
176
178
181 static
182 const std::type_info & guessType(double d, const std::type_info & type = typeid(unsigned char));
183
184
185
187
190 template <class C>
191 static
192 const std::type_info & guessArrayType(const C & container);
193
194
199 template <typename T, typename S>
200 static inline
201 bool isWithinRange(const S & x){
202 // Call limit(), eg. check if 352 stays within [0,256[
203 return (Type::call<typeLimiter<S> >(typeid(T))(x) == x);
204 }
205
210 template <typename S>
211 static inline
212 bool isWithinRange(const S & x, const std::type_info & type){
213 // Call limit(), eg. check if 352 stays within uchar range [0,256[
214 return (Type::call<typeLimiter<S> >(type)(x) == x);
215 }
216
217 // * \tparam S - source type, typically with a large value range, double for example
218
220
224 template <typename T=unsigned char>
225 static inline
226 const std::type_info & minimizeIntType(double value){
227 // a bit clumsy, as calls Type::call().
228 return minimizeIntType(value, typeid(T));
229 }
230
232
236 static
237 const std::type_info & minimizeIntType(double value, const std::type_info & type = typeid(unsigned char));
238
239
240 static
241 const drain::RegExp trueRegExp; // ignore case
242
243 static
244 const drain::RegExp falseRegExp; // ignore case
245
246 // TODO: better whitespace
247 static
248 const drain::RegExp numeralRegExp;
249
250};
251
252
253
258/*
259template <typename T=unsigned char>
260const std::type_info & TypeUtils::minimizeIntType(double d){ // , const std::type_info & type = typeid(unsigned char)){
261
262 // const bool IS_INTEGER = (d == ::trunc(d));
263
264 if (d != ::trunc(d)){
265 return typeid(double); // later, also float option?
266 }
267
268
269 if (isWithinRange<T>(d)){
270 return typeid(T);
271 }
272
273 static const std::type_info & type = typeid(T);
274
275 // Type::call<isSigned>(type)
276 // Later, directly "inline" through type specification ?
277 if (std::numeric_limits<T>::is_signed){
278 // throw std::runtime_error(StringBuilder<' '>(__FUNCTION__, " requested signed type: ", TypeName<T>::str()));
279 if (&type == &typeid(signed char)){
280 return minimizeIntType<signed short>(d);
281 }
282 else if (&type == &typeid(signed short)){
283 return minimizeIntType<signed int>(d);
284 }
285 else if (&type == &typeid(signed int)){
286 return minimizeIntType<signed long>(d);
287 }
288 }
289 else {
290 if (&type == &typeid(unsigned char)){
291 return minimizeIntType<unsigned short>(d);
292 }
293 else if (&type == &typeid(unsigned short)){
294 return minimizeIntType<unsigned int>(d);
295 }
296 else if (&type == &typeid(unsigned int)){
297 return minimizeIntType<unsigned long>(d);
298 }
299 }
300
301 return typeid(double);
302
303}
304*/
305
306
307
308/*
309 * \tparam C - contrainer, esp. std::list or std::vector
310 */
311template <class C>
312const std::type_info & TypeUtils::guessArrayType(const C & l){
313
314
315 typedef std::set<const std::type_info *> typeset;
316
317 typeset s;
318 for (typename C::const_iterator it = l.begin(); it != l.end(); ++it) {
319 s.insert(& guessType(*it));
320 }
321
323 if (s.find(& typeid(std::string)) != s.end())
324 return typeid(std::string);
325
327 if (s.find(& typeid(double)) != s.end())
328 return typeid(double);
329
330 if (s.find(& typeid(int)) != s.end())
331 return typeid(int);
332
334 if (s.find(& typeid(bool)) != s.end())
335 return typeid(bool);
336
337 // General fallback solution
338 return typeid(std::string);
339
340}
341
342
343
346public:
347
352 template <class S, class T>
353 static
354 void callback(T & target){
355 target.template setType<S>();
356 }
357};
358
359
361
370
371public:
372
373 typedef std::size_t value_t;
374
379 template <class S, class T>
380 static inline
382 return static_cast<T>(getSize<S>()); // static cast unneeded in these ?
383 }
384
385protected:
386
387 // Must be here to get template<void> implemented
388 template <class S>
389 static inline
390 size_t getSize(){
391 return sizeof(S);
392 }
393
394};
395
396template <>
397inline
398size_t sizeGetter::getSize<void>(){
399 return 0;
400}
401// todo:: std::string?
402
403
404
405
406
407
408
410
415
416public:
417
418 typedef const std::string & value_t;
419
424 template <class S, class T>
425 static
427
428 static std::string s;
429
430 if (s.empty()){
431 std::stringstream sstr;
432 size_t n = sizeGetter::callback<S, std::size_t>();
433 if (std::numeric_limits<S>::is_specialized){
434 if (std::numeric_limits<S>::is_integer){
435 if (!std::numeric_limits<S>::is_signed)
436 sstr << 'u';
437 // sstr << ' ';
438 if (n==1)
439 sstr << "char";
440 else
441 sstr << "int";
442 }
443 else
444 sstr << "float";
445 }
446 else {
447 if (typeid(S) == typeid(bool))
448 sstr << "bool";
449 else if (n==0)
450 sstr << "void";
451 else
452 sstr << "other"; // pointer, for example?
453 }
454 //sstr << (8 * n);
455 s = sstr.str();
456 }
457
458 return s;
459
460 }
461
462};
463
465
466public:
467
468 //typedef std::string value_t;
469 typedef const std::string & value_t;
470
475 template <class S, class T>
476 static
478 // typedef std::numeric_limits<S> nlim;
479 // return numInfo<nlim::is_specialized, nlim::is_integer, nlim::is_signed>::s;
480 static std::string s;
481
482 if (s.empty()){
483 std::stringstream sstr;
484 size_t n = sizeGetter::callback<S, std::size_t>();
485 if (std::numeric_limits<S>::is_specialized){
486 if (std::numeric_limits<S>::is_integer){
487 if (std::numeric_limits<S>::is_signed)
488 sstr << "signed";
489 else
490 sstr << "unsigned";
491 sstr << ' ';
492 if (n==1)
493 sstr << "char";
494 else
495 sstr << "integer";
496 }
497 else
498 sstr << "float";
499 }
500 else {
501 if (typeid(S) == typeid(bool))
502 sstr << "bool";
503 else if (n==0)
504 sstr << "void"; // "uninitialized";
505 else
506 sstr << "non-numeric";
507 }
508 sstr << " (" << (8 * n) << "b)";
509 s = sstr.str();
510 }
511
512 return s;
513
514 }
515
516
517
518};
519
520
521
522
525
526public:
527
528 typedef const char * value_t;
529
530 template <class S, class T>
531 static inline
532 T callback(){
533 return typeid(S).name();
534 }
535
536};
537
538/*
539 * Usage:
540 *
541 * Type::call<drain::typeIsFundamental>(t)
542 *
543 */
545
546public:
547
548 typedef bool value_t;
549
554 template <class S, class T>
555 static inline
556 T callback(){ return std::is_fundamental<S>::value; }
557
558};
559
563class isSigned { // F2
564
565public:
566
567 typedef bool value_t;
568
573 template <class S, class T>
574 static inline
576 return static_cast<T>( std::numeric_limits<S>::is_signed);
577 }
578
579};
580
581
583
590
591public:
592
593 typedef bool value_t;
594
599 template <class S, class T>
600 static inline
601 T callback(){ return std::numeric_limits<S>::is_specialized; }
602
603};
604
610class typeIsInteger { // F2
611
612public:
613
614 typedef bool value_t;
615
620 template <class S, class T>
621 static inline
622 T callback(){ return std::numeric_limits<S>::is_integer; }
623
624};
625
631class typeIsFloat { // F2
632
633public:
634
635 typedef bool value_t;
636
641 template <class S, class T>
642 static inline
644 return (typeid(S)==typeid(float)) || (typeid(S)==typeid(double));
645 //return std::numeric_limits<S>::is_float;
646 }
647 // { return (typeid(S)==typeid(float)) || (typeid(S)==typeid(double)); }
648
649};
650
651
653
660
661public:
662
663 typedef bool value_t;
664
669 template <class S, class D>
670 static inline
672 return (typeid(S) == typeid(char)) || (typeid(S) == typeid(unsigned char)) || (typeid(S) == typeid(short)) || (typeid(S) == typeid(unsigned short));
673 }
674};
675
676
677
678
680
686class typeMin {
687
688public:
689
690 //typedef T value_t;
691
696 template <class S, class D>
697 static inline
699 if (std::numeric_limits<S>::is_integer)
700 return static_cast<D>(+typeLimits<S>::getMinI());
701 else
702 return static_cast<D>(-typeLimits<S>::getMaxF());
703 }
704};
705
706
708
714class typeMax {
715
716public:
717
718 //typedef T value_t;
719
724 template <class S, class D>
725 static inline
727 if (std::numeric_limits<S>::is_integer)
728 return static_cast<D>(+typeLimits<S>::getMaxI());
729 else
730 return static_cast<D>(+typeLimits<S>::getMaxF());
731 }
732};
733
735
744
745public:
746
747 typedef double value_t;
748
753 template <class S, class D>
754 static inline
756 if (typeIsSmallInt::callback<S,bool>())
757 return static_cast<D>(typeLimits<S>::getMaxI());
758 else
759 return static_cast<D>(1.0);
760 }
761};
762
763
764
765// Experimental template exercise... (works ok)
802} // drain::
803
804#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:222
Returns the basic type (integer, float, bool, string, void) as a string.
Definition TypeUtils.h:414
static T callback()
Definition TypeUtils.h:426
Definition TypeUtils.h:464
static T callback()
Definition TypeUtils.h:477
Definition TypeUtils.h:563
static T callback()
Definition TypeUtils.h:575
Returns the compiler specific ie. non-standard name of the type.
Definition TypeUtils.h:524
Returns the sizeof() of a type. Accepts void (and returns size 0), which is not supported by std::num...
Definition TypeUtils.h:369
static T callback()
Definition TypeUtils.h:381
Definition TypeUtils.h:631
static T callback()
Definition TypeUtils.h:643
Definition TypeUtils.h:544
static T callback()
Definition TypeUtils.h:556
Definition TypeUtils.h:610
static T callback()
Definition TypeUtils.h:622
Checks if type is numeric.
Definition TypeUtils.h:589
static T callback()
Definition TypeUtils.h:601
The maximum value of a type given as type_info, char or std::string.
Definition TypeUtils.h:659
static D callback()
Definition TypeUtils.h:671
Class for ensuring that variable of type D remains within limits of type S.
Definition TypeUtils.h:100
static T limitFloat(T x)
Definition TypeUtils.h:151
static T limitInteger(T x)
Definition TypeUtils.h:132
D(* value_t)(D)
Definition that simplifies.
Definition TypeUtils.h:105
static T callback()
Definition TypeUtils.h:113
The maximum value of a type given as type_info, char or std::string.
Definition TypeUtils.h:714
static D callback()
Definition TypeUtils.h:726
The minimum value of a type given as type_info, char or std::string.
Definition TypeUtils.h:686
static D callback()
Definition TypeUtils.h:698
The maximum value of a.
Definition TypeUtils.h:743
static D callback()
Definition TypeUtils.h:755
Utility for implementing setType(const std::type_info &t) in classes supporting setType<T>().
Definition TypeUtils.h:345
static void callback(T &target)
Definition TypeUtils.h:354
Definition DataSelector.cpp:1277
Definition TypeUtils.h:167
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:312
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:226
static bool isWithinRange(const S &x, const std::type_info &type)
Definition TypeUtils.h:212
static bool isWithinRange(const S &x)
Definition TypeUtils.h:201
Definition TypeUtils.h:55