Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 2016


Ignore:
Timestamp:
Oct 26, 2008, 1:54:15 AM (15 years ago)
Author:
rgrieder
Message:

Merged the changes in Convert.h from core3 branch back.
If it doesn't work, feel free to revert. I have however more or less checked every possible conversion on gcc (tardis) and msvc with a script.

Location:
code/branches/objecthierarchy
Files:
5 edited
1 copied

Legend:

Unmodified
Added
Removed
  • code/branches/objecthierarchy/src/util

  • code/branches/objecthierarchy/src/util/Convert.h

    r1889 r2016  
    2121 *
    2222 *   Author:
     23 *      Reto Grieder
    2324 *      Fabian 'x3n' Landau
    2425 *      Benjamin Grauer
     
    2829
    2930/*!
    30     @file Convert.h
     31    @file
    3132    @brief Definition and Implementation of the Convert class.
    3233*/
    3334
    34 #ifndef _Convert_H__
    35 #define _Convert_H__
     35#ifndef _Converter_H__
     36#define _Converter_H__
    3637
    3738#include "UtilPrereqs.h"
     
    3940#include <string>
    4041#include <sstream>
     42#include <istream>
     43#include <ostream>
    4144#include <typeinfo>
    4245
    43 #include "Math.h"
    4446#include "Debug.h"
    45 #include "SubString.h"
    4647#include "String.h"
    4748
    48 // disable annoying warning about forcing value to boolean
     49// GCC generates warnings when implicitely casting from float to int for instance.
     50// This is however exactly what convertValue does, so we need to suppress these warnings.
     51// They only occur when using the ImplicitConversion template.
     52#if ORXONOX_COMPILER == ORXONOX_COMPILER_GNUC
     53#  pragma GCC system_header
     54#endif
     55
     56
     57///////////////////////////////////////////////
     58// Static detection for conversion functions //
     59///////////////////////////////////////////////
     60
     61/* The idea to use the sizeof() operator on return functions to determine function existance
     62   is described in 'Modern C++ design' by Alexandrescu (2001). */
     63
     64// disable warnings about possible loss of data
    4965#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
    50 #pragma warning(push)
    51 #pragma warning(disable:4100 4800)
     66#  pragma warning(push)
     67#  pragma warning(disable:4244)
    5268#endif
    5369
    54 
    55 //////////
    56 // MAIN //
    57 //////////
    58 
    59 // Enum to declare the wanted conversion preference in case of equal type-levels
    60 enum ConversionPreference
    61 {
    62     CP_PreferToType,
    63     CP_PreferFromType,
    64 };
    65 
    66 // Helper classes to determine the preferred partial template specialization
    67 class _ToType_   {};
    68 class _FromType_ {};
    69 class _Explicit_ {};
    70 
    71 
    72 // The default convert functions
    73 template <class FromType, class ToType, class Type>
    74 struct ConverterSpecialized
    75 {
    76     enum { specialized = false };
     70template <class FromType, class ToType>
     71class ImplicitConversion
     72{
     73private:
     74    ImplicitConversion(); ImplicitConversion(const ImplicitConversion&); ~ImplicitConversion();
     75    // Gets chosen only if there is an implicit conversion from FromType to ToType.
     76    static char test(ToType);
     77    // Accepts any argument. Why do we not use a template? The reason is that with templates,
     78    // the function above is only taken iff it is an exact type match. But since we want to
     79    // check for implicit conversion, we have to use the ellipsis.
     80    static long long test(...);
     81    static FromType object; // helper object to handle private c'tor and d'tor
     82public:
     83    // test(object) only has 'long long' return type iff the compiler doesn't choose test(...)
     84    enum { exists = (sizeof(test(object)) == sizeof(char)) };
     85};
     86
     87#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
     88#  pragma warning(pop)
     89#endif
     90
     91
     92////////////////////////////////////
     93//// ACTUAL CONVERSION SEQUENCE ////
     94////////////////////////////////////
     95/*
     96    There is a distinct priority when choosing the right conversion function:
     97    Overwrite:
     98    1. (Partial) template specialisation of ConverterExplicit::convert()
     99    Fallbacks:
     100    2. Any possible implicit conversion. This includes 'FooBar' --> 'int' if FooBar defines operator float().
     101    3. Global or member operators for stringstream when converting from or to std::string (or FROM const char*)
     102    4. (Partial) template specialisation of ConverterFallback::convert()
     103    5. Function that simply displays "Could not convert value" with type information obtained from typeid().
     104
     105    Notes:
     106    There has to be an exact type match when using template specialisations.
     107    Template specialisations can be defined after including this file. Any implicit cast function or iostream
     108    operator has to be declared BEFORE this file gets parsed.
     109
     110    Defining your own functions:
     111    There are obviously 4 ways to specifiy a user defined conversion. What should I use?
     112
     113    Usually, ConverterFallback fits quite well. You won't have to deal with the conversion from
     114    'MyClass' to 'MyClass' by using another explicit template specialisation to avoid ambiguities.
     115
     116    However if you want to overwrite an implicit conversion or an iostream operator, you really need to
     117    make use of ConverterExplicit.
     118*/
     119
     120namespace
     121{
     122    //! Little template that maps integers to entire types (Alexandrescu 2001)
     123    template <int I>
     124    struct Int2Type { };
     125}
     126
     127
     128///////////////////
     129// No Conversion //
     130///////////////////
     131
     132// Default template. No conversion available at all.
     133template <class FromType, class ToType>
     134struct ConverterFallback
     135{
    77136    static bool convert(ToType* output, const FromType& input)
    78137    {
    79         COUT(2) << "Warning: Couldn't convert a value: From \"" << typeid(FromType).name() << "\" to \"" << typeid(ToType).name() << "\"" << std::endl;
     138        COUT(2) << "Could not convert value of type " << typeid(FromType).name()
     139                << " to type " << typeid(ToType).name() << std::endl;
    80140        return false;
    81141    }
     
    83143
    84144
    85 // The default convert function if both types are the same
    86 template <class BothTypes>
    87 struct ConverterSpecialized<BothTypes, BothTypes, _Explicit_>
    88 {
    89     enum { specialized = true };
    90     static bool convert(BothTypes* output, const BothTypes& input)
    91     { (*output) = input; return true; }
    92 };
    93 
    94 
    95 // The possible levels
    96 #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)
    97 #define __mid__  1 // Everything that has overloaded << and >> operators to operate on a std::stream
    98 #define __high__ 2 // Everything that doesn't fullfill the lowerlevel-requirements and therefore needs specialized conversions
    99 
    100 // Defines the levels of all types: Default is __high__ so you don't have to define every high-level type
    101 template <class T> struct ConverterLevel              { enum { level = __high__ }; };
    102 template <> struct ConverterLevel<std::string>        { enum { level = __mid__ }; };
    103 template <> struct ConverterLevel<orxonox::Radian>    { enum { level = __mid__ }; };
    104 template <> struct ConverterLevel<orxonox::Degree>    { enum { level = __mid__ }; };
    105 template <> struct ConverterLevel<int>                { enum { level = __low__ }; };
    106 template <> struct ConverterLevel<unsigned int>       { enum { level = __low__ }; };
    107 template <> struct ConverterLevel<char>               { enum { level = __low__ }; };
    108 template <> struct ConverterLevel<unsigned char>      { enum { level = __low__ }; };
    109 template <> struct ConverterLevel<short>              { enum { level = __low__ }; };
    110 template <> struct ConverterLevel<unsigned short>     { enum { level = __low__ }; };
    111 template <> struct ConverterLevel<long>               { enum { level = __low__ }; };
    112 template <> struct ConverterLevel<unsigned long>      { enum { level = __low__ }; };
    113 template <> struct ConverterLevel<long long>          { enum { level = __low__ }; };
    114 template <> struct ConverterLevel<unsigned long long> { enum { level = __low__ }; };
    115 template <> struct ConverterLevel<float>              { enum { level = __low__ }; };
    116 template <> struct ConverterLevel<double>             { enum { level = __low__ }; };
    117 template <> struct ConverterLevel<long double>        { enum { level = __low__ }; };
    118 template <> struct ConverterLevel<bool>               { enum { level = __low__ }; };
    119 
    120 
    121 // Calculates the preference based on the levels of FromType and ToType
    122 template <int from, int to>
    123 struct ConverterPreference
    124 {
    125     enum
    126     {
    127         // The maximum of both levels: element of {0, 1, 2}
    128         // max 0: Both types are primitives or have a similar behaviour
    129         // max 1: At least one type is not a primitive, but both can be put on a std::stream
    130         // max 2: There is at least one generic type that needs specialized conversions
    131         max = (from > to) ? from : to,
    132 
    133         // The difference between both levels limited to +-1: element of {-1, 0, 1}
    134         // diff -1: The FromType has higher level than the ToType
    135         // diff  0: Both types have the same level
    136         // diff  1: The ToType has higher level than the FromType
    137         diff = ((to - from) > 1) ? 1 : (((to - from) < -1) ? -1 : to - from)
    138     };
    139 };
    140 
    141 
    142 // The default conversion: This usually does nothing
    143 template <int max, class FromType, class ToType>
    144 struct ConverterDefault
     145///////////////////////
     146// ConverterFallback //
     147///////////////////////
     148
     149// Default template for stringstream
     150template <class FromType, class ToType>
     151struct ConverterStringStream
    145152{
    146153    static bool convert(ToType* output, const FromType& input)
    147154    {
    148         COUT(2) << "Warning: Couldn't convert a value: From \"" << typeid(FromType).name() << "\" to \"" << typeid(ToType).name() << "\"" << std::endl;
    149         return false;
    150     }
    151 };
    152 // 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>
    153 template <class FromType, class ToType>
    154 struct ConverterDefault<0, FromType, ToType>
    155 {
    156     static bool convert(ToType* output, const FromType& input)
    157     {
    158         (*output) = (ToType)input;
    159         return true;
    160     }
    161 };
    162 
    163 
    164 // Converter: Converts input of FromType into output of ToType
    165 template <int diff, int max, class FromType, class ToType, ConversionPreference pref>
    166 struct Converter
    167 {
    168     static bool convert(ToType* output, const FromType& input)
    169     {
    170         return false;
    171     }
    172 };
    173 // Converter: level{FromType} > level{ToType}
    174 template <int max, class FromType, class ToType, ConversionPreference pref>
    175 struct Converter<-1, max, FromType, ToType, pref>
    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)) : (ConverterDefault<max, FromType, ToType>::convert(output, input)); } };
    178 // Converter: level{FromType} < level{ToType}
    179 template <int max, class FromType, class ToType, ConversionPreference pref>
    180 struct Converter<1, max, FromType, ToType, pref>
    181 {   static bool convert(ToType* output, const FromType& input)
    182     { 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)); } };
    183 // Converter: level{FromType} = level{ToType}
    184 // CP_PreferToType
    185 template <int max, class FromType, class ToType>
    186 struct Converter<0, max, FromType, ToType, CP_PreferToType>
    187 {   static bool convert(ToType* output, const FromType& input)
    188     { 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)); } };
    189 // CP_PreferFromType
    190 template <int max, class FromType, class ToType>
    191 struct Converter<0, max, FromType, ToType, CP_PreferFromType>
    192 {   static bool convert(ToType* output, const FromType& input)
    193     { 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)); } };
    194 
    195 
    196 // Calls the Converter::convertValue function with the correct template type parameters calculated by ConverterPreference
    197 template <class FromType, class ToType>
    198 static bool convertValue(ToType* output, const FromType& input, ConversionPreference preference = CP_PreferToType)
    199 {
    200     return (preference == CP_PreferToType) ?
    201            Converter<ConverterPreference<ConverterLevel<FromType>::level, ConverterLevel<ToType>::level>::diff,
    202                      ConverterPreference<ConverterLevel<FromType>::level, ConverterLevel<ToType>::level>::max,
    203                      FromType,
    204                      ToType,
    205                      CP_PreferToType>::convert(output, input)
    206          : Converter<ConverterPreference<ConverterLevel<FromType>::level, ConverterLevel<ToType>::level>::diff,
    207                      ConverterPreference<ConverterLevel<FromType>::level, ConverterLevel<ToType>::level>::max,
    208                      FromType,
    209                      ToType,
    210                      CP_PreferFromType>::convert(output, input);
    211 }
    212 
    213 
    214 //////////////////////
    215 // HELPER FUNCTIONS //
    216 //////////////////////
    217 
    218 // Helper function: Calls convertValue with and without default value and returns true if the conversion was successful
    219 template<class FromType, class ToType>
    220 static bool ConvertValue(ToType* output, const FromType& input, ConversionPreference preference = CP_PreferToType)
    221 {
    222     return convertValue(output, input, preference);
    223 }
    224 template<class FromType, class ToType>
    225 static bool ConvertValue(ToType* output, const FromType& input, const ToType& fallback, ConversionPreference preference = CP_PreferToType)
    226 {
    227     if (convertValue(output, input, preference))
    228         return true;
    229 
    230     (*output) = fallback;
    231     return false;
    232 }
    233 
    234 // Helper function: Calls convertValue with and without default value and returns the converted value
    235 template<class FromType, class ToType>
    236 static ToType getConvertedValue(const FromType& input, ConversionPreference preference = CP_PreferToType)
    237 {
    238     ToType output = ToType();
    239     ConvertValue(&output, input, preference);
    240     return output;
    241 }
    242 template<class FromType, class ToType>
    243 static ToType getConvertedValue(const FromType& input, const ToType& fallback, ConversionPreference preference = CP_PreferToType)
    244 {
    245     ToType output = fallback;
    246     ConvertValue(&output, input, fallback, preference);
    247     return output;
    248 }
    249 
    250 
    251 /////////////////////
    252 // SPECIALIZATIONS //
    253 /////////////////////
     155        return ConverterFallback<FromType, ToType>::convert(output, input);
     156    }
     157};
     158
    254159
    255160/////////////
    256 // SAMPLES //
     161// OStream //
    257162/////////////
    258 /*
    259 // convert everything to xyz
     163
     164namespace fallbackTemplates
     165{
     166    template <class FromType>
     167    inline bool operator <<(std::ostream& outstream,  const FromType& input)
     168    {
     169        std::string temp;
     170        if (ConverterFallback<FromType, std::string>::convert(&temp, input))
     171        {
     172            std::operator <<(outstream, temp);
     173            return true;
     174        }
     175        else
     176            return false;
     177    }
     178}
     179
     180// template that evaluates whether we can convert to std::string via ostringstream
    260181template <class FromType>
    261 struct ConverterSpecialized<FromType, xyz, _ToType_>
    262 {
    263     enum { specialized = true };
    264     static bool convert(xyz* output, const FromType& input)
    265     { return ...; }
    266 };
    267 
    268 // convert xyz to everything
    269 template <class ToType>
    270 struct ConverterSpecialized<xyz, ToType, _FromType_>
    271 {
    272     enum { specialized = true };
    273     static bool convert(ToType* output, const xyz& input)
    274     { return ...; }
    275 };
    276 
    277 // convert abc to xyz
    278 template <>
    279 struct ConverterSpecialized<abc, xyz, _Explicit_>
    280 {
    281     enum { specialized = true };
    282     static bool convert(xyz* output, const abc& input)
    283     { return ...; }
    284 };
    285 */
    286 
    287 ////////////
    288 // STRING //
    289 ////////////
    290 
    291 // convert to string
    292 template <class FromType>
    293 struct ConverterSpecialized<FromType, std::string, _ToType_>
    294 {
    295     enum { specialized = true };
     182struct ConverterStringStream<FromType, std::string>
     183{
    296184    static bool convert(std::string* output, const FromType& input)
    297185    {
     186        using namespace fallbackTemplates;
     187        // this operator call only chooses fallbackTemplates::operator<< if there's no other fitting function
    298188        std::ostringstream oss;
    299189        if (oss << input)
     
    307197};
    308198
     199
     200/////////////
     201// IStream //
     202/////////////
     203
     204namespace fallbackTemplates
     205{
     206    template <class ToType>
     207    inline bool operator >>(std::istream& instream, ToType& output)
     208    {
     209        return ConverterFallback<std::string, ToType>
     210            ::convert(&output, static_cast<std::istringstream&>(instream).str());
     211    }
     212}
     213
     214// template that evaluates whether we can convert from std::string via ostringstream
     215template <class ToType>
     216struct ConverterStringStream<std::string, ToType>
     217{
     218    static bool convert(ToType* output, const std::string& input)
     219    {
     220        using namespace fallbackTemplates;
     221        std::istringstream iss(input);
     222        // this operator call only chooses fallbackTemplates::operator>> if there's no other fitting function
     223        if (iss >> (*output))
     224        {
     225            return true;
     226        }
     227        else
     228            return false;
     229    }
     230};
     231
     232
     233///////////////////
     234// Implicit Cast //
     235///////////////////
     236
     237// implicit cast not possible, try stringstream conversion next
     238template <class FromType, class ToType>
     239inline bool convertImplicitely(ToType* output, const FromType& input, ::Int2Type<false>)
     240{
     241    return ConverterStringStream<FromType, ToType>::convert(output, input);
     242}
     243
     244// We can cast implicitely
     245template <class FromType, class ToType>
     246inline bool convertImplicitely(ToType* output, const FromType& input, ::Int2Type<true>)
     247{
     248    (*output) = static_cast<ToType>(input);
     249    return true;
     250}
     251
     252
     253////////////////////////////////
     254// ConverterExplicit Fallback //
     255////////////////////////////////
     256
     257// Default template if no specialisation is available
     258template <class FromType, class ToType>
     259struct ConverterExplicit
     260{
     261    static bool convert(ToType* output, const FromType& input)
     262    {
     263        // Try implict cast and probe first. If a simple cast is not possible, it will not compile
     264        // We therefore have to out source it into another template function
     265        const bool probe = ImplicitConversion<FromType, ToType>::exists;
     266        return convertImplicitely(output, input, ::Int2Type<probe>());
     267    }
     268};
     269
     270
     271//////////////////////
     272// Public Functions //
     273//////////////////////
     274
     275/**
     276@brief
     277    Converts any value to any other as long as there exists a conversion.
     278    Otherwise, the conversion will generate a runtime warning and return false.
     279    For information about the different conversion methods (user defined too), see the section
     280    'Actual conversion sequence' in this file above.
     281*/
     282template <class FromType, class ToType>
     283inline bool convertValue(ToType* output, const FromType& input)
     284{
     285    return ConverterExplicit<FromType, ToType>::convert(output, input);
     286}
     287
     288// For compatibility reasons. The same, but with capital ConvertValue
     289template<class FromType, class ToType>
     290inline bool ConvertValue(ToType* output, const FromType& input)
     291{
     292    return convertValue(output, input);
     293}
     294
     295// Calls convertValue and returns true if the conversion was successful.
     296// Otherwise the fallback is used.
     297/**
     298@brief
     299    Converts any value to any other as long as there exists a conversion.
     300    Otherwise, the conversion will generate a runtime warning and return false.
     301    For information about the different conversion methods (user defined too), see the section
     302    'Actual conversion sequence' in this file above.
     303    If the conversion doesn't succeed, 'fallback' is written to '*output'.
     304@param fallback
     305    A default value that gets written to '*output' if there is no conversion.
     306*/
     307template<class FromType, class ToType>
     308inline bool convertValue(ToType* output, const FromType& input, const ToType& fallback)
     309{
     310    if (convertValue(output, input))
     311        return true;
     312    else
     313    {
     314        (*output) = fallback;
     315        return false;
     316    }
     317}
     318
     319// for compatibility reason. (capital 'c' in ConvertValue)
     320template<class FromType, class ToType>
     321inline bool ConvertValue(ToType* output, const FromType& input, const ToType& fallback)
     322{
     323    return convertValue(output, input, fallback);
     324}
     325
     326// Directly returns the converted value, even if the conversion was not successful.
     327template<class FromType, class ToType>
     328inline ToType getConvertedValue(const FromType& input)
     329{
     330    ToType output;
     331    convertValue(&output, input);
     332    return output;
     333}
     334
     335// Directly returns the converted value, but uses the fallback on failure.
     336template<class FromType, class ToType>
     337inline ToType getConvertedValue(const FromType& input, const ToType& fallback)
     338{
     339    ToType output;
     340    convertValue(&output, input, fallback);
     341    return output;
     342}
     343
     344// Like getConvertedValue, but the template argument order is in reverse.
     345// That means you can call it exactly like static_cast<ToType>(fromTypeValue).
     346template<class ToType, class FromType>
     347inline ToType conversion_cast(const FromType& input)
     348{
     349    ToType output;
     350    convertValue(&output, input);
     351    return output;
     352}
     353
    309354// convert to string Shortcut
    310355template <class FromType>
     
    314359}
    315360
    316 // convert from string
    317 template <class ToType>
    318 struct ConverterSpecialized<std::string, ToType, _FromType_>
    319 {
    320     enum { specialized = true };
    321     static bool convert(ToType* output, const std::string& input)
    322     {
    323         std::istringstream iss(input);
    324         if (iss >> (*output))
    325             return true;
    326         else
    327             return false;
    328     }
    329 };
    330 
    331361// convert from string Shortcut
    332362template <class ToType>
     
    336366}
    337367
    338 
    339 //////////
    340 // MATH //
    341 //////////
    342 // convert everything to Degree
    343 template <class FromType>
    344 struct ConverterSpecialized<FromType, Ogre::Degree, _ToType_>
    345 {
    346     enum { specialized = true };
    347     static bool convert(Ogre::Degree* output, const FromType& input)
    348     {
    349         float angle = 0;
    350         bool success = ConvertValue<FromType, float>(&angle, input);
    351         (*output) = angle;
    352         return success;
    353     }
    354 };
    355 
    356 // convert everything to Radian
    357 template <class FromType>
    358 struct ConverterSpecialized<FromType, Ogre::Radian, _ToType_>
    359 {
    360     enum { specialized = true };
    361     static bool convert(Ogre::Radian* output, const FromType& input)
    362     {
    363         float angle = 0;
    364         bool success = ConvertValue<FromType, float>(&angle, input);
    365         (*output) = angle;
    366         return success;
    367     }
    368 };
    369 
    370 
    371 ////////////////////
    372 // MATH TO STRING //
    373 ////////////////////
     368////////////////////////////////
     369// Special string conversions //
     370////////////////////////////////
     371
     372// Delegate conversion from const char* to std::string
     373template <class ToType>
     374struct ConverterExplicit<const char*, ToType>
     375{
     376    static bool convert(ToType* output, const char* input)
     377    {
     378        return convertValue<std::string, ToType>(output, input);
     379    }
     380};
     381
     382// These conversions would exhibit ambiguous << or >> operators when using stringstream
     383template <>
     384struct ConverterExplicit<char, std::string>
     385{
     386    static bool convert(std::string* output, const char input)
     387    {
     388        *output = std::string(1, input);
     389        return true;
     390    }
     391};
     392template <>
     393struct ConverterExplicit<unsigned char, std::string>
     394{
     395    static bool convert(std::string* output, const unsigned char input)
     396    {
     397        *output = std::string(1, input);
     398        return true;
     399    }
     400};
     401template <>
     402struct ConverterExplicit<std::string, char>
     403{
     404    static bool convert(char* output, const std::string input)
     405    {
     406        if (input != "")
     407            *output = input[0];
     408        else
     409            *output = '\0';
     410        return true;
     411    }
     412};
     413template <>
     414struct ConverterExplicit<std::string, unsigned char>
     415{
     416    static bool convert(unsigned char* output, const std::string input)
     417    {
     418        if (input != "")
     419            *output = input[0];
     420        else
     421            *output = '\0';
     422        return true;
     423    }
     424};
     425
    374426
    375427// bool to std::string
    376428template <>
    377 struct ConverterSpecialized<bool, std::string, _Explicit_>
    378 {
    379     enum { specialized = true };
     429struct ConverterExplicit<bool, std::string>
     430{
    380431    static bool convert(std::string* output, const bool& input)
    381432    {
     
    388439};
    389440
    390 // Vector2 to std::string
    391 template <>
    392 struct ConverterSpecialized<orxonox::Vector2, std::string, _Explicit_>
    393 {
    394     enum { specialized = true };
    395     static bool convert(std::string* output, const orxonox::Vector2& input)
    396     {
    397         std::ostringstream ostream;
    398         if (ostream << input.x << "," << input.y)
    399         {
    400             (*output) = ostream.str();
    401             return true;
    402         }
    403         return false;
    404     }
    405 };
    406 
    407 // Vector3 to std::string
    408 template <>
    409 struct ConverterSpecialized<orxonox::Vector3, std::string, _Explicit_>
    410 {
    411     enum { specialized = true };
    412     static bool convert(std::string* output, const orxonox::Vector3& input)
    413     {
    414         std::ostringstream ostream;
    415         if (ostream << input.x << "," << input.y << "," << input.z)
    416         {
    417             (*output) = ostream.str();
    418             return true;
    419         }
    420         return false;
    421     }
    422 };
    423 
    424 // Vector4 to std::string
    425 template <>
    426 struct ConverterSpecialized<orxonox::Vector4, std::string, _Explicit_>
    427 {
    428     enum { specialized = true };
    429     static bool convert(std::string* output, const orxonox::Vector4& input)
    430     {
    431         std::ostringstream ostream;
    432         if (ostream << input.x << "," << input.y << "," << input.z << "," << input.w)
    433         {
    434             (*output) = ostream.str();
    435             return true;
    436         }
    437         return false;
    438     }
    439 };
    440 
    441 // Quaternion to std::string
    442 template <>
    443 struct ConverterSpecialized<orxonox::Quaternion, std::string, _Explicit_>
    444 {
    445     enum { specialized = true };
    446     static bool convert(std::string* output, const orxonox::Quaternion& input)
    447     {
    448         std::ostringstream ostream;
    449         if (ostream << input.w << "," << input.x << "," << input.y << "," << input.z)
    450         {
    451             (*output) = ostream.str();
    452             return true;
    453         }
    454         return false;
    455     }
    456 };
    457 
    458 // ColourValue to std::string
    459 template <>
    460 struct ConverterSpecialized<orxonox::ColourValue, std::string, _Explicit_>
    461 {
    462     enum { specialized = true };
    463     static bool convert(std::string* output, const orxonox::ColourValue& input)
    464     {
    465         std::ostringstream ostream;
    466         if (ostream << input.r << "," << input.g << "," << input.b << "," << input.a)
    467         {
    468             (*output) = ostream.str();
    469             return true;
    470         }
    471         return false;
    472     }
    473 };
    474 
    475 
    476 ////////////////////
    477 // STRING TO MATH //
    478 ////////////////////
    479 
    480441// std::string to bool
    481442template <>
    482 struct ConverterSpecialized<std::string, bool, _Explicit_>
    483 {
    484     enum { specialized = true };
     443struct ConverterExplicit<std::string, bool>
     444{
    485445    static bool convert(bool* output, const std::string& input)
    486446    {
     
    505465};
    506466
    507 // std::string to Vector2
    508 template <>
    509 struct ConverterSpecialized<std::string, orxonox::Vector2, _Explicit_>
    510 {
    511     enum { specialized = true };
    512     static bool convert(orxonox::Vector2* output, const std::string& input)
    513     {
    514         size_t opening_parenthesis, closing_parenthesis = input.find(')');
    515         if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
    516 
    517         SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
    518         if (tokens.size() >= 2)
    519         {
    520             if (!ConvertValue(&(output->x), tokens[0]))
    521                 return false;
    522             if (!ConvertValue(&(output->y), tokens[1]))
    523                 return false;
    524 
    525             return true;
    526         }
    527         return false;
    528     }
    529 };
    530 
    531 // std::string to Vector3
    532 template <>
    533 struct ConverterSpecialized<std::string, orxonox::Vector3, _Explicit_>
    534 {
    535     enum { specialized = true };
    536     static bool convert(orxonox::Vector3* output, const std::string& input)
    537     {
    538         size_t opening_parenthesis, closing_parenthesis = input.find(')');
    539         if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
    540 
    541         SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
    542         if (tokens.size() >= 3)
    543         {
    544             if (!ConvertValue(&(output->x), tokens[0]))
    545                 return false;
    546             if (!ConvertValue(&(output->y), tokens[1]))
    547                 return false;
    548             if (!ConvertValue(&(output->z), tokens[2]))
    549                 return false;
    550 
    551             return true;
    552         }
    553         return false;
    554     }
    555 };
    556 
    557 // std::string to Vector4
    558 template <>
    559 struct ConverterSpecialized<std::string, orxonox::Vector4, _Explicit_>
    560 {
    561     enum { specialized = true };
    562     static bool convert(orxonox::Vector4* output, const std::string& input)
    563     {
    564         size_t opening_parenthesis, closing_parenthesis = input.find(')');
    565         if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
    566 
    567         SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
    568         if (tokens.size() >= 4)
    569         {
    570             if (!ConvertValue(&(output->x), tokens[0]))
    571                 return false;
    572             if (!ConvertValue(&(output->y), tokens[1]))
    573                 return false;
    574             if (!ConvertValue(&(output->z), tokens[2]))
    575                 return false;
    576             if (!ConvertValue(&(output->w), tokens[3]))
    577                 return false;
    578 
    579             return true;
    580         }
    581         return false;
    582     }
    583 };
    584 
    585 // std::string to Quaternion
    586 template <>
    587 struct ConverterSpecialized<std::string, orxonox::Quaternion, _Explicit_>
    588 {
    589     enum { specialized = true };
    590     static bool convert(orxonox::Quaternion* output, const std::string& input)
    591     {
    592         size_t opening_parenthesis, closing_parenthesis = input.find(')');
    593         if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
    594 
    595         SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
    596         if (tokens.size() >= 4)
    597         {
    598             if (!ConvertValue(&(output->w), tokens[0]))
    599                 return false;
    600             if (!ConvertValue(&(output->x), tokens[1]))
    601                 return false;
    602             if (!ConvertValue(&(output->y), tokens[2]))
    603                 return false;
    604             if (!ConvertValue(&(output->z), tokens[3]))
    605                 return false;
    606 
    607             return true;
    608         }
    609         return false;
    610     }
    611 };
    612 
    613 // std::string to ColourValue
    614 template <>
    615 struct ConverterSpecialized<std::string, orxonox::ColourValue, _Explicit_>
    616 {
    617     enum { specialized = true };
    618     static bool convert(orxonox::ColourValue* output, const std::string& input)
    619     {
    620         size_t opening_parenthesis, closing_parenthesis = input.find(')');
    621         if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
    622 
    623         SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
    624         if (tokens.size() >= 3)
    625         {
    626             if (!ConvertValue(&(output->r), tokens[0]))
    627                 return false;
    628             if (!ConvertValue(&(output->g), tokens[1]))
    629                 return false;
    630             if (!ConvertValue(&(output->b), tokens[2]))
    631                 return false;
    632             if (tokens.size() >= 4)
    633             {
    634                 if (!ConvertValue(&(output->a), tokens[3]))
    635                     return false;
    636             }
    637             else
    638                 output->a = 1.0;
    639 
    640             return true;
    641         }
    642         return false;
    643     }
    644 };
    645 
    646 
    647 ///////////////////////////
    648 // Static type detection //
    649 ///////////////////////////
    650 
    651 /**
    652     Template class that determines whether type T converts implicitly to type U.
    653 @note
    654     This allows to detect type conversion at compile time.
    655     From 'Modern C++ Design' (Alexandrescu 2001).
    656 */
    657 template <class T, class U>
    658 class StaticConversion
    659 {
    660     class Small { char dummy[1]; };
    661     class Big   { char dummy[1024]; };
    662     static Small Test(U);
    663     static Big   Test(...);
    664     static T MakeT();
    665 public:
    666     enum { exists = sizeof(Test(MakeT())) == sizeof(Small) };
    667 };
    668 
    669 #if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
    670 #pragma warning(pop)
    671 #endif
    672 
    673467#endif /* _Convert_H__ */
  • code/branches/objecthierarchy/src/util/Math.cc

    r1791 r2016  
    2828
    2929/**
    30     @file Math.cc
     30    @file
    3131    @brief Implementation of several math-functions.
    3232*/
    3333
     34#include "Math.h"
     35
    3436#include <OgrePlane.h>
    35 
    36 #include "Math.h"
    37 #include "Convert.h"
     37#include "MathConvert.h"
     38#include "SubString.h"
    3839
    3940/**
     
    205206    return convertToString(getUniqueNumber());
    206207}
     208
     209
     210//////////////////////////
     211// Conversion functions //
     212//////////////////////////
     213
     214// std::string to Vector2
     215bool ConverterFallback<std::string, orxonox::Vector2>::convert(orxonox::Vector2* output, const std::string& input)
     216{
     217    size_t opening_parenthesis, closing_parenthesis = input.find(')');
     218    if ((opening_parenthesis = input.find('(')) == std::string::npos)
     219        opening_parenthesis = 0;
     220    else
     221        opening_parenthesis++;
     222
     223    SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
     224                     ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
     225    if (tokens.size() >= 2)
     226    {
     227        if (!ConvertValue(&(output->x), tokens[0]))
     228            return false;
     229        if (!ConvertValue(&(output->y), tokens[1]))
     230            return false;
     231
     232        return true;
     233    }
     234    return false;
     235}
     236
     237// std::string to Vector3
     238bool ConverterFallback<std::string, orxonox::Vector3>::convert(orxonox::Vector3* output, const std::string& input)
     239{
     240    size_t opening_parenthesis, closing_parenthesis = input.find(')');
     241    if ((opening_parenthesis = input.find('(')) == std::string::npos)
     242        opening_parenthesis = 0;
     243    else
     244        opening_parenthesis++;
     245
     246    SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
     247                     ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
     248    if (tokens.size() >= 3)
     249    {
     250        if (!ConvertValue(&(output->x), tokens[0]))
     251            return false;
     252        if (!ConvertValue(&(output->y), tokens[1]))
     253            return false;
     254        if (!ConvertValue(&(output->z), tokens[2]))
     255            return false;
     256
     257        return true;
     258    }
     259    return false;
     260}
     261
     262// std::string to Vector4
     263bool ConverterFallback<std::string, orxonox::Vector4>::convert(orxonox::Vector4* output, const std::string& input)
     264{
     265    size_t opening_parenthesis, closing_parenthesis = input.find(')');
     266    if ((opening_parenthesis = input.find('(')) == std::string::npos)
     267        opening_parenthesis = 0;
     268    else
     269        opening_parenthesis++;
     270
     271    SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
     272                     ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
     273    if (tokens.size() >= 4)
     274    {
     275        if (!ConvertValue(&(output->x), tokens[0]))
     276            return false;
     277        if (!ConvertValue(&(output->y), tokens[1]))
     278            return false;
     279        if (!ConvertValue(&(output->z), tokens[2]))
     280            return false;
     281        if (!ConvertValue(&(output->w), tokens[3]))
     282            return false;
     283
     284        return true;
     285    }
     286    return false;
     287}
     288
     289// std::string to Quaternion
     290bool ConverterFallback<std::string, orxonox::Quaternion>::convert(orxonox::Quaternion* output, const std::string& input)
     291{
     292    size_t opening_parenthesis, closing_parenthesis = input.find(')');
     293    if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
     294
     295    SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
     296    if (tokens.size() >= 4)
     297    {
     298        if (!ConvertValue(&(output->w), tokens[0]))
     299            return false;
     300        if (!ConvertValue(&(output->x), tokens[1]))
     301            return false;
     302        if (!ConvertValue(&(output->y), tokens[2]))
     303            return false;
     304        if (!ConvertValue(&(output->z), tokens[3]))
     305            return false;
     306
     307        return true;
     308    }
     309    return false;
     310}
     311
     312// std::string to ColourValue
     313bool ConverterFallback<std::string, orxonox::ColourValue>::convert(orxonox::ColourValue* output, const std::string& input)
     314{
     315    size_t opening_parenthesis, closing_parenthesis = input.find(')');
     316    if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
     317
     318    SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
     319    if (tokens.size() >= 3)
     320    {
     321        if (!ConvertValue(&(output->r), tokens[0]))
     322            return false;
     323        if (!ConvertValue(&(output->g), tokens[1]))
     324            return false;
     325        if (!ConvertValue(&(output->b), tokens[2]))
     326            return false;
     327        if (tokens.size() >= 4)
     328        {
     329            if (!ConvertValue(&(output->a), tokens[3]))
     330                return false;
     331        }
     332        else
     333            output->a = 1.0;
     334
     335        return true;
     336    }
     337    return false;
     338}
  • code/branches/objecthierarchy/src/util/MathConvert.h

    r2015 r2016  
    4747// Vector2 to std::string
    4848template <>
    49 struct ConverterExplicit<std::string, orxonox::Vector2>
     49struct ConverterExplicit<orxonox::Vector2, std::string>
    5050{
    5151    static bool convert(std::string* output, const orxonox::Vector2& input)
     
    6363// Vector3 to std::string
    6464template <>
    65 struct ConverterExplicit<std::string, orxonox::Vector3>
     65struct ConverterExplicit<orxonox::Vector3, std::string>
    6666{
    6767    static bool convert(std::string* output, const orxonox::Vector3& input)
     
    7979// Vector4 to std::string
    8080template <>
    81 struct ConverterExplicit<std::string, orxonox::Vector4>
     81struct ConverterExplicit<orxonox::Vector4, std::string>
    8282{
    8383    static bool convert(std::string* output, const orxonox::Vector4& input)
     
    9595// Quaternion to std::string
    9696template <>
    97 struct ConverterExplicit<std::string, orxonox::Quaternion>
     97struct ConverterExplicit<orxonox::Quaternion, std::string>
    9898{
    9999    static bool convert(std::string* output, const orxonox::Quaternion& input)
     
    111111// ColourValue to std::string
    112112template <>
    113 struct ConverterExplicit<std::string, orxonox::ColourValue>
     113struct ConverterExplicit<orxonox::ColourValue, std::string>
    114114{
    115115    static bool convert(std::string* output, const orxonox::ColourValue& input)
     
    131131
    132132// std::string to Vector2
    133 template <> struct _UtilExport ConverterFallback<orxonox::Vector2,     std::string>
     133template <> struct _UtilExport ConverterFallback<std::string, orxonox::Vector2>
    134134{ static bool convert(orxonox::Vector2*     output, const std::string& input); };
    135135// std::string to Vector3
    136 template <> struct _UtilExport ConverterFallback<orxonox::Vector3,     std::string>
     136template <> struct _UtilExport ConverterFallback<std::string, orxonox::Vector3>
    137137{ static bool convert(orxonox::Vector3*     output, const std::string& input); };
    138138// std::string to Vector4
    139 template <> struct _UtilExport ConverterFallback<orxonox::Vector4,     std::string>
     139template <> struct _UtilExport ConverterFallback<std::string, orxonox::Vector4>
    140140{ static bool convert(orxonox::Vector4*     output, const std::string& input); };
    141141// std::string to Quaternion
    142 template <> struct _UtilExport ConverterFallback<orxonox::Quaternion,  std::string>
     142template <> struct _UtilExport ConverterFallback<std::string, orxonox::Quaternion>
    143143{ static bool convert(orxonox::Quaternion*  output, const std::string& input); };
    144144// std::string to ColourValue
    145 template <> struct _UtilExport ConverterFallback<orxonox::ColourValue, std::string>
     145template <> struct _UtilExport ConverterFallback<std::string, orxonox::ColourValue>
    146146{ static bool convert(orxonox::ColourValue* output, const std::string& input); };
    147147
     
    153153// From Radian
    154154template <class ToType>
    155 struct ConverterFallback<ToType, orxonox::Radian>
     155struct ConverterFallback<orxonox::Radian, ToType>
    156156{
    157157    static bool convert(ToType* output, const orxonox::Radian& input)
    158158    {
    159         return convertValue<ToType, Ogre::Real>(output, input.valueRadians());
     159        return convertValue<Ogre::Real, ToType>(output, input.valueRadians());
    160160    }
    161161};
     
    163163// From Degree
    164164template <class ToType>
    165 struct ConverterFallback<ToType, orxonox::Degree>
     165struct ConverterFallback<orxonox::Degree, ToType>
    166166{
    167167    static bool convert(ToType* output, const orxonox::Degree& input)
    168168    {
    169         return convertValue<ToType, Ogre::Real>(output, input.valueDegrees());
     169        return convertValue<Ogre::Real, ToType>(output, input.valueDegrees());
    170170    }
    171171};
     
    173173// To Radian
    174174template <class FromType>
    175 struct ConverterFallback<orxonox::Radian, FromType>
     175struct ConverterFallback<FromType, orxonox::Radian>
    176176{
    177177    static bool convert(orxonox::Radian* output, const FromType& input)
     
    190190// To Degree
    191191template <class FromType>
    192 struct ConverterFallback<orxonox::Degree, FromType>
     192struct ConverterFallback<FromType, orxonox::Degree>
    193193{
    194194    static bool convert(orxonox::Degree* output, const FromType& input)
  • code/branches/objecthierarchy/src/util/MultiTypeValue.h

    r2002 r2016  
    3838
    3939#include "UtilPrereqs.h"
    40 #include "Convert.h"
     40#include "MathConvert.h"
    4141#include "MultiType.h"
    4242
  • code/branches/objecthierarchy/visual_studio/vc8/util.vcproj

    r1841 r2016  
    227227                        </File>
    228228                        <File
     229                                RelativePath="..\..\src\util\MathConvert.h"
     230                                >
     231                        </File>
     232                        <File
    229233                                RelativePath="..\..\src\util\MultiType.h"
    230234                                >
Note: See TracChangeset for help on using the changeset viewer.