Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core2/src/util/Convert.h @ 1975

Last change on this file since 1975 was 1004, checked in by landauf, 17 years ago

test

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.