Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Jul 20, 2010, 2:08:28 PM (14 years ago)
Author:
rgrieder
Message:

Reduced a dependency in util.

Location:
code/branches/presentation3/src/libraries
Files:
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • code/branches/presentation3/src/libraries/core/ConfigFileManager.cc

    r6536 r7155  
    3333#include "util/Convert.h"
    3434#include "util/Math.h"
     35#include "util/StringUtils.h"
    3536#include "ConsoleCommand.h"
    3637#include "ConfigValueContainer.h"
  • code/branches/presentation3/src/libraries/core/ConfigFileManager.h

    r6536 r7155  
    3939
    4040#include "util/Singleton.h"
    41 #include "util/StringUtils.h"
    4241
    4342namespace orxonox // tolua_export
  • code/branches/presentation3/src/libraries/util/CMakeLists.txt

    r7135 r7155  
    2727  Clipboard.cc
    2828  Clock.cc
     29  Convert.cc
    2930  CRC32.cc
    3031  ExprParser.cc
  • code/branches/presentation3/src/libraries/util/Convert.cc

    r7141 r7155  
    2323 *      Reto Grieder
    2424 *      Fabian 'x3n' Landau
    25  *      Benjamin Grauer
    2625 *   Co-authors:
    2726 *      ...
    2827 */
    2928
    30 /*!
    31     @file
    32     @brief Definition and Implementation of the Convert class.
    33 */
    34 
    35 #ifndef _Converter_H__
    36 #define _Converter_H__
    37 
    38 #include "UtilPrereqs.h"
    39 
    40 #include <string>
    41 #include <sstream>
    42 #include <typeinfo>
    43 
    44 #include "Debug.h"
    45 #include "TemplateUtils.h"
    46 
    47 ////////////////////////////////////
    48 //// ACTUAL CONVERSION SEQUENCE ////
    49 ////////////////////////////////////
    50 /*
    51     There is a distinct priority when choosing the right conversion function:
    52     Overwrite:
    53     1. (Partial) template specialisation of ConverterExplicit::convert()
    54     Fallbacks:
    55     2. Any possible implicit conversion. This includes 'FooBar' --> 'int' if FooBar defines operator float().
    56     3. Global or member operators for stringstream when converting from or to std::string (or FROM const char*)
    57     4. (Partial) template specialisation of ConverterFallback::convert()
    58     5. Function that simply displays "Could not convert value" with type information obtained from typeid().
    59 
    60     Notes:
    61     There has to be an exact type match when using template specialisations.
    62     Template specialisations can be defined after including this file. Any implicit cast function or iostream
    63     operator has to be declared BEFORE this file gets parsed.
    64 
    65     Defining your own functions:
    66     There are obviously 4 ways to specifiy a user defined conversion. What should I use?
    67 
    68     Usually, ConverterFallback fits quite well. You won't have to deal with the conversion from
    69     'MyClass' to 'MyClass' by using another explicit template specialisation to avoid ambiguities.
    70 
    71     However if you want to overwrite an implicit conversion or an iostream operator, you really need to
    72     make use of ConverterExplicit.
    73 */
     29#include "Convert.h"
     30#include "StringUtils.h"
    7431
    7532namespace orxonox
    7633{
    77     namespace detail
     34    //template <class FromType, class ToType>
     35    bool ConverterExplicit<std::string, bool>::convert(bool* output, const std::string& input)
    7836    {
    79         //! Little template that maps integers to entire types (Alexandrescu 2001)
    80         template <int I>
    81         struct Int2Type { };
    82     }
    83 
    84 
    85     ///////////////////
    86     // No Conversion //
    87     ///////////////////
    88 
    89     // Default template. No conversion available at all.
    90     template <class FromType, class ToType>
    91     struct ConverterFallback
    92     {
    93         FORCEINLINE static bool convert(ToType* output, const FromType& input)
     37        const std::string& stripped = getLowercase(removeTrailingWhitespaces(input));
     38        if (stripped == "true" || stripped == "on" || stripped == "yes")
    9439        {
    95             COUT(2) << "Could not convert value of type " << typeid(FromType).name()
    96                     << " to type " << typeid(ToType).name() << std::endl;
    97             return false;
    98         }
    99     };
    100 
    101     // If all else fails, try a dynamic_cast for pointer types.
    102     template <class FromType, class ToType>
    103     struct ConverterFallback<FromType*, ToType*>
    104     {
    105         FORCEINLINE static bool convert(ToType** output, FromType* const input)
    106         {
    107             ToType* temp = dynamic_cast<ToType*>(input);
    108             if (temp)
    109             {
    110                 *output = temp;
    111                 return true;
    112             }
    113             else
    114                 return false;
    115         }
    116     };
    117 }
    118 
    119 
    120 ///////////////////////
    121 // ConverterFallback //
    122 ///////////////////////
    123 
    124 // Default template for stringstream
    125 template <class FromType, class ToType>
    126 struct ConverterStringStream
    127 {
    128     FORCEINLINE static bool convert(ToType* output, const FromType& input)
    129     {
    130         return orxonox::ConverterFallback<FromType, ToType>::convert(output, input);
    131     }
    132 };
    133 
    134 
    135 /////////////
    136 // OStream //
    137 /////////////
    138 
    139 namespace fallbackTemplates
    140 {
    141     template <class FromType>
    142     FORCEINLINE bool operator <<(std::ostream& outstream,  const FromType& input)
    143     {
    144         std::string temp;
    145         if (orxonox::ConverterFallback<FromType, std::string>::convert(&temp, input))
    146         {
    147             std::operator <<(outstream, temp);
     40            *output = true;
    14841            return true;
    14942        }
     43        else if (stripped == "false" || stripped == "off" || stripped == "no")
     44        {
     45            *output = false;
     46            return true;
     47        }
     48
     49        std::istringstream iss(input);
     50        if (iss >> (*output))
     51            return true;
    15052        else
    15153            return false;
    15254    }
    15355}
    154 
    155 // template that evaluates whether we can convert to std::string via ostringstream
    156 template <class FromType>
    157 struct ConverterStringStream<FromType, std::string>
    158 {
    159     FORCEINLINE static bool convert(std::string* output, const FromType& input)
    160     {
    161         using namespace fallbackTemplates;
    162         // this operator call only chooses fallbackTemplates::operator<< if there's no other fitting function
    163         std::ostringstream oss;
    164         if (oss << input)
    165         {
    166             (*output) = oss.str();
    167             return true;
    168         }
    169         else
    170             return false;
    171     }
    172 };
    173 
    174 
    175 /////////////
    176 // IStream //
    177 /////////////
    178 
    179 namespace fallbackTemplates
    180 {
    181     template <class ToType>
    182     FORCEINLINE bool operator >>(std::istream& instream, ToType& output)
    183     {
    184         return orxonox::ConverterFallback<std::string, ToType>
    185             ::convert(&output, static_cast<std::istringstream&>(instream).str());
    186     }
    187 }
    188 
    189 // template that evaluates whether we can convert from std::string via ostringstream
    190 template <class ToType>
    191 struct ConverterStringStream<std::string, ToType>
    192 {
    193     FORCEINLINE static bool convert(ToType* output, const std::string& input)
    194     {
    195         using namespace fallbackTemplates;
    196         std::istringstream iss(input);
    197         // this operator call only chooses fallbackTemplates::operator>> if there's no other fitting function
    198         if (iss >> (*output))
    199         {
    200             return true;
    201         }
    202         else
    203             return false;
    204     }
    205 };
    206 
    207 namespace orxonox
    208 {
    209 
    210     ///////////////////
    211     // Implicit Cast //
    212     ///////////////////
    213 
    214     // implicit cast not possible, try stringstream conversion next
    215     template <class FromType, class ToType>
    216     FORCEINLINE bool convertImplicitely(ToType* output, const FromType& input, detail::Int2Type<false>)
    217     {
    218         return ConverterStringStream<FromType, ToType>::convert(output, input);
    219     }
    220 
    221     // We can cast implicitely
    222     template <class FromType, class ToType>
    223     FORCEINLINE bool convertImplicitely(ToType* output, const FromType& input, detail::Int2Type<true>)
    224     {
    225         (*output) = static_cast<ToType>(input);
    226         return true;
    227     }
    228 
    229 
    230     ////////////////////////////////
    231     // ConverterExplicit Fallback //
    232     ////////////////////////////////
    233 
    234     // Default template if no specialisation is available
    235     template <class FromType, class ToType>
    236     struct ConverterExplicit
    237     {
    238         enum { probe = ImplicitConversion<FromType, ToType>::exists };
    239         FORCEINLINE static bool convert(ToType* output, const FromType& input)
    240         {
    241             // Try implict cast and probe first. If a simple cast is not possible, it will not compile
    242             // We therefore have to out source it into another template function
    243             return convertImplicitely(output, input, detail::Int2Type<probe>());
    244         }
    245     };
    246 
    247 
    248     //////////////////////
    249     // Public Functions //
    250     //////////////////////
    251 
    252     /**
    253     @brief
    254         Converts any value to any other as long as there exists a conversion.
    255         Otherwise, the conversion will generate a runtime warning and return false.
    256         For information about the different conversion methods (user defined too), see the section
    257         'Actual conversion sequence' in this file above.
    258     */
    259     template <class FromType, class ToType>
    260     FORCEINLINE bool convertValue(ToType* output, const FromType& input)
    261     {
    262         return ConverterExplicit<FromType, ToType>::convert(output, input);
    263     }
    264 
    265     // Calls convertValue and returns true if the conversion was successful.
    266     // Otherwise the fallback is used.
    267     /**
    268     @brief
    269         Converts any value to any other as long as there exists a conversion.
    270         Otherwise, the conversion will generate a runtime warning and return false.
    271         For information about the different conversion methods (user defined too), see the section
    272         'Actual conversion sequence' in this file above.
    273         If the conversion doesn't succeed, 'fallback' is written to '*output'.
    274     @param fallback
    275         A default value that gets written to '*output' if there is no conversion.
    276     */
    277     template<class FromType, class ToType>
    278     FORCEINLINE bool convertValue(ToType* output, const FromType& input, const ToType& fallback)
    279     {
    280         if (convertValue(output, input))
    281             return true;
    282         else
    283         {
    284             (*output) = fallback;
    285             return false;
    286         }
    287     }
    288 
    289     // Directly returns the converted value, even if the conversion was not successful.
    290     template<class FromType, class ToType>
    291     FORCEINLINE ToType getConvertedValue(const FromType& input)
    292     {
    293         ToType output;
    294         convertValue(&output, input);
    295         return output;
    296     }
    297 
    298     // Directly returns the converted value, but uses the fallback on failure.
    299     template<class FromType, class ToType>
    300     FORCEINLINE ToType getConvertedValue(const FromType& input, const ToType& fallback)
    301     {
    302         ToType output;
    303         convertValue(&output, input, fallback);
    304         return output;
    305     }
    306 
    307     // Like getConvertedValue, but the template argument order is in reverse.
    308     // That means you can call it exactly like static_cast<ToType>(fromTypeValue).
    309     template<class ToType, class FromType>
    310     FORCEINLINE ToType multi_cast(const FromType& input)
    311     {
    312         ToType output;
    313         convertValue(&output, input);
    314         return output;
    315     }
    316 
    317     ////////////////////////////////
    318     // Special string conversions //
    319     ////////////////////////////////
    320 
    321     // Delegate conversion from const char* to std::string
    322     template <class ToType>
    323     struct ConverterExplicit<const char*, ToType>
    324     {
    325         FORCEINLINE static bool convert(ToType* output, const char* input)
    326         {
    327             return convertValue<std::string, ToType>(output, input);
    328         }
    329     };
    330 
    331     // These conversions would exhibit ambiguous << or >> operators when using stringstream
    332     template <>
    333     struct ConverterExplicit<char, std::string>
    334     {
    335         FORCEINLINE static bool convert(std::string* output, const char input)
    336         {
    337             *output = input;
    338             return true;
    339         }
    340     };
    341     template <>
    342     struct ConverterExplicit<unsigned char, std::string>
    343     {
    344         FORCEINLINE static bool convert(std::string* output, const unsigned char input)
    345         {
    346             *output = input;
    347             return true;
    348         }
    349     };
    350     template <>
    351     struct ConverterExplicit<std::string, char>
    352     {
    353         FORCEINLINE static bool convert(char* output, const std::string& input)
    354         {
    355             if (!input.empty())
    356                 *output = input[0];
    357             else
    358                 *output = '\0';
    359             return true;
    360         }
    361     };
    362     template <>
    363     struct ConverterExplicit<std::string, unsigned char>
    364     {
    365         FORCEINLINE static bool convert(unsigned char* output, const std::string& input)
    366         {
    367             if (!input.empty())
    368                 *output = input[0];
    369             else
    370                 *output = '\0';
    371             return true;
    372         }
    373     };
    374 
    375 
    376     // bool to std::string
    377     template <>
    378     struct ConverterExplicit<bool, std::string>
    379     {
    380         FORCEINLINE static bool convert(std::string* output, const bool& input)
    381         {
    382             if (input)
    383               *output = "true";
    384             else
    385               *output = "false";
    386             return true;
    387         }
    388     };
    389 
    390     // Declarations to avoid StringUtils.h include
    391     _UtilExport std::string removeTrailingWhitespaces(const std::string& str);
    392     _UtilExport std::string getLowercase(const std::string& str);
    393 
    394     // std::string to bool
    395     template <>
    396     struct ConverterExplicit<std::string, bool>
    397     {
    398         static bool convert(bool* output, const std::string& input)
    399         {
    400             const std::string& stripped = getLowercase(removeTrailingWhitespaces(input));
    401             if (stripped == "true" || stripped == "on" || stripped == "yes")
    402             {
    403                 *output = true;
    404                 return true;
    405             }
    406             else if (stripped == "false" || stripped == "off" || stripped == "no")
    407             {
    408                 *output = false;
    409                 return true;
    410             }
    411 
    412             std::istringstream iss(input);
    413             if (iss >> (*output))
    414                 return true;
    415             else
    416                 return false;
    417         }
    418     };
    419 }
    420 
    421 #endif /* _Convert_H__ */
  • code/branches/presentation3/src/libraries/util/Convert.h

    r6417 r7155  
    6464
    6565    Defining your own functions:
    66     There are obviously 4 ways to specifiy a user defined conversion. What should I use?
     66    There are obviously 4 ways to specify a user defined conversion. What should you use?
    6767
    6868    Usually, ConverterFallback fits quite well. You won't have to deal with the conversion from
     
    7070
    7171    However if you want to overwrite an implicit conversion or an iostream operator, you really need to
    72     make use of ConverterExplicit.
     72    make use of ConverterExplicit. We have to do this for the Ogre classes for instance because they
     73    define stream operators we don't particulary like.
    7374*/
    7475
     
    388389    };
    389390
    390     // Declarations to avoid StringUtils.h include
    391     _UtilExport std::string removeTrailingWhitespaces(const std::string& str);
    392     _UtilExport std::string getLowercase(const std::string& str);
    393 
    394391    // std::string to bool
    395392    template <>
    396     struct ConverterExplicit<std::string, bool>
    397     {
    398         static bool convert(bool* output, const std::string& input)
    399         {
    400             const std::string& stripped = getLowercase(removeTrailingWhitespaces(input));
    401             if (stripped == "true" || stripped == "on" || stripped == "yes")
    402             {
    403                 *output = true;
    404                 return true;
    405             }
    406             else if (stripped == "false" || stripped == "off" || stripped == "no")
    407             {
    408                 *output = false;
    409                 return true;
    410             }
    411 
    412             std::istringstream iss(input);
    413             if (iss >> (*output))
    414                 return true;
    415             else
    416                 return false;
    417         }
     393    struct _UtilExport ConverterExplicit<std::string, bool>
     394    {
     395        static bool convert(bool* output, const std::string& input);
    418396    };
    419397}
Note: See TracChangeset for help on using the changeset viewer.