Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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