Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/util/Convert.h @ 1052

Last change on this file since 1052 was 1052, checked in by landauf, 16 years ago

merged core2 back to trunk
there might be some errors, wasn't able to test it yet due to some strange g++ and linker behaviour.

File size: 23.1 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Benjamin Grauer
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 */
27
28/*!
29    @file Convert.h
30    @brief Definition and Implementation of the Convert class.
31*/
32
33#ifndef _Convert_H__
34#define _Convert_H__
35
36#include <string>
37#include <sstream>
38
39#include "UtilPrereqs.h"
40#include "Math.h"
41#include "SubString.h"
42#include "MultiTypeMath.h"
43
44
45//////////
46// MAIN //
47//////////
48
49// Enum to declare the wanted conversion preference in case of equal type-levels
50enum ConversionPreference
51{
52    CP_PreferToType,
53    CP_PreferFromType,
54};
55
56// Helper classes to determine the preferred partial template specialization
57class _ToType_   {};
58class _FromType_ {};
59class _Explicit_ {};
60
61
62// The default convert functions
63template <class FromType, class ToType, class Type>
64struct ConverterSpecialized
65{
66    enum { specialized = false };
67    static bool convert(ToType* output, const FromType& input)
68    { return false; }
69};
70
71
72// The default convert function if both types are the same
73template <class BothTypes>
74struct ConverterSpecialized<BothTypes, BothTypes, _Explicit_>
75{
76    enum { specialized = true };
77    static bool convert(BothTypes* output, const BothTypes& input)
78    { (*output) = input; return true; }
79};
80
81
82// The possible levels
83#define __low__  0 // Everything that is or behaves like a primitive type (an can be converted with a typecast to every other low-level type)
84#define __mid__  1 // Everything that has overloaded << and >> operators to operate on a std::stream
85#define __high__ 2 // Everything that doesn't fullfill the lowerlevel-requirements and therefore needs specialized conversions
86
87// Defines the levels of all types: Default is __high__ so you don't have to define every high-level type
88template <class T> struct ConverterLevel           { enum { level = __high__ }; };
89template <> struct ConverterLevel<std::string>     { enum { level = __mid__ }; };
90template <> struct ConverterLevel<orxonox::Radian> { enum { level = __mid__ }; };
91template <> struct ConverterLevel<orxonox::Degree> { enum { level = __mid__ }; };
92template <> struct ConverterLevel<int>             { enum { level = __low__ }; };
93template <> struct ConverterLevel<unsigned int>    { enum { level = __low__ }; };
94template <> struct ConverterLevel<char>            { enum { level = __low__ }; };
95template <> struct ConverterLevel<unsigned char>   { enum { level = __low__ }; };
96template <> struct ConverterLevel<short>           { enum { level = __low__ }; };
97template <> struct ConverterLevel<unsigned short>  { enum { level = __low__ }; };
98template <> struct ConverterLevel<long>            { enum { level = __low__ }; };
99template <> struct ConverterLevel<unsigned long>   { enum { level = __low__ }; };
100template <> struct ConverterLevel<float>           { enum { level = __low__ }; };
101template <> struct ConverterLevel<double>          { enum { level = __low__ }; };
102template <> struct ConverterLevel<long double>     { enum { level = __low__ }; };
103template <> struct ConverterLevel<bool>            { enum { level = __low__ }; };
104
105
106// Calculates the preference based on the levels of FromType and ToType
107template <int from, int to>
108struct ConverterPreference
109{
110    enum
111    {
112        // The maximum of both levels: element of {0, 1, 2}
113        // max 0: Both types are primitives or have a similar behaviour
114        // max 1: At least one type is not a primitive, but both can be put on a std::stream
115        // max 2: There is at least one generic type that needs specialized conversions
116        max = (from > to) ? from : to,
117
118        // The difference between both levels limited to +-1: element of {-1, 0, 1}
119        // diff -1: The FromType has higher level than the ToType
120        // diff  0: Both types have the same level
121        // diff  1: The ToType has higher level than the FromType
122        diff = ((to - from) > 1) ? 1 : (((to - from) < -1) ? -1 : to - from)
123    };
124};
125
126
127// The default conversion: This usually does nothing
128template <int max, class FromType, class ToType>
129struct ConverterDefault
130{
131    static bool convert(ToType* output, const FromType& input)
132    {
133        return false;
134    }
135};
136// The default conversion for primitives: A typecast (defined over two partial specialized templates to exclude all non-primitive types and classes)    template <int max, class FromType, class ToType>
137template <class FromType, class ToType>
138struct ConverterDefault<0, FromType, ToType>
139{
140    static bool convert(ToType* output, const FromType& input)
141    {
142        (*output) = (ToType)input;
143        return true;
144    }
145};
146
147
148// Converter: Converts input of FromType into output of ToType
149template <int diff, int max, class FromType, class ToType, ConversionPreference pref>
150struct Converter
151{
152    static bool convert(ToType* output, const FromType& input)
153    {
154        return false;
155    }
156};
157// Converter: level{FromType} > level{ToType}
158template <int max, class FromType, class ToType, ConversionPreference pref>
159struct Converter<-1, max, FromType, ToType, pref>
160{   static bool convert(ToType* output, const FromType& input)
161    { return (ConverterSpecialized<FromType, ToType, _Explicit_>::specialized) ? (ConverterSpecialized<FromType, ToType, _Explicit_>::convert(output, input)) : (ConverterSpecialized<FromType, ToType, _FromType_>::specialized) ? (ConverterSpecialized<FromType, ToType, _FromType_>::convert(output, input)) : (ConverterDefault<max, FromType, ToType>::convert(output, input)); } };
162// Converter: level{FromType} < level{ToType}
163template <int max, class FromType, class ToType, ConversionPreference pref>
164struct Converter<1, max, FromType, ToType, pref>
165{   static bool convert(ToType* output, const FromType& input)
166    { return (ConverterSpecialized<FromType, ToType, _Explicit_>::specialized) ? (ConverterSpecialized<FromType, ToType, _Explicit_>::convert(output, input)) : (ConverterSpecialized<FromType, ToType, _ToType_>::specialized) ? (ConverterSpecialized<FromType, ToType, _ToType_>::convert(output, input)) : (ConverterDefault<max, FromType, ToType>::convert(output, input)); } };
167// Converter: level{FromType} = level{ToType}
168// CP_PreferToType
169template <int max, class FromType, class ToType>
170struct Converter<0, max, FromType, ToType, CP_PreferToType>
171{   static bool convert(ToType* output, const FromType& input)
172    { return (ConverterSpecialized<FromType, ToType, _Explicit_>::specialized) ? (ConverterSpecialized<FromType, ToType, _Explicit_>::convert(output, input)) : (ConverterSpecialized<FromType, ToType, _ToType_>::specialized) ? (ConverterSpecialized<FromType, ToType, _ToType_>::convert(output, input)) : (ConverterSpecialized<FromType, ToType, _FromType_>::specialized) ? (ConverterSpecialized<FromType, ToType, _FromType_>::convert(output, input)) : (ConverterDefault<max, FromType, ToType>::convert(output, input)); } };
173// CP_PreferFromType
174template <int max, class FromType, class ToType>
175struct Converter<0, max, FromType, ToType, CP_PreferFromType>
176{   static bool convert(ToType* output, const FromType& input)
177    { return (ConverterSpecialized<FromType, ToType, _Explicit_>::specialized) ? (ConverterSpecialized<FromType, ToType, _Explicit_>::convert(output, input)) : (ConverterSpecialized<FromType, ToType, _FromType_>::specialized) ? (ConverterSpecialized<FromType, ToType, _FromType_>::convert(output, input)) : (ConverterSpecialized<FromType, ToType, _ToType_>::specialized) ? (ConverterSpecialized<FromType, ToType, _ToType_>::convert(output, input)) : (ConverterDefault<max, FromType, ToType>::convert(output, input)); } };
178
179
180// Calls the Converter::convertValue function with the correct template type parameters calculated by ConverterPreference
181template <class FromType, class ToType>
182static bool convertValue(ToType* output, const FromType& input, ConversionPreference preference = CP_PreferToType)
183{
184    return (preference == CP_PreferToType) ?
185           Converter<ConverterPreference<ConverterLevel<FromType>::level, ConverterLevel<ToType>::level>::diff,
186                     ConverterPreference<ConverterLevel<FromType>::level, ConverterLevel<ToType>::level>::max,
187                     FromType,
188                     ToType,
189                     CP_PreferToType>::convert(output, input)
190         : Converter<ConverterPreference<ConverterLevel<FromType>::level, ConverterLevel<ToType>::level>::diff,
191                     ConverterPreference<ConverterLevel<FromType>::level, ConverterLevel<ToType>::level>::max,
192                     FromType,
193                     ToType,
194                     CP_PreferFromType>::convert(output, input);
195}
196
197
198//////////////////////
199// HELPER FUNCTIONS //
200//////////////////////
201
202// Helper function: Calls convertValue with and without default value and returns true if the conversion was successful
203template<class FromType, class ToType>
204static bool ConvertValue(ToType* output, const FromType& input, ConversionPreference preference = CP_PreferToType)
205{
206    return convertValue(output, input, preference);
207}
208template<class FromType, class ToType>
209static bool ConvertValue(ToType* output, const FromType& input, const ToType& fallback, ConversionPreference preference = CP_PreferToType)
210{
211    if (convertValue(output, input, preference))
212        return true;
213
214    (*output) = fallback;
215    return false;
216}
217
218// Helper function: Calls convertValue with and without default value and returns the converted value
219template<class FromType, class ToType>
220static ToType getConvertedValue(const FromType& input, ConversionPreference preference = CP_PreferToType)
221{
222    ToType output = ToType();
223    ConvertValue(&output, input, preference);
224    return output;
225}
226template<class FromType, class ToType>
227static ToType getConvertedValue(const FromType& input, const ToType& fallback, ConversionPreference preference = CP_PreferToType)
228{
229    ToType output = fallback;
230    ConvertValue(&output, input, fallback, preference);
231    return output;
232}
233
234
235/////////////////////
236// SPECIALIZATIONS //
237/////////////////////
238
239/////////////
240// SAMPLES //
241/////////////
242/*
243// convert everything to xyz
244template <class FromType>
245struct ConverterSpecialized<FromType, xyz, _ToType_>
246{
247    enum { specialized = true };
248    static bool convert(xyz* output, const FromType& input)
249    { return ...; }
250};
251
252// convert xyz to everything
253template <class ToType>
254struct ConverterSpecialized<xyz, ToType, _FromType_>
255{
256    enum { specialized = true };
257    static bool convert(ToType* output, const xyz& input)
258    { return ...; }
259};
260
261// convert abc to xyz
262template <>
263struct ConverterSpecialized<abc, xyz, _Explicit_>
264{
265    enum { specialized = true };
266    static bool convert(xyz* output, const abc& input)
267    { return ...; }
268};
269*/
270
271////////////
272// STRING //
273////////////
274
275// convert to string
276template <class FromType>
277struct ConverterSpecialized<FromType, std::string, _ToType_>
278{
279    enum { specialized = true };
280    static bool convert(std::string* output, const FromType& input)
281    {
282        std::ostringstream oss;
283        if (oss << input)
284        {
285            (*output) = oss.str();
286            return true;
287        }
288        else
289            return false;
290    }
291};
292
293// convert from string
294template <class ToType>
295struct ConverterSpecialized<std::string, ToType, _FromType_>
296{
297    enum { specialized = true };
298    static bool convert(ToType* output, const std::string& input)
299    {
300        std::istringstream iss(input);
301        if (iss >> (*output))
302            return true;
303        else
304            return false;
305    }
306};
307
308
309////////////////
310// MULTITYPES //
311////////////////
312
313// convert from MultiTypePrimitive
314template <class ToType>
315struct ConverterSpecialized<MultiTypePrimitive, ToType, _FromType_>
316{
317    enum { specialized = true };
318    static bool convert(ToType* output, const MultiTypePrimitive& input)
319    {
320        if (input.getType() == MT_void)
321            return ConvertValue(output, input.getVoid());
322        else if (input.getType() == MT_int)
323            return ConvertValue(output, input.getInt());
324        else if (input.getType() == MT_uint)
325            return ConvertValue(output, input.getUnsignedInt());
326        else if (input.getType() == MT_char)
327            return ConvertValue(output, input.getChar());
328        else if (input.getType() == MT_uchar)
329            return ConvertValue(output, input.getUnsignedChar());
330        else if (input.getType() == MT_short)
331            return ConvertValue(output, input.getShort());
332        else if (input.getType() == MT_ushort)
333            return ConvertValue(output, input.getUnsignedShort());
334        else if (input.getType() == MT_long)
335            return ConvertValue(output, input.getLong());
336        else if (input.getType() == MT_ulong)
337            return ConvertValue(output, input.getUnsignedLong());
338        else if (input.getType() == MT_float)
339            return ConvertValue(output, input.getFloat());
340        else if (input.getType() == MT_double)
341            return ConvertValue(output, input.getDouble());
342        else if (input.getType() == MT_longdouble)
343            return ConvertValue(output, input.getLongDouble());
344        else if (input.getType() == MT_bool)
345            return ConvertValue(output, input.getBool());
346        else
347            return false;
348    }
349};
350
351// convert from MultiTypeString
352template <class ToType>
353struct ConverterSpecialized<MultiTypeString, ToType, _FromType_>
354{
355    enum { specialized = true };
356    static bool convert(ToType* output, const MultiTypeString& input)
357    {
358        if (input.getType() == MT_constchar)
359            return ConvertValue(output, input.getConstChar());
360        else if (input.getType() == MT_string)
361            return ConvertValue(output, input.getString());
362        else
363            return ConvertValue(output, (MultiTypePrimitive)input);
364    }
365};
366
367// convert from MultiTypeMath
368template <class ToType>
369struct ConverterSpecialized<MultiTypeMath, ToType, _FromType_>
370{
371    enum { specialized = true };
372    static bool convert(ToType* output, const MultiTypeMath& input)
373    {
374        if (input.getType() == MT_vector2)
375            return ConvertValue(output, input.getVector2());
376        else if (input.getType() == MT_vector3)
377            return ConvertValue(output, input.getVector3());
378        else if (input.getType() == MT_quaternion)
379            return ConvertValue(output, input.getQuaternion());
380        else if (input.getType() == MT_colourvalue)
381            return ConvertValue(output, input.getColourValue());
382        else if (input.getType() == MT_radian)
383            return ConvertValue(output, input.getRadian());
384        else if (input.getType() == MT_degree)
385            return ConvertValue(output, input.getDegree());
386        else
387            return ConvertValue(output, (MultiTypeString)input);
388    }
389};
390
391
392////////////////////
393// MATH TO STRING //
394////////////////////
395
396// Vector2 to std::string
397template <>
398struct ConverterSpecialized<orxonox::Vector2, std::string, _Explicit_>
399{
400    enum { specialized = true };
401    static bool convert(std::string* output, const orxonox::Vector2& input)
402    {
403        std::ostringstream ostream;
404        if (ostream << input.x << "," << input.y)
405        {
406            (*output) = ostream.str();
407            return true;
408        }
409        return false;
410    }
411};
412
413// Vector3 to std::string
414template <>
415struct ConverterSpecialized<orxonox::Vector3, std::string, _Explicit_>
416{
417    enum { specialized = true };
418    static bool convert(std::string* output, const orxonox::Vector3& input)
419    {
420        std::ostringstream ostream;
421        if (ostream << input.x << "," << input.y << "," << input.z)
422        {
423            (*output) = ostream.str();
424            return true;
425        }
426        return false;
427    }
428};
429
430// Vector4 to std::string
431template <>
432struct ConverterSpecialized<orxonox::Vector4, std::string, _Explicit_>
433{
434    enum { specialized = true };
435    static bool convert(std::string* output, const orxonox::Vector4& input)
436    {
437        std::ostringstream ostream;
438        if (ostream << input.x << "," << input.y << "," << input.z << "," << input.w)
439        {
440            (*output) = ostream.str();
441            return true;
442        }
443        return false;
444    }
445};
446
447// Quaternion to std::string
448template <>
449struct ConverterSpecialized<orxonox::Quaternion, std::string, _Explicit_>
450{
451    enum { specialized = true };
452    static bool convert(std::string* output, const orxonox::Quaternion& input)
453    {
454        std::ostringstream ostream;
455        if (ostream << input.w << "," << input.x << "," << input.y << "," << input.z)
456        {
457            (*output) = ostream.str();
458            return true;
459        }
460        return false;
461    }
462};
463
464// ColourValue to std::string
465template <>
466struct ConverterSpecialized<orxonox::ColourValue, std::string, _Explicit_>
467{
468    enum { specialized = true };
469    static bool convert(std::string* output, const orxonox::ColourValue& input)
470    {
471        std::ostringstream ostream;
472        if (ostream << input.r << "," << input.g << "," << input.b << "," << input.a)
473        {
474            (*output) = ostream.str();
475            return true;
476        }
477        return false;
478    }
479};
480
481
482////////////////////
483// STRING TO MATH //
484////////////////////
485
486// std::string to Vector2
487template <>
488struct ConverterSpecialized<std::string, orxonox::Vector2, _Explicit_>
489{
490    enum { specialized = true };
491    static bool convert(orxonox::Vector2* output, const std::string& input)
492    {
493        unsigned int opening_parenthesis, closing_parenthesis = input.find(')');
494        if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
495
496        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
497        if (tokens.size() >= 2)
498        {
499            if (!ConvertValue(&(output->x), tokens[0]))
500                return false;
501            if (!ConvertValue(&(output->y), tokens[1]))
502                return false;
503
504            return true;
505        }
506        return false;
507    }
508};
509
510// std::string to Vector3
511template <>
512struct ConverterSpecialized<std::string, orxonox::Vector3, _Explicit_>
513{
514    enum { specialized = true };
515    static bool convert(orxonox::Vector3* output, const std::string& input)
516    {
517        unsigned int opening_parenthesis, closing_parenthesis = input.find(')');
518        if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
519
520        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
521        if (tokens.size() >= 3)
522        {
523            if (!ConvertValue(&(output->x), tokens[0]))
524                return false;
525            if (!ConvertValue(&(output->y), tokens[1]))
526                return false;
527            if (!ConvertValue(&(output->z), tokens[2]))
528                return false;
529
530            return true;
531        }
532        return false;
533    }
534};
535
536// std::string to Vector4
537template <>
538struct ConverterSpecialized<std::string, orxonox::Vector4, _Explicit_>
539{
540    enum { specialized = true };
541    static bool convert(orxonox::Vector4* output, const std::string& input)
542    {
543        unsigned int opening_parenthesis, closing_parenthesis = input.find(')');
544        if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
545
546        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
547        if (tokens.size() >= 4)
548        {
549            if (!ConvertValue(&(output->x), tokens[0]))
550                return false;
551            if (!ConvertValue(&(output->y), tokens[1]))
552                return false;
553            if (!ConvertValue(&(output->z), tokens[2]))
554                return false;
555            if (!ConvertValue(&(output->w), tokens[3]))
556                return false;
557
558            return true;
559        }
560        return false;
561    }
562};
563
564// std::string to Quaternion
565template <>
566struct ConverterSpecialized<std::string, orxonox::Quaternion, _Explicit_>
567{
568    enum { specialized = true };
569    static bool convert(orxonox::Quaternion* output, const std::string& input)
570    {
571        unsigned int opening_parenthesis, closing_parenthesis = input.find(')');
572        if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
573
574        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
575        if (tokens.size() >= 4)
576        {
577            if (!ConvertValue(&(output->w), tokens[0]))
578                return false;
579            if (!ConvertValue(&(output->x), tokens[1]))
580                return false;
581            if (!ConvertValue(&(output->y), tokens[2]))
582                return false;
583            if (!ConvertValue(&(output->z), tokens[3]))
584                return false;
585
586            return true;
587        }
588        return false;
589    }
590};
591
592// std::string to ColourValue
593template <>
594struct ConverterSpecialized<std::string, orxonox::ColourValue, _Explicit_>
595{
596    enum { specialized = true };
597    static bool convert(orxonox::ColourValue* output, const std::string& input)
598    {
599        unsigned int opening_parenthesis, closing_parenthesis = input.find(')');
600        if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
601
602        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
603        if (tokens.size() >= 4)
604        {
605            if (!ConvertValue(&(output->r), tokens[0]))
606                return false;
607            if (!ConvertValue(&(output->g), tokens[1]))
608                return false;
609            if (!ConvertValue(&(output->b), tokens[2]))
610                return false;
611            if (!ConvertValue(&(output->a), tokens[3]))
612                return false;
613
614            return true;
615        }
616        return false;
617    }
618};
619
620#endif /* _Convert_H__ */
Note: See TracBrowser for help on using the repository browser.