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#include <cstdint>
39
40#include <list>
41#include <set>
42#include <vector>
43
44
45
46namespace drain {
47
49
52class Type {
53public:
54
55 inline
56 Type() : currentType(&typeid(void)) { //, typeMin(0), typeMax(0) {
57 }
58
59 inline
60 Type(const Type & t) : currentType(t.currentType) { //, typeMin(t.typeMin), typeMax(t.typeMax) { // FIX 0 0
61 //std::cerr << __FUNCTION__ << "(const &)" << std::endl;
62 }
63
64 template <class T>
65 Type(const T & t) : currentType(&typeid(void)){
66 setType(t);
67 }
68
69
70 template <class T>
71 inline
72 void setType(){
73 //std::cerr << __FUNCTION__ << "<T>()" << std::endl;
74 currentType = & typeid(T);
75 }
76
77
79
82 template <class T>
83 inline
84 void setType(const T & t){
85 call<typeSetter>(*this, t);
86 }
87
88 // TODO for std::strings.
89 template <class T>
90 inline
91 Type & operator=(const T & t){
92 setType(t);
93 return *this;
94 }
95
96 inline
97 operator const std::type_info & () const {return (*currentType); }
98
99 inline
100 operator char () const {return getTypeChar(*currentType); }
101
102 inline
103 operator std::string () const {return std::string(1, getTypeChar(*currentType)); }
104
105
107 inline
108 const std::type_info & getType() const {
109 return *currentType;
110 }
111
112
114
133 static
134 inline
135 const std::type_info & getTypeInfo(char t){
136
137 switch (t) {
138 case 'c':
139 return typeid(char);
140 case 'C':
141 return typeid(unsigned char);
142 case 's':
143 return typeid(short);
144 case 'S':
145 return typeid(unsigned short);
146 case 'i':
147 return typeid(int);
148 case 'I':
149 return typeid(unsigned int);
150 case 'l':
151 return typeid(long);
152 case 'L':
153 return typeid(unsigned long);
154 case 'f':
155 return typeid(float);
156 case 'd':
157 return typeid(double);
158 case 'B':
159 return typeid(bool);
160 case '$': // deprecated?
161 case '#':
162 return typeid(std::string);
163 case '*':
164 return typeid(void);
165 default:
166 //Logger mout("Type", std::string(__FUNCTION__)+"(char c)");
167 //Logger mout(__FILE__, __FUNCTION__);
168 //mout.error(" undefined type: '" , t , "'=" , (int)t );
169 std::cerr << __FILE__ << ' ' << __FUNCTION__ << " undefined type: '" << t << "'=" << (int)t << std::endl;
170 //mout.error(" undefined type: '" , t , "'=" , (int)t );
171 throw std::runtime_error("undefined type");
172 return typeid(void);
173 }
174
175 }
176
177 static
178 inline
179 char getTypeChar(const std::type_info & t){
180 if (t == typeid(char))
181 return 'c';
182 else if (t == typeid(unsigned char))
183 return 'C';
184 else if (t == typeid(short))
185 return 's';
186 else if (t == typeid(unsigned short))
187 return 'S';
188 else if (t == typeid(int))
189 return 'i';
190 else if (t == typeid(unsigned int))
191 return 'I';
192 else if (t == typeid(long))
193 return 'l';
194 else if (t == typeid(unsigned long))
195 return 'L';
196 else if (t == typeid(float))
197 return 'f';
198 else if (t == typeid(double))
199 return 'd';
200 else if (t == typeid(bool))
201 return 'B';
202 else if (t == typeid(void))
203 return '*';
204 else if (t == typeid(std::string))
205 return '#';
206 else if (t == typeid(const char *))
207 return '#';
208 else if (t == typeid(char *))
209 return '#';
210 else {
211 return 'x'; // = "extension"
212 }
213 }
214
216
222 template <class F, class T>
223 static
224 T call(const std::type_info & t){ // ORIGINAL
225
226 //std::cout << "Calling call with " << t.name() << " (" << getTypeChar(t) << ")\n";
227 // NOTE: STL uses string comparison!!!
228 if (t == typeid(char)){
229 return F::template callback<char,T>();
230 }
231 else if (t == typeid(unsigned char)) {
232 return F::template callback<unsigned char,T>();
233 }
234 else if (t == typeid(int)) {
235 return F::template callback<int,T>();
236 }
237 else if (t == typeid(unsigned int)) {
238 return F::template callback<unsigned int,T>();
239 }
240 else if (t == typeid(short int)) {
241 return F::template callback<short int,T>();
242 }
243 else if (t == typeid(unsigned short int)) {
244 return F::template callback<unsigned short int,T>();
245 }
246 else if (t == typeid(long int)) {
247 return F::template callback<long int,T>();
248 }
249 else if (t == typeid(unsigned long int)) {
250 return F::template callback<unsigned long int,T>();
251 }
252 else if (t == typeid(float)) {
253 return F::template callback<float,T>();
254 }
255 else if (t == typeid(double)) {
256 return F::template callback<double,T>();
257 }
258 else if (t == typeid(bool)) {
259 return F::template callback<bool,T>();
260 }
261 else if (t == typeid(void)) {
262 return F::template callback<void,T>();
263 }
264 else if (t == typeid(std::string)) {
265 return F::template callback<std::string,T>();
266 }
267 /*
268 else if (Type::call<isEnum>(t)){ // NEW 2023
269 // Problem: looping if not enum...
270 return F::template callback<int,T>();
271 }
272 */
273 else {
274 std::cerr << __FILE__ << ' ' << __FUNCTION__ << "unimplemented type: ..." << t.name() << std::endl;
275 //mout.error(" undefined type: '" , t , "'=" , (int)t );
276 throw std::runtime_error("unimplemented type: ...");
277 //Logger mout(__FILE__, __FUNCTION__);
278 // mout.error("unimplemented type: ...", t.name(), " NOTE: enums suppressed");
279 //return T(); //F::template callback<char,T>();
280 // Problem with ref types
281 return F::template callback<char,T>();
282 }
283
284 }
285
287
292 template <class F, class D, class S>
293 static inline
294 D call(const S & typeCode){
295 return call<F,D>(getTypeInfo(typeCode));
296 }
297
299
305 template <class F, class S>
306 static inline
307 typename F::value_t call(const S & typeCode){
308 return call<F,typename F::value_t>(getTypeInfo(typeCode));
309 }
310
311
313
339 template <class F, class T>
340 static
341 void call(T & target, const std::type_info &t){ // const Type &type){
342
343 if (t == typeid(char))
344 F::template callback<char>(target);
345 else if (t == typeid(unsigned char))
346 F::template callback<unsigned char>(target);
347 else if (t == typeid(int))
348 F::template callback<int>(target);
349 else if (t == typeid(unsigned int))
350 F::template callback<unsigned int>(target);
351 else if (t == typeid(short))
352 F::template callback<short>(target);
353 else if (t == typeid(unsigned short))
354 F::template callback<unsigned short>(target);
355 else if (t == typeid(long))
356 F::template callback<long>(target);
357 else if (t == typeid(unsigned long))
358 F::template callback<unsigned long>(target);
359 else if (t == typeid(float))
360 F::template callback<float>(target);
361 else if (t == typeid(double))
362 F::template callback<double>(target);
363 else if (t == typeid(bool))
364 F::template callback<bool>(target);
365 else if (t == typeid(std::string))
366 F::template callback<std::string>(target);
367 else if (t == typeid(void)) {
368 F::template callback<void>(target);
369 }
370 /*
371 else if (Type::call<isEnum>(t)){
372 F::template callback<int>(target);
373 }
374 */
375 else {
376 std::cerr << __FILE__ << ' ' << __FUNCTION__ << "unimplemented type: ..." << t.name() << std::endl;
377 //mout.error(" undefined type: '" , t , "'=" , (int)t );
378 throw std::runtime_error("unimplemented type: ...");
379
380 //Logger mout(__FILE__, __FUNCTION__);
381 //mout.error("unimplemented type: ...", t.name(), " NOTE: enums suppressed");
382 // throw std::runtime_error(std::string(": unimplemented type: ") + t.name() + " NOTE: enums suppressed");
383 return;
384 }
385 }
386
388
397 template <class F, class T, class T2>
398 static
399 void call(T & target, const T2 &t){
400 call<F>(target, getTypeInfo(t));
401 }
402
403
404
406
409 static
410 inline
411 const std::type_info & getTypeInfo(const char *typeCode){
412 if ((typeCode != NULL) && (*typeCode != '\0'))
413 return getTypeInfo(*typeCode);
414 else if (typeCode == NULL)
415 return getTypeInfo('*');
416 else
417 throw std::runtime_error(std::string("Type::operator=, not unit-length std::string: ") + typeCode);
418 }
419
421
424 static
425 inline
426 const std::type_info & getTypeInfo(const std::string & typeCode){
427 if (typeCode.length() == 1)
428 return getTypeInfo(typeCode.at(0));
429 else if (typeCode.empty())
430 return getTypeInfo('*');
431 else
432 throw std::runtime_error(std::string("Type::operator=, not unit-length std::string: ") + typeCode);
433 }
434
436 static
437 inline
438 const std::type_info & getTypeInfo(const Type & t){
439 return t;
440 }
441
442 /*
443 static
444 const drain::RegExp trueRegExp;
445
446 static
447 const drain::RegExp falseRegExp;
448 */
449
451
454 /*
455 static
456 const std::type_info & guessType(const std::string & value);
457
459 template <class C>
460 static
461 const std::type_info & guessArrayType(const C & container);
462 */
463
464 static inline
465 std::ostream & toStream(std::ostream & ostr, const Type &t){
466 const std::type_info & type = t.getType();
467 ostr << Type::getTypeChar(type) << '@'; // << Type::call<drain::sizeGetter>(type);
468 return ostr;
469 }
470
471 static inline
472 std::ostream & toStreamFull(std::ostream & ostr, const Type &t){
473 toStream(ostr, t);
474 //const std::type_info & type = t.getType();
475 // ostr << ' '<< '(' << Type::getMin<double>(type) << ',' << Type::call<drain::typeMax,double>(type) << ')';
476 /*
477 if (isSigned(type)){
478 //if (true){
479 ostr << " +/-";
480 }
481 */
482 return ostr;
483 }
484
485 struct isEnum {
486
487 typedef bool value_t;
488
493 template <class S, class T>
494 static
496 return std::is_enum<S>::value;
497 }
498
499
500 };
501
502// protected:
503
508 //static
510
515 template <class T>
516 static inline
517 void callback(Type & target){
518 //Logger mout(monitor, "Type", __FUNCTION__);
519 target.setType<T>();
520 }
521
522 };
523
525 public:
526
531 template <class S, class T>
532 static
533 void callback(T & target){
534 target.template setType<S>();
535 }
536 };
537
538 const std::type_info *currentType;
539
540};
541
542
544inline
545std::ostream & operator<<(std::ostream & ostr, const Type &t){
546 Type::toStream(ostr, t);
547 return ostr;
548}
549
550
551#ifdef DRAIN_TYPENAME
553
557class simpleNameOLD{
558
559public:
560
561 typedef std::string value_t;
562
567 template <class S, class T>
568 static
569 T callback(){
570 return TypeName<S>::str();
571 }
572
573
574};
575#endif
576
577
578
579} // drain::
580
581#endif
Definition Type.h:524
static void callback(T &target)
Definition Type.h:533
Utilities related to std::type_info.
Definition Type.h:52
static const std::type_info & getTypeInfo(const char *typeCode)
Returns the type corresponding to a single-character string.
Definition Type.h:411
static const std::type_info & getTypeInfo(const std::string &typeCode)
Returns the type corresponding to a single-character string.
Definition Type.h:426
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:465
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:438
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:341
const std::type_info & getType() const
Deprecated! Use cast (above) instead?
Definition Type.h:108
void setType(const T &t)
Set current type to t.
Definition Type.h:84
static T call(const std::type_info &t)
Calls a static function that has no parameters.
Definition Type.h:224
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:307
static D call(const S &typeCode)
New, preferred implementation: a single if-then structure once and for all.
Definition Type.h:294
static void call(T &target, const T2 &t)
Static function call with a single parameter.
Definition Type.h:399
static const std::type_info & getTypeInfo(char t)
Returns the base type associated with a character key.
Definition Type.h:135
Definition DataSelector.cpp:1277
Definition Type.h:485
static T callback()
Definition Type.h:495
Definition Type.h:509
static void callback(Type &target)
Definition Type.h:517