Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core3/src/util/Convert.h @ 1723

Last change on this file since 1723 was 1723, checked in by rgrieder, 16 years ago

Added types long long and unsigned long long to Convert.h

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