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// #include <bits/types.h> // uint8, uint16 etc
38
39
40
41
42namespace drain {
43
45
48class Type {
49public:
50
51 inline
52 Type() : currentType(&typeid(void)) { //, typeMin(0), typeMax(0) {
53 }
54
55 inline
56 Type(const Type & t) : currentType(t.currentType) { //, typeMin(t.typeMin), typeMax(t.typeMax) { // FIX 0 0
57 //std::cerr << __FUNCTION__ << "(const &)" << std::endl;
58 }
59
60 template <class T>
61 Type(const T & t) : currentType(&typeid(void)){
62 setType(t);
63 }
64
65
66 template <class T>
67 inline
68 void setType(){
69 //std::cerr << __FUNCTION__ << "<T>()" << std::endl;
70 currentType = & typeid(T);
71 }
72
73
75
78 template <class T>
79 inline
80 void setType(const T & t){
81 call<typeSetter>(*this, t);
82 }
83
84 // TODO for std::strings.
85 template <class T>
86 inline
87 Type & operator=(const T & t){
88 setType(t);
89 return *this;
90 }
91
92 inline
93 operator const std::type_info & () const {return (*currentType); }
94
95 inline
96 operator char () const {return getTypeChar(*currentType); }
97
98 inline
99 operator std::string () const {return std::string(1, getTypeChar(*currentType)); }
100
101
103 inline
104 const std::type_info & getType() const {
105 return *currentType;
106 }
107
108
110
129 static
130 inline
131 const std::type_info & getTypeInfo(char t){
132
133 switch (t) {
134 case 'c':
135 return typeid(char);
136 case 'C':
137 return typeid(unsigned char);
138 case 's':
139 return typeid(short);
140 case 'S':
141 return typeid(unsigned short);
142 case 'i':
143 return typeid(int);
144 case 'I':
145 return typeid(unsigned int);
146 case 'l':
147 return typeid(long);
148 case 'L':
149 return typeid(unsigned long);
150 case 'f':
151 return typeid(float);
152 case 'd':
153 return typeid(double);
154 case 'B':
155 return typeid(bool);
156 case '$': // deprecated?
157 case '#':
158 return typeid(std::string);
159 case '*':
160 return typeid(void);
161 default:
162 //Logger mout("Type", std::string(__FUNCTION__)+"(char c)");
163 //Logger mout(__FILE__, __FUNCTION__);
164 //mout.error(" undefined type: '" , t , "'=" , (int)t );
165 std::cerr << __FILE__ << ' ' << __FUNCTION__ << " undefined type: '" << t << "'=" << (int)t << std::endl;
166 //mout.error(" undefined type: '" , t , "'=" , (int)t );
167 throw std::runtime_error("undefined type");
168 return typeid(void);
169 }
170
171 }
172
173 static
174 inline
175 char getTypeChar(const std::type_info & t){
176 if (t == typeid(char))
177 return 'c';
178 else if (t == typeid(unsigned char))
179 return 'C';
180 else if (t == typeid(short))
181 return 's';
182 else if (t == typeid(unsigned short))
183 return 'S';
184 else if (t == typeid(int))
185 return 'i';
186 else if (t == typeid(unsigned int))
187 return 'I';
188 else if (t == typeid(long))
189 return 'l';
190 else if (t == typeid(unsigned long))
191 return 'L';
192 else if (t == typeid(float))
193 return 'f';
194 else if (t == typeid(double))
195 return 'd';
196 else if (t == typeid(bool))
197 return 'B';
198 else if (t == typeid(void))
199 return '*';
200 else if (t == typeid(std::string))
201 return '#';
202 else if (t == typeid(const char *))
203 return '#';
204 else if (t == typeid(char *))
205 return '#';
206 else {
207 return 'x'; // = "extension"
208 }
209 }
210
212
218 template <class F, class T>
219 static
220 T call(const std::type_info & t){ // ORIGINAL
221
222 //std::cout << "Calling call with " << t.name() << " (" << getTypeChar(t) << ")\n";
223 // NOTE: STL uses string comparison!!!
224 if (t == typeid(char)){
225 return F::template callback<char,T>();
226 }
227 else if (t == typeid(unsigned char)) {
228 return F::template callback<unsigned char,T>();
229 }
230 else if (t == typeid(int)) {
231 return F::template callback<int,T>();
232 }
233 else if (t == typeid(unsigned int)) {
234 return F::template callback<unsigned int,T>();
235 }
236 else if (t == typeid(short int)) {
237 return F::template callback<short int,T>();
238 }
239 else if (t == typeid(unsigned short int)) {
240 return F::template callback<unsigned short int,T>();
241 }
242 else if (t == typeid(long int)) {
243 return F::template callback<long int,T>();
244 }
245 else if (t == typeid(unsigned long int)) {
246 return F::template callback<unsigned long int,T>();
247 }
248 else if (t == typeid(float)) {
249 return F::template callback<float,T>();
250 }
251 else if (t == typeid(double)) {
252 return F::template callback<double,T>();
253 }
254 else if (t == typeid(bool)) {
255 return F::template callback<bool,T>();
256 }
257 else if (t == typeid(void)) {
258 return F::template callback<void,T>();
259 }
260 else if (t == typeid(std::string)) {
261 return F::template callback<std::string,T>();
262 }
263 /*
264 else if (Type::call<isEnum>(t)){ // NEW 2023
265 // Problem: looping if not enum...
266 return F::template callback<int,T>();
267 }
268 */
269 else {
270 std::cerr << __FILE__ << ' ' << __FUNCTION__ << "unimplemented type: ..." << t.name() << std::endl;
271 //mout.error(" undefined type: '" , t , "'=" , (int)t );
272 throw std::runtime_error("unimplemented type: ...");
273 //Logger mout(__FILE__, __FUNCTION__);
274 // mout.error("unimplemented type: ...", t.name(), " NOTE: enums suppressed");
275 //return T(); //F::template callback<char,T>();
276 // Problem with ref types
277 return F::template callback<char,T>();
278 }
279
280 }
281
283
288 template <class F, class D, class S>
289 static inline
290 D call(const S & typeCode){
291 return call<F,D>(getTypeInfo(typeCode));
292 }
293
295
301 template <class F, class S>
302 static inline
303 typename F::value_t call(const S & typeCode){
304 return call<F,typename F::value_t>(getTypeInfo(typeCode));
305 }
306
307
309
335 template <class F, class T>
336 static
337 void call(T & target, const std::type_info &t){ // const Type &type){
338
339 if (t == typeid(char))
340 F::template callback<char>(target);
341 else if (t == typeid(unsigned char))
342 F::template callback<unsigned char>(target);
343 else if (t == typeid(int))
344 F::template callback<int>(target);
345 else if (t == typeid(unsigned int))
346 F::template callback<unsigned int>(target);
347 else if (t == typeid(short))
348 F::template callback<short>(target);
349 else if (t == typeid(unsigned short))
350 F::template callback<unsigned short>(target);
351 else if (t == typeid(long))
352 F::template callback<long>(target);
353 else if (t == typeid(unsigned long))
354 F::template callback<unsigned long>(target);
355 else if (t == typeid(float))
356 F::template callback<float>(target);
357 else if (t == typeid(double))
358 F::template callback<double>(target);
359 else if (t == typeid(bool))
360 F::template callback<bool>(target);
361 else if (t == typeid(std::string))
362 F::template callback<std::string>(target);
363 else if (t == typeid(void)) {
364 F::template callback<void>(target);
365 }
366 /*
367 else if (Type::call<isEnum>(t)){
368 F::template callback<int>(target);
369 }
370 */
371 else {
372 std::cerr << __FILE__ << ' ' << __FUNCTION__ << "unimplemented type: ..." << t.name() << std::endl;
373 //mout.error(" undefined type: '" , t , "'=" , (int)t );
374 throw std::runtime_error("unimplemented type: ...");
375
376 //Logger mout(__FILE__, __FUNCTION__);
377 //mout.error("unimplemented type: ...", t.name(), " NOTE: enums suppressed");
378 // throw std::runtime_error(std::string(": unimplemented type: ") + t.name() + " NOTE: enums suppressed");
379 return;
380 }
381 }
382
384
393 template <class F, class T, class T2>
394 static
395 void call(T & target, const T2 &t){
396 call<F>(target, getTypeInfo(t));
397 }
398
399
400
402
405 static
406 inline
407 const std::type_info & getTypeInfo(const char *typeCode){
408 if ((typeCode != NULL) && (*typeCode != '\0'))
409 return getTypeInfo(*typeCode);
410 else if (typeCode == NULL)
411 return getTypeInfo('*');
412 else
413 throw std::runtime_error(std::string("Type::operator=, not unit-length std::string: ") + typeCode);
414 }
415
417
420 static
421 inline
422 const std::type_info & getTypeInfo(const std::string & typeCode){
423 if (typeCode.length() == 1)
424 return getTypeInfo(typeCode.at(0));
425 else if (typeCode.empty())
426 return getTypeInfo('*');
427 else
428 throw std::runtime_error(std::string("Type::operator=, not unit-length std::string: ") + typeCode);
429 }
430
432 static
433 inline
434 const std::type_info & getTypeInfo(const Type & t){
435 return t;
436 }
437
438 /*
439 static
440 const drain::RegExp trueRegExp;
441
442 static
443 const drain::RegExp falseRegExp;
444 */
445
447
450 /*
451 static
452 const std::type_info & guessType(const std::string & value);
453
455 template <class C>
456 static
457 const std::type_info & guessArrayType(const C & container);
458 */
459
460 static inline
461 std::ostream & toStream(std::ostream & ostr, const Type &t){
462 const std::type_info & type = t.getType();
463 ostr << Type::getTypeChar(type) << '@'; // << Type::call<drain::sizeGetter>(type);
464 return ostr;
465 }
466
467 static inline
468 std::ostream & toStreamFull(std::ostream & ostr, const Type &t){
469 toStream(ostr, t);
470 //const std::type_info & type = t.getType();
471 // ostr << ' '<< '(' << Type::getMin<double>(type) << ',' << Type::call<drain::typeMax,double>(type) << ')';
472 /*
473 if (isSigned(type)){
474 //if (true){
475 ostr << " +/-";
476 }
477 */
478 return ostr;
479 }
480
481 struct isEnum {
482
483 typedef bool value_t;
484
489 template <class S, class T>
490 static
492 return std::is_enum<S>::value;
493 }
494
495
496 };
497
498// protected:
499
504 //static
506
511 template <class T>
512 static inline
513 void callback(Type & target){
514 //Logger mout(monitor, "Type", __FUNCTION__);
515 target.setType<T>();
516 }
517
518 };
519
521 public:
522
527 template <class S, class T>
528 static
529 void callback(T & target){
530 target.template setType<S>();
531 }
532 };
533
534 const std::type_info *currentType;
535
536};
537
538
540inline
541std::ostream & operator<<(std::ostream & ostr, const Type &t){
542 Type::toStream(ostr, t);
543 return ostr;
544}
545
546
547#ifdef DRAIN_TYPENAME
549
553class simpleNameOLD{
554
555public:
556
557 typedef std::string value_t;
558
563 template <class S, class T>
564 static
565 T callback(){
566 return TypeName<S>::str();
567 }
568
569
570};
571#endif
572
573
574
575} // drain::
576
577#endif
Definition Type.h:520
static void callback(T &target)
Definition Type.h:529
Utilities related to std::type_info.
Definition Type.h:48
static const std::type_info & getTypeInfo(const char *typeCode)
Returns the type corresponding to a single-character string.
Definition Type.h:407
static const std::type_info & getTypeInfo(const std::string &typeCode)
Returns the type corresponding to a single-character string.
Definition Type.h:422
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:461
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:434
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:337
const std::type_info & getType() const
Deprecated! Use cast (above) instead?
Definition Type.h:104
void setType(const T &t)
Set current type to t.
Definition Type.h:80
static T call(const std::type_info &t)
Calls a static function that has no parameters.
Definition Type.h:220
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:303
static D call(const S &typeCode)
New, preferred implementation: a single if-then structure once and for all.
Definition Type.h:290
static void call(T &target, const T2 &t)
Static function call with a single parameter.
Definition Type.h:395
static const std::type_info & getTypeInfo(char t)
Returns the base type associated with a character key.
Definition Type.h:131
Definition DataSelector.cpp:1277
Definition Type.h:481
static T callback()
Definition Type.h:491
Definition Type.h:505
static void callback(Type &target)
Definition Type.h:513