Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Nov 10, 2008, 12:05:03 AM (16 years ago)
Author:
landauf
Message:

merged revisions 2111-2170 from objecthierarchy branch back to trunk.

Location:
code/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/util

  • code/trunk/src/util/Convert.h

    r2087 r2171  
    6868#endif
    6969
    70 template <class FromType, class ToType>
    71 class ImplicitConversion
    72 {
    73 private:
    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
    82 public:
    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 };
     70namespace orxonox
     71{
     72    template <class FromType, class ToType>
     73    class ImplicitConversion
     74    {
     75    private:
     76        ImplicitConversion(); ImplicitConversion(const ImplicitConversion&); ~ImplicitConversion();
     77        // Gets chosen only if there is an implicit conversion from FromType to ToType.
     78        static char test(ToType);
     79        // Accepts any argument. Why do we not use a template? The reason is that with templates,
     80        // the function above is only taken iff it is an exact type match. But since we want to
     81        // check for implicit conversion, we have to use the ellipsis.
     82        static long long test(...);
     83        static FromType object; // helper object to handle private c'tor and d'tor
     84    public:
     85        // test(object) only has 'long long' return type iff the compiler doesn't choose test(...)
     86        enum { exists = (sizeof(test(object)) == sizeof(char)) };
     87    };
     88}
    8689
    8790#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
     
    118121*/
    119122
    120 namespace
    121 {
    122     //! Little template that maps integers to entire types (Alexandrescu 2001)
    123     template <int I>
    124     struct Int2Type { };
     123namespace orxonox
     124{
     125    namespace
     126    {
     127        //! Little template that maps integers to entire types (Alexandrescu 2001)
     128        template <int I>
     129        struct Int2Type { };
     130    }
     131
     132
     133    ///////////////////
     134    // No Conversion //
     135    ///////////////////
     136
     137    // Default template. No conversion available at all.
     138    template <class FromType, class ToType>
     139    struct ConverterFallback
     140    {
     141        static bool convert(ToType* output, const FromType& input)
     142        {
     143            COUT(2) << "Could not convert value of type " << typeid(FromType).name()
     144                    << " to type " << typeid(ToType).name() << std::endl;
     145            return false;
     146        }
     147    };
     148
     149    // If all else fails, try a dynamic_cast for pointer types.
     150    template <class FromType, class ToType>
     151    struct ConverterFallback<FromType*, ToType*>
     152    {
     153        static bool convert(ToType** output, FromType* const input)
     154        {
     155            ToType* temp = dynamic_cast<ToType*>(input);
     156            if (temp)
     157            {
     158                *output = temp;
     159                return true;
     160            }
     161            else
     162                return false;
     163        }
     164    };
    125165}
    126 
    127 
    128 ///////////////////
    129 // No Conversion //
    130 ///////////////////
    131 
    132 // Default template. No conversion available at all.
    133 template <class FromType, class ToType>
    134 struct ConverterFallback
    135 {
    136     static bool convert(ToType* output, const FromType& input)
    137     {
    138         COUT(2) << "Could not convert value of type " << typeid(FromType).name()
    139                 << " to type " << typeid(ToType).name() << std::endl;
    140         return false;
    141     }
    142 };
    143 
    144 // If all else fails, try a dynamic_cast for pointer types.
    145 template <class FromType, class ToType>
    146 struct ConverterFallback<FromType*, ToType*>
    147 {
    148     static bool convert(ToType** output, FromType* const input)
    149     {
    150         ToType* temp = dynamic_cast<ToType*>(input);
    151         if (temp)
    152         {
    153             *output = temp;
    154             return true;
    155         }
    156         else
    157             return false;
    158     }
    159 };
    160166
    161167
     
    170176    static bool convert(ToType* output, const FromType& input)
    171177    {
    172         return ConverterFallback<FromType, ToType>::convert(output, input);
     178        return orxonox::ConverterFallback<FromType, ToType>::convert(output, input);
    173179    }
    174180};
     
    185191    {
    186192        std::string temp;
    187         if (ConverterFallback<FromType, std::string>::convert(&temp, input))
     193        if (orxonox::ConverterFallback<FromType, std::string>::convert(&temp, input))
    188194        {
    189195            std::operator <<(outstream, temp);
     
    224230    inline bool operator >>(std::istream& instream, ToType& output)
    225231    {
    226         return ConverterFallback<std::string, ToType>
     232        return orxonox::ConverterFallback<std::string, ToType>
    227233            ::convert(&output, static_cast<std::istringstream&>(instream).str());
    228234    }
     
    247253};
    248254
    249 
    250 ///////////////////
    251 // Implicit Cast //
    252 ///////////////////
    253 
    254 // implicit cast not possible, try stringstream conversion next
    255 template <class FromType, class ToType>
    256 inline bool convertImplicitely(ToType* output, const FromType& input, ::Int2Type<false>)
    257 {
    258     return ConverterStringStream<FromType, ToType>::convert(output, input);
     255namespace orxonox
     256{
     257
     258    ///////////////////
     259    // Implicit Cast //
     260    ///////////////////
     261
     262    // implicit cast not possible, try stringstream conversion next
     263    template <class FromType, class ToType>
     264    inline bool convertImplicitely(ToType* output, const FromType& input, orxonox::Int2Type<false>)
     265    {
     266        return ConverterStringStream<FromType, ToType>::convert(output, input);
     267    }
     268
     269    // We can cast implicitely
     270    template <class FromType, class ToType>
     271    inline bool convertImplicitely(ToType* output, const FromType& input, orxonox::Int2Type<true>)
     272    {
     273        (*output) = static_cast<ToType>(input);
     274        return true;
     275    }
     276
     277
     278    ////////////////////////////////
     279    // ConverterExplicit Fallback //
     280    ////////////////////////////////
     281
     282    // Default template if no specialisation is available
     283    template <class FromType, class ToType>
     284    struct ConverterExplicit
     285    {
     286        static bool convert(ToType* output, const FromType& input)
     287        {
     288            // Try implict cast and probe first. If a simple cast is not possible, it will not compile
     289            // We therefore have to out source it into another template function
     290            const bool probe = ImplicitConversion<FromType, ToType>::exists;
     291            return convertImplicitely(output, input, orxonox::Int2Type<probe>());
     292        }
     293    };
     294
     295
     296    //////////////////////
     297    // Public Functions //
     298    //////////////////////
     299
     300    /**
     301    @brief
     302        Converts any value to any other as long as there exists a conversion.
     303        Otherwise, the conversion will generate a runtime warning and return false.
     304        For information about the different conversion methods (user defined too), see the section
     305        'Actual conversion sequence' in this file above.
     306    */
     307    template <class FromType, class ToType>
     308    inline bool convertValue(ToType* output, const FromType& input)
     309    {
     310        return ConverterExplicit<FromType, ToType>::convert(output, input);
     311    }
     312
     313    // For compatibility reasons. The same, but with capital ConvertValue
     314    template<class FromType, class ToType>
     315    inline bool ConvertValue(ToType* output, const FromType& input)
     316    {
     317        return convertValue(output, input);
     318    }
     319
     320    // Calls convertValue and returns true if the conversion was successful.
     321    // Otherwise the fallback is used.
     322    /**
     323    @brief
     324        Converts any value to any other as long as there exists a conversion.
     325        Otherwise, the conversion will generate a runtime warning and return false.
     326        For information about the different conversion methods (user defined too), see the section
     327        'Actual conversion sequence' in this file above.
     328        If the conversion doesn't succeed, 'fallback' is written to '*output'.
     329    @param fallback
     330        A default value that gets written to '*output' if there is no conversion.
     331    */
     332    template<class FromType, class ToType>
     333    inline bool convertValue(ToType* output, const FromType& input, const ToType& fallback)
     334    {
     335        if (convertValue(output, input))
     336            return true;
     337        else
     338        {
     339            (*output) = fallback;
     340            return false;
     341        }
     342    }
     343
     344    // for compatibility reason. (capital 'c' in ConvertValue)
     345    template<class FromType, class ToType>
     346    inline bool ConvertValue(ToType* output, const FromType& input, const ToType& fallback)
     347    {
     348        return convertValue(output, input, fallback);
     349    }
     350
     351    // Directly returns the converted value, even if the conversion was not successful.
     352    template<class FromType, class ToType>
     353    inline ToType getConvertedValue(const FromType& input)
     354    {
     355        ToType output;
     356        convertValue(&output, input);
     357        return output;
     358    }
     359
     360    // Directly returns the converted value, but uses the fallback on failure.
     361    template<class FromType, class ToType>
     362    inline ToType getConvertedValue(const FromType& input, const ToType& fallback)
     363    {
     364        ToType output;
     365        convertValue(&output, input, fallback);
     366        return output;
     367    }
     368
     369    // Like getConvertedValue, but the template argument order is in reverse.
     370    // That means you can call it exactly like static_cast<ToType>(fromTypeValue).
     371    template<class ToType, class FromType>
     372    inline ToType omni_cast(const FromType& input)
     373    {
     374        ToType output;
     375        convertValue(&output, input);
     376        return output;
     377    }
     378
     379    // convert to string Shortcut
     380    template <class FromType>
     381    inline std::string convertToString(FromType value)
     382    {
     383      return getConvertedValue<FromType, std::string>(value);
     384    }
     385
     386    // convert from string Shortcut
     387    template <class ToType>
     388    inline ToType convertFromString(std::string str)
     389    {
     390      return getConvertedValue<std::string, ToType>(str);
     391    }
     392
     393    ////////////////////////////////
     394    // Special string conversions //
     395    ////////////////////////////////
     396
     397    // Delegate conversion from const char* to std::string
     398    template <class ToType>
     399    struct ConverterExplicit<const char*, ToType>
     400    {
     401        static bool convert(ToType* output, const char* input)
     402        {
     403            return convertValue<std::string, ToType>(output, input);
     404        }
     405    };
     406
     407    // These conversions would exhibit ambiguous << or >> operators when using stringstream
     408    template <>
     409    struct ConverterExplicit<char, std::string>
     410    {
     411        static bool convert(std::string* output, const char input)
     412        {
     413            *output = std::string(1, input);
     414            return true;
     415        }
     416    };
     417    template <>
     418    struct ConverterExplicit<unsigned char, std::string>
     419    {
     420        static bool convert(std::string* output, const unsigned char input)
     421        {
     422            *output = std::string(1, input);
     423            return true;
     424        }
     425    };
     426    template <>
     427    struct ConverterExplicit<std::string, char>
     428    {
     429        static bool convert(char* output, const std::string input)
     430        {
     431            if (input != "")
     432                *output = input[0];
     433            else
     434                *output = '\0';
     435            return true;
     436        }
     437    };
     438    template <>
     439    struct ConverterExplicit<std::string, unsigned char>
     440    {
     441        static bool convert(unsigned char* output, const std::string input)
     442        {
     443            if (input != "")
     444                *output = input[0];
     445            else
     446                *output = '\0';
     447            return true;
     448        }
     449    };
     450
     451
     452    // bool to std::string
     453    template <>
     454    struct ConverterExplicit<bool, std::string>
     455    {
     456        static bool convert(std::string* output, const bool& input)
     457        {
     458            if (input)
     459              *output = "true";
     460            else
     461              *output = "false";
     462            return false;
     463        }
     464    };
     465
     466    // std::string to bool
     467    template <>
     468    struct ConverterExplicit<std::string, bool>
     469    {
     470        static bool convert(bool* output, const std::string& input)
     471        {
     472            std::string stripped = getLowercase(removeTrailingWhitespaces(input));
     473            if (stripped == "true" || stripped == "on" || stripped == "yes")
     474            {
     475              *output = true;
     476              return true;
     477            }
     478            else if (stripped == "false" || stripped == "off" || stripped == "no")
     479            {
     480              *output = false;
     481              return true;
     482            }
     483
     484            std::istringstream iss(input);
     485            if (iss >> (*output))
     486                return true;
     487            else
     488                return false;
     489        }
     490    };
    259491}
    260492
    261 // We can cast implicitely
    262 template <class FromType, class ToType>
    263 inline bool convertImplicitely(ToType* output, const FromType& input, ::Int2Type<true>)
    264 {
    265     (*output) = static_cast<ToType>(input);
    266     return true;
    267 }
    268 
    269 
    270 ////////////////////////////////
    271 // ConverterExplicit Fallback //
    272 ////////////////////////////////
    273 
    274 // Default template if no specialisation is available
    275 template <class FromType, class ToType>
    276 struct ConverterExplicit
    277 {
    278     static bool convert(ToType* output, const FromType& input)
    279     {
    280         // Try implict cast and probe first. If a simple cast is not possible, it will not compile
    281         // We therefore have to out source it into another template function
    282         const bool probe = ImplicitConversion<FromType, ToType>::exists;
    283         return convertImplicitely(output, input, ::Int2Type<probe>());
    284     }
    285 };
    286 
    287 
    288 //////////////////////
    289 // Public Functions //
    290 //////////////////////
    291 
    292 /**
    293 @brief
    294     Converts any value to any other as long as there exists a conversion.
    295     Otherwise, the conversion will generate a runtime warning and return false.
    296     For information about the different conversion methods (user defined too), see the section
    297     'Actual conversion sequence' in this file above.
    298 */
    299 template <class FromType, class ToType>
    300 inline bool convertValue(ToType* output, const FromType& input)
    301 {
    302     return ConverterExplicit<FromType, ToType>::convert(output, input);
    303 }
    304 
    305 // For compatibility reasons. The same, but with capital ConvertValue
    306 template<class FromType, class ToType>
    307 inline bool ConvertValue(ToType* output, const FromType& input)
    308 {
    309     return convertValue(output, input);
    310 }
    311 
    312 // Calls convertValue and returns true if the conversion was successful.
    313 // Otherwise the fallback is used.
    314 /**
    315 @brief
    316     Converts any value to any other as long as there exists a conversion.
    317     Otherwise, the conversion will generate a runtime warning and return false.
    318     For information about the different conversion methods (user defined too), see the section
    319     'Actual conversion sequence' in this file above.
    320     If the conversion doesn't succeed, 'fallback' is written to '*output'.
    321 @param fallback
    322     A default value that gets written to '*output' if there is no conversion.
    323 */
    324 template<class FromType, class ToType>
    325 inline bool convertValue(ToType* output, const FromType& input, const ToType& fallback)
    326 {
    327     if (convertValue(output, input))
    328         return true;
    329     else
    330     {
    331         (*output) = fallback;
    332         return false;
    333     }
    334 }
    335 
    336 // for compatibility reason. (capital 'c' in ConvertValue)
    337 template<class FromType, class ToType>
    338 inline bool ConvertValue(ToType* output, const FromType& input, const ToType& fallback)
    339 {
    340     return convertValue(output, input, fallback);
    341 }
    342 
    343 // Directly returns the converted value, even if the conversion was not successful.
    344 template<class FromType, class ToType>
    345 inline ToType getConvertedValue(const FromType& input)
    346 {
    347     ToType output;
    348     convertValue(&output, input);
    349     return output;
    350 }
    351 
    352 // Directly returns the converted value, but uses the fallback on failure.
    353 template<class FromType, class ToType>
    354 inline ToType getConvertedValue(const FromType& input, const ToType& fallback)
    355 {
    356     ToType output;
    357     convertValue(&output, input, fallback);
    358     return output;
    359 }
    360 
    361 // Like getConvertedValue, but the template argument order is in reverse.
    362 // That means you can call it exactly like static_cast<ToType>(fromTypeValue).
    363 template<class ToType, class FromType>
    364 inline ToType omni_cast(const FromType& input)
    365 {
    366     ToType output;
    367     convertValue(&output, input);
    368     return output;
    369 }
    370 
    371 // convert to string Shortcut
    372 template <class FromType>
    373 inline std::string convertToString(FromType value)
    374 {
    375   return getConvertedValue<FromType, std::string>(value);
    376 }
    377 
    378 // convert from string Shortcut
    379 template <class ToType>
    380 inline ToType convertFromString(std::string str)
    381 {
    382   return getConvertedValue<std::string, ToType>(str);
    383 }
    384 
    385 ////////////////////////////////
    386 // Special string conversions //
    387 ////////////////////////////////
    388 
    389 // Delegate conversion from const char* to std::string
    390 template <class ToType>
    391 struct ConverterExplicit<const char*, ToType>
    392 {
    393     static bool convert(ToType* output, const char* input)
    394     {
    395         return convertValue<std::string, ToType>(output, input);
    396     }
    397 };
    398 
    399 // These conversions would exhibit ambiguous << or >> operators when using stringstream
    400 template <>
    401 struct ConverterExplicit<char, std::string>
    402 {
    403     static bool convert(std::string* output, const char input)
    404     {
    405         *output = std::string(1, input);
    406         return true;
    407     }
    408 };
    409 template <>
    410 struct ConverterExplicit<unsigned char, std::string>
    411 {
    412     static bool convert(std::string* output, const unsigned char input)
    413     {
    414         *output = std::string(1, input);
    415         return true;
    416     }
    417 };
    418 template <>
    419 struct ConverterExplicit<std::string, char>
    420 {
    421     static bool convert(char* output, const std::string input)
    422     {
    423         if (input != "")
    424             *output = input[0];
    425         else
    426             *output = '\0';
    427         return true;
    428     }
    429 };
    430 template <>
    431 struct ConverterExplicit<std::string, unsigned char>
    432 {
    433     static bool convert(unsigned char* output, const std::string input)
    434     {
    435         if (input != "")
    436             *output = input[0];
    437         else
    438             *output = '\0';
    439         return true;
    440     }
    441 };
    442 
    443 
    444 // bool to std::string
    445 template <>
    446 struct ConverterExplicit<bool, std::string>
    447 {
    448     static bool convert(std::string* output, const bool& input)
    449     {
    450         if (input)
    451           *output = "true";
    452         else
    453           *output = "false";
    454         return false;
    455     }
    456 };
    457 
    458 // std::string to bool
    459 template <>
    460 struct ConverterExplicit<std::string, bool>
    461 {
    462     static bool convert(bool* output, const std::string& input)
    463     {
    464         std::string stripped = getLowercase(removeTrailingWhitespaces(input));
    465         if (stripped == "true" || stripped == "on" || stripped == "yes")
    466         {
    467           *output = true;
    468           return true;
    469         }
    470         else if (stripped == "false" || stripped == "off" || stripped == "no")
    471         {
    472           *output = false;
    473           return true;
    474         }
    475 
    476         std::istringstream iss(input);
    477         if (iss >> (*output))
    478             return true;
    479         else
    480             return false;
    481     }
    482 };
    483 
    484493#endif /* _Convert_H__ */
Note: See TracChangeset for help on using the changeset viewer.