Loading...
Searching...
No Matches
Type.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#ifndef DRAIN_TYPE
32#define DRAIN_TYPE
33
34#include <iostream>
35#include <stdexcept>
36#include <typeinfo>
37
38#include <list>
39#include <set>
40#include <vector>
41
42
43
44namespace drain {
45
47
50class Type {
51public:
52
53 inline
54 Type() : currentType(&typeid(void)) { //, typeMin(0), typeMax(0) {
55 }
56
57 inline
58 Type(const Type & t) : currentType(t.currentType) { //, typeMin(t.typeMin), typeMax(t.typeMax) { // FIX 0 0
59 //std::cerr << __FUNCTION__ << "(const &)" << std::endl;
60 }
61
62 template <class T>
63 Type(const T & t) : currentType(&typeid(void)){
64 setType(t);
65 }
66
67
68 template <class T>
69 inline
70 void setType(){
71 //std::cerr << __FUNCTION__ << "<T>()" << std::endl;
72 currentType = & typeid(T);
73 }
74
75
77
80 template <class T>
81 inline
82 void setType(const T & t){
83 call<typeSetter>(*this, t);
84 }
85
86 // TODO for std::strings.
87 template <class T>
88 inline
89 Type & operator=(const T & t){
90 setType(t);
91 return *this;
92 }
93
94 inline
95 operator const std::type_info & () const {return (*currentType); }
96
97 inline
98 operator char () const {return getTypeChar(*currentType); }
99
100 inline
101 operator std::string () const {return std::string(1, getTypeChar(*currentType)); }
102
103
105 inline
106 const std::type_info & getType() const {
107 return *currentType;
108 }
109
110
112
131 static
132 inline
133 const std::type_info & getTypeInfo(char t){
134
135 switch (t) {
136 case 'c':
137 return typeid(char);
138 case 'C':
139 return typeid(unsigned char);
140 case 's':
141 return typeid(short);
142 case 'S':
143 return typeid(unsigned short);
144 case 'i':
145 return typeid(int);
146 case 'I':
147 return typeid(unsigned int);
148 case 'l':
149 return typeid(long);
150 case 'L':
151 return typeid(unsigned long);
152 case 'f':
153 return typeid(float);
154 case 'd':
155 return typeid(double);
156 case 'B':
157 return typeid(bool);
158 case '$': // deprecated?
159 case '#':
160 return typeid(std::string);
161 case '*':
162 return typeid(void);
163 default:
164 //Logger mout("Type", std::string(__FUNCTION__)+"(char c)");
165 //Logger mout(__FILE__, __FUNCTION__);
166 //mout.error(" undefined type: '" , t , "'=" , (int)t );
167 std::cerr << __FILE__ << ' ' << __FUNCTION__ << " undefined type: '" << t << "'=" << (int)t << std::endl;
168 //mout.error(" undefined type: '" , t , "'=" , (int)t );
169 throw std::runtime_error("undefined type");
170 return typeid(void);
171 }
172
173 }
174
175 static
176 inline
177 char getTypeChar(const std::type_info & t){
178 if (t == typeid(char))
179 return 'c';
180 else if (t == typeid(unsigned char))
181 return 'C';
182 else if (t == typeid(short))
183 return 's';
184 else if (t == typeid(unsigned short))
185 return 'S';
186 else if (t == typeid(int))
187 return 'i';
188 else if (t == typeid(unsigned int))
189 return 'I';
190 else if (t == typeid(long))
191 return 'l';
192 else if (t == typeid(unsigned long))
193 return 'L';
194 else if (t == typeid(float))
195 return 'f';
196 else if (t == typeid(double))
197 return 'd';
198 else if (t == typeid(bool))
199 return 'B';
200 else if (t == typeid(void))
201 return '*';
202 else if (t == typeid(std::string))
203 return '#';
204 else if (t == typeid(const char *))
205 return '#';
206 else if (t == typeid(char *))
207 return '#';
208 else {
209 return 'x'; // = "extension"
210 }
211 }
212
214
220 template <class F, class T>
221 static
222 T call(const std::type_info & t){ // ORIGINAL
223
224 //std::cout << "Calling call with " << t.name() << " (" << getTypeChar(t) << ")\n";
225 // NOTE: STL uses string comparison!!!
226 if (t == typeid(char)){
227 return F::template callback<char,T>();
228 }
229 else if (t == typeid(unsigned char)) {
230 return F::template callback<unsigned char,T>();
231 }
232 else if (t == typeid(int)) {
233 return F::template callback<int,T>();
234 }
235 else if (t == typeid(unsigned int)) {
236 return F::template callback<unsigned int,T>();
237 }
238 else if (t == typeid(short int)) {
239 return F::template callback<short int,T>();
240 }
241 else if (t == typeid(unsigned short int)) {
242 return F::template callback<unsigned short int,T>();
243 }
244 else if (t == typeid(long int)) {
245 return F::template callback<long int,T>();
246 }
247 else if (t == typeid(unsigned long int)) {
248 return F::template callback<unsigned long int,T>();
249 }
250 else if (t == typeid(float)) {
251 return F::template callback<float,T>();
252 }
253 else if (t == typeid(double)) {
254 return F::template callback<double,T>();
255 }
256 else if (t == typeid(bool)) {
257 return F::template callback<bool,T>();
258 }
259 else if (t == typeid(void)) {
260 return F::template callback<void,T>();
261 }
262 else if (t == typeid(std::string)) {
263 return F::template callback<std::string,T>();
264 }
265 /*
266 else if (Type::call<isEnum>(t)){ // NEW 2023
267 // Problem: looping if not enum...
268 return F::template callback<int,T>();
269 }
270 */
271 else {
272 std::cerr << __FILE__ << ' ' << __FUNCTION__ << "unimplemented type: ..." << t.name() << std::endl;
273 //mout.error(" undefined type: '" , t , "'=" , (int)t );
274 throw std::runtime_error("unimplemented type: ...");
275 //Logger mout(__FILE__, __FUNCTION__);
276 // mout.error("unimplemented type: ...", t.name(), " NOTE: enums suppressed");
277 //return T(); //F::template callback<char,T>();
278 // Problem with ref types
279 return F::template callback<char,T>();
280 }
281
282 }
283
285
290 template <class F, class D, class S>
291 static inline
292 D call(const S & typeCode){
293 return call<F,D>(getTypeInfo(typeCode));
294 }
295
297
303 template <class F, class S>
304 static inline
305 typename F::value_t call(const S & typeCode){
306 return call<F,typename F::value_t>(getTypeInfo(typeCode));
307 }
308
309
311
337 template <class F, class T>
338 static
339 void call(T & target, const std::type_info &t){ // const Type &type){
340
341 if (t == typeid(char))
342 F::template callback<char>(target);
343 else if (t == typeid(unsigned char))
344 F::template callback<unsigned char>(target);
345 else if (t == typeid(int))
346 F::template callback<int>(target);
347 else if (t == typeid(unsigned int))
348 F::template callback<unsigned int>(target);
349 else if (t == typeid(short))
350 F::template callback<short>(target);
351 else if (t == typeid(unsigned short))
352 F::template callback<unsigned short>(target);
353 else if (t == typeid(long))
354 F::template callback<long>(target);
355 else if (t == typeid(unsigned long))
356 F::template callback<unsigned long>(target);
357 else if (t == typeid(float))
358 F::template callback<float>(target);
359 else if (t == typeid(double))
360 F::template callback<double>(target);
361 else if (t == typeid(bool))
362 F::template callback<bool>(target);
363 else if (t == typeid(std::string))
364 F::template callback<std::string>(target);
365 else if (t == typeid(void)) {
366 F::template callback<void>(target);
367 }
368 /*
369 else if (Type::call<isEnum>(t)){
370 F::template callback<int>(target);
371 }
372 */
373 else {
374 std::cerr << __FILE__ << ' ' << __FUNCTION__ << "unimplemented type: ..." << t.name() << std::endl;
375 //mout.error(" undefined type: '" , t , "'=" , (int)t );
376 throw std::runtime_error("unimplemented type: ...");
377
378 //Logger mout(__FILE__, __FUNCTION__);
379 //mout.error("unimplemented type: ...", t.name(), " NOTE: enums suppressed");
380 // throw std::runtime_error(std::string(": unimplemented type: ") + t.name() + " NOTE: enums suppressed");
381 return;
382 }
383 }
384
386
395 template <class F, class T, class T2>
396 static
397 void call(T & target, const T2 &t){
398 call<F>(target, getTypeInfo(t));
399 }
400
401
402
404
407 static
408 inline
409 const std::type_info & getTypeInfo(const char *typeCode){
410 if ((typeCode != NULL) && (*typeCode != '\0'))
411 return getTypeInfo(*typeCode);
412 else if (typeCode == NULL)
413 return getTypeInfo('*');
414 else
415 throw std::runtime_error(std::string("Type::operator=, not unit-length std::string: ") + typeCode);
416 }
417
419
422 static
423 inline
424 const std::type_info & getTypeInfo(const std::string & typeCode){
425 if (typeCode.length() == 1)
426 return getTypeInfo(typeCode.at(0));
427 else if (typeCode.empty())
428 return getTypeInfo('*');
429 else
430 throw std::runtime_error(std::string("Type::operator=, not unit-length std::string: ") + typeCode);
431 }
432
434 static
435 inline
436 const std::type_info & getTypeInfo(const Type & t){
437 return t;
438 }
439
440 /*
441 static
442 const drain::RegExp trueRegExp;
443
444 static
445 const drain::RegExp falseRegExp;
446 */
447
449
452 /*
453 static
454 const std::type_info & guessType(const std::string & value);
455
457 template <class C>
458 static
459 const std::type_info & guessArrayType(const C & container);
460 */
461
462 static inline
463 std::ostream & toStream(std::ostream & ostr, const Type &t){
464 const std::type_info & type = t.getType();
465 ostr << Type::getTypeChar(type) << '@'; // << Type::call<drain::sizeGetter>(type);
466 return ostr;
467 }
468
469 static inline
470 std::ostream & toStreamFull(std::ostream & ostr, const Type &t){
471 toStream(ostr, t);
472 //const std::type_info & type = t.getType();
473 // ostr << ' '<< '(' << Type::getMin<double>(type) << ',' << Type::call<drain::typeMax,double>(type) << ')';
474 /*
475 if (isSigned(type)){
476 //if (true){
477 ostr << " +/-";
478 }
479 */
480 return ostr;
481 }
482
483 struct isEnum {
484
485 typedef bool value_t;
486
491 template <class S, class T>
492 static
494 return std::is_enum<S>::value;
495 }
496
497
498 };
499
500protected:
501
506 struct typeSetter {
507
512 template <class T>
513 static inline
514 void callback(Type & target){
515 //Logger mout(monitor, "Type", __FUNCTION__);
516 target.setType<T>();
517 }
518
519 };
520
521 const std::type_info *currentType;
522
523};
524
525
527inline
528std::ostream & operator<<(std::ostream & ostr, const Type &t){
529 Type::toStream(ostr, t);
530 return ostr;
531}
532
533
534
536/*
537
538*/
539template <typename T>
541{
542
543 static const std::string & str(){
544 return name;
545 }
546
547protected:
548
549 static const std::string name;
550
551};
552
554template <typename T>
555const std::string TypeName<T>::name(typeid(T).name());
556
558#define DRAIN_TYPENAME(tname) template <> const std::string TypeName<tname>::name
560#define DRAIN_TYPENAME_DEF(tname) template <> const std::string TypeName<tname>::name(#tname)
561
562//#define DRAIN_TYPENAME_T(cname,T) template <class T> struct TypeName<cname<T> > {static const std::string & str(){static const std::string n=drain::StringBuilder<>(#cname, '<', drain::TypeName<T>::str(),'>'); return name;}
563#define DRAIN_TYPENAME_T(cname,T) template <class T> struct TypeName<cname<T> > {static const std::string & str(){static const std::string n=drain::StringBuilder<>(#cname, '<', drain::TypeName<T>::str(),'>'); return n;}}
564
565
567// (Unless the string returned by typeid is sufficient.)
568
569
571DRAIN_TYPENAME(bool);
572DRAIN_TYPENAME(char);
573DRAIN_TYPENAME(unsigned char);
574DRAIN_TYPENAME(short);
575DRAIN_TYPENAME(unsigned short);
576DRAIN_TYPENAME(int);
577DRAIN_TYPENAME(unsigned int);
578DRAIN_TYPENAME(long);
579DRAIN_TYPENAME(unsigned long);
580DRAIN_TYPENAME(float);
581DRAIN_TYPENAME(double);
582DRAIN_TYPENAME(char *);
583DRAIN_TYPENAME(const char *); // why const separately...?
584DRAIN_TYPENAME(std::string);
585
586#define DRAIN_TYPENAME_T0(cname,T) template <class T> struct TypeName<cname<T> > {static const std::string & str(){static const std::string n=std::string(#cname)+'<'+drain::TypeName<T>::str()+'>'; return n;}}
587
588DRAIN_TYPENAME_T0(std::initializer_list, T);
589DRAIN_TYPENAME_T0(std::vector, T);
590
591/*
592template <typename T>
593struct TypeName<std::initializer_list<T> > {
594
595 static const std::string & str(){
596 static std::string name;
597 if (name.empty()){
598 name = "std::initializer_list<";
599 name += drain::TypeName<T>::str();
600 name += ">";
601 //name = drain::StringBuilder("std::initializer_list<", drain::TypeName<T>::get(), ">");
602 }
603 return name;
604 }
605
606};
607
608
609template <typename T>
610struct TypeName<std::vector<T> > {
611
612 static const std::string & str(){
613 static std::string name;
614 if (name.empty()){
615 name = "std::vector<"; // + drain::TypeName<T>::get() + ">";
616 name += drain::TypeName<T>::str();
617 name += ">";
618 }
619 return name;
620 }
621
622};
623*/
624
625/*
626namespace std {
627 template <typename K, typename V>
628 class map<K,V>;
629}
630*/
631
632
633
635
640
641public:
642
643 typedef std::string value_t;
644 // typedef const std::string & value_t;
645
650 template <class S, class T>
651 static
653 //return TypeName<S>::get();
654 return TypeName<S>::str();
655 }
656
657
658};
659
660
661
662} // drain::
663
664#endif
Utilities related to std::type_info.
Definition Type.h:50
static const std::type_info & getTypeInfo(const char *typeCode)
Returns the type corresponding to a single-character string.
Definition Type.h:409
static const std::type_info & getTypeInfo(const std::string &typeCode)
Returns the type corresponding to a single-character string.
Definition Type.h:424
static std::ostream & toStream(std::ostream &ostr, const Type &t)
Given a string, check if it could be stored as int or double instead of std::string .
Definition Type.h:463
static const std::type_info & getTypeInfo(const Type &t)
Convenience. Purpose is to have a full set of getTypeInfo commands for templated constructs.
Definition Type.h:436
static void call(T &target, const std::type_info &t)
Static function call without parameters on a single target of type T.
Definition Type.h:339
const std::type_info & getType() const
Deprecated! Use cast (above) instead?
Definition Type.h:106
void setType(const T &t)
Set current type to t.
Definition Type.h:82
static T call(const std::type_info &t)
Calls a static function that has no parameters.
Definition Type.h:222
static F::value_t call(const S &typeCode)
A shorthand for functors with a fixed return type, hence D = F::value_t.
Definition Type.h:305
static D call(const S &typeCode)
New, preferred implementation: a single if-then structure once and for all.
Definition Type.h:292
static void call(T &target, const T2 &t)
Static function call with a single parameter.
Definition Type.h:397
static const std::type_info & getTypeInfo(char t)
Returns the base type associated with a character key.
Definition Type.h:133
Returns the basic type (integer, float, bool, string, void) as a string.
Definition Type.h:639
static T callback()
Definition Type.h:652
Definition DataSelector.cpp:1277
DRAIN_TYPENAME(void)
Add a specialization for each type of those you want to support.
Default implementation.
Definition Type.h:541
static const std::string name
Default implementation: name returned by std::type_info::name()
Definition Type.h:549
Definition Type.h:483
static T callback()
Definition Type.h:493
Definition Type.h:506
static void callback(Type &target)
Definition Type.h:514