Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1057 was 1056, checked in by landauf, 18 years ago

don't panic, no codechanges!
added a link to www.orxonox.net

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