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