Changeset 2016 for code/branches
- Timestamp:
- Oct 26, 2008, 1:54:15 AM (16 years ago)
- Location:
- code/branches/objecthierarchy
- Files:
-
- 5 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
code/branches/objecthierarchy/src/util
-
Property
svn:mergeinfo
set to
(toggle deleted branches)
/code/branches/ceguilua/src/util merged eligible /code/branches/core3/src/util merged eligible /code/branches/gui/src/util merged eligible /code/branches/script_trigger/src/util merged eligible /code/branches/gcc43/src/util 1580 /code/branches/input/src/util 1629-1636
-
Property
svn:mergeinfo
set to
(toggle deleted branches)
-
code/branches/objecthierarchy/src/util/Convert.h
r1889 r2016 21 21 * 22 22 * Author: 23 * Reto Grieder 23 24 * Fabian 'x3n' Landau 24 25 * Benjamin Grauer … … 28 29 29 30 /*! 30 @file Convert.h31 @file 31 32 @brief Definition and Implementation of the Convert class. 32 33 */ 33 34 34 #ifndef _Convert _H__35 #define _Convert _H__35 #ifndef _Converter_H__ 36 #define _Converter_H__ 36 37 37 38 #include "UtilPrereqs.h" … … 39 40 #include <string> 40 41 #include <sstream> 42 #include <istream> 43 #include <ostream> 41 44 #include <typeinfo> 42 45 43 #include "Math.h"44 46 #include "Debug.h" 45 #include "SubString.h"46 47 #include "String.h" 47 48 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 49 65 #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) 52 68 #endif 53 69 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 }; 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 }; 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 120 namespace 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. 133 template <class FromType, class ToType> 134 struct ConverterFallback 135 { 77 136 static bool convert(ToType* output, const FromType& input) 78 137 { 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; 80 140 return false; 81 141 } … … 83 143 84 144 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 150 template <class FromType, class ToType> 151 struct ConverterStringStream 145 152 { 146 153 static bool convert(ToType* output, const FromType& input) 147 154 { 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 254 159 255 160 ///////////// 256 // SAMPLES//161 // OStream // 257 162 ///////////// 258 /* 259 // convert everything to xyz 163 164 namespace 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 260 181 template <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 }; 182 struct ConverterStringStream<FromType, std::string> 183 { 296 184 static bool convert(std::string* output, const FromType& input) 297 185 { 186 using namespace fallbackTemplates; 187 // this operator call only chooses fallbackTemplates::operator<< if there's no other fitting function 298 188 std::ostringstream oss; 299 189 if (oss << input) … … 307 197 }; 308 198 199 200 ///////////// 201 // IStream // 202 ///////////// 203 204 namespace 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 215 template <class ToType> 216 struct 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 238 template <class FromType, class ToType> 239 inline 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 245 template <class FromType, class ToType> 246 inline 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 258 template <class FromType, class ToType> 259 struct 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 */ 282 template <class FromType, class ToType> 283 inline 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 289 template<class FromType, class ToType> 290 inline 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 */ 307 template<class FromType, class ToType> 308 inline 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) 320 template<class FromType, class ToType> 321 inline 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. 327 template<class FromType, class ToType> 328 inline 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. 336 template<class FromType, class ToType> 337 inline 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). 346 template<class ToType, class FromType> 347 inline ToType conversion_cast(const FromType& input) 348 { 349 ToType output; 350 convertValue(&output, input); 351 return output; 352 } 353 309 354 // convert to string Shortcut 310 355 template <class FromType> … … 314 359 } 315 360 316 // convert from string317 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 else327 return false;328 }329 };330 331 361 // convert from string Shortcut 332 362 template <class ToType> … … 336 366 } 337 367 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 373 template <class ToType> 374 struct 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 383 template <> 384 struct 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 }; 392 template <> 393 struct 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 }; 401 template <> 402 struct 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 }; 413 template <> 414 struct 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 374 426 375 427 // bool to std::string 376 428 template <> 377 struct ConverterSpecialized<bool, std::string, _Explicit_> 378 { 379 enum { specialized = true }; 429 struct ConverterExplicit<bool, std::string> 430 { 380 431 static bool convert(std::string* output, const bool& input) 381 432 { … … 388 439 }; 389 440 390 // Vector2 to std::string391 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::string408 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::string425 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::string442 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::string459 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 480 441 // std::string to bool 481 442 template <> 482 struct ConverterSpecialized<std::string, bool, _Explicit_> 483 { 484 enum { specialized = true }; 443 struct ConverterExplicit<std::string, bool> 444 { 485 445 static bool convert(bool* output, const std::string& input) 486 446 { … … 505 465 }; 506 466 507 // std::string to Vector2508 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 Vector3532 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 Vector4558 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 Quaternion586 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 ColourValue614 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 else638 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 @note654 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 StaticConversion659 {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_MSVC670 #pragma warning(pop)671 #endif672 673 467 #endif /* _Convert_H__ */ -
code/branches/objecthierarchy/src/util/Math.cc
r1791 r2016 28 28 29 29 /** 30 @file Math.cc30 @file 31 31 @brief Implementation of several math-functions. 32 32 */ 33 33 34 #include "Math.h" 35 34 36 #include <OgrePlane.h> 35 36 #include "Math.h" 37 #include "Convert.h" 37 #include "MathConvert.h" 38 #include "SubString.h" 38 39 39 40 /** … … 205 206 return convertToString(getUniqueNumber()); 206 207 } 208 209 210 ////////////////////////// 211 // Conversion functions // 212 ////////////////////////// 213 214 // std::string to Vector2 215 bool 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 238 bool 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 263 bool 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 290 bool 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 313 bool 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 47 47 // Vector2 to std::string 48 48 template <> 49 struct ConverterExplicit< std::string, orxonox::Vector2>49 struct ConverterExplicit<orxonox::Vector2, std::string> 50 50 { 51 51 static bool convert(std::string* output, const orxonox::Vector2& input) … … 63 63 // Vector3 to std::string 64 64 template <> 65 struct ConverterExplicit< std::string, orxonox::Vector3>65 struct ConverterExplicit<orxonox::Vector3, std::string> 66 66 { 67 67 static bool convert(std::string* output, const orxonox::Vector3& input) … … 79 79 // Vector4 to std::string 80 80 template <> 81 struct ConverterExplicit< std::string, orxonox::Vector4>81 struct ConverterExplicit<orxonox::Vector4, std::string> 82 82 { 83 83 static bool convert(std::string* output, const orxonox::Vector4& input) … … 95 95 // Quaternion to std::string 96 96 template <> 97 struct ConverterExplicit< std::string, orxonox::Quaternion>97 struct ConverterExplicit<orxonox::Quaternion, std::string> 98 98 { 99 99 static bool convert(std::string* output, const orxonox::Quaternion& input) … … 111 111 // ColourValue to std::string 112 112 template <> 113 struct ConverterExplicit< std::string, orxonox::ColourValue>113 struct ConverterExplicit<orxonox::ColourValue, std::string> 114 114 { 115 115 static bool convert(std::string* output, const orxonox::ColourValue& input) … … 131 131 132 132 // std::string to Vector2 133 template <> struct _UtilExport ConverterFallback< orxonox::Vector2, std::string>133 template <> struct _UtilExport ConverterFallback<std::string, orxonox::Vector2> 134 134 { static bool convert(orxonox::Vector2* output, const std::string& input); }; 135 135 // std::string to Vector3 136 template <> struct _UtilExport ConverterFallback< orxonox::Vector3, std::string>136 template <> struct _UtilExport ConverterFallback<std::string, orxonox::Vector3> 137 137 { static bool convert(orxonox::Vector3* output, const std::string& input); }; 138 138 // std::string to Vector4 139 template <> struct _UtilExport ConverterFallback< orxonox::Vector4, std::string>139 template <> struct _UtilExport ConverterFallback<std::string, orxonox::Vector4> 140 140 { static bool convert(orxonox::Vector4* output, const std::string& input); }; 141 141 // std::string to Quaternion 142 template <> struct _UtilExport ConverterFallback< orxonox::Quaternion, std::string>142 template <> struct _UtilExport ConverterFallback<std::string, orxonox::Quaternion> 143 143 { static bool convert(orxonox::Quaternion* output, const std::string& input); }; 144 144 // std::string to ColourValue 145 template <> struct _UtilExport ConverterFallback< orxonox::ColourValue, std::string>145 template <> struct _UtilExport ConverterFallback<std::string, orxonox::ColourValue> 146 146 { static bool convert(orxonox::ColourValue* output, const std::string& input); }; 147 147 … … 153 153 // From Radian 154 154 template <class ToType> 155 struct ConverterFallback< ToType, orxonox::Radian>155 struct ConverterFallback<orxonox::Radian, ToType> 156 156 { 157 157 static bool convert(ToType* output, const orxonox::Radian& input) 158 158 { 159 return convertValue< ToType, Ogre::Real>(output, input.valueRadians());159 return convertValue<Ogre::Real, ToType>(output, input.valueRadians()); 160 160 } 161 161 }; … … 163 163 // From Degree 164 164 template <class ToType> 165 struct ConverterFallback< ToType, orxonox::Degree>165 struct ConverterFallback<orxonox::Degree, ToType> 166 166 { 167 167 static bool convert(ToType* output, const orxonox::Degree& input) 168 168 { 169 return convertValue< ToType, Ogre::Real>(output, input.valueDegrees());169 return convertValue<Ogre::Real, ToType>(output, input.valueDegrees()); 170 170 } 171 171 }; … … 173 173 // To Radian 174 174 template <class FromType> 175 struct ConverterFallback< orxonox::Radian, FromType>175 struct ConverterFallback<FromType, orxonox::Radian> 176 176 { 177 177 static bool convert(orxonox::Radian* output, const FromType& input) … … 190 190 // To Degree 191 191 template <class FromType> 192 struct ConverterFallback< orxonox::Degree, FromType>192 struct ConverterFallback<FromType, orxonox::Degree> 193 193 { 194 194 static bool convert(orxonox::Degree* output, const FromType& input) -
code/branches/objecthierarchy/src/util/MultiTypeValue.h
r2002 r2016 38 38 39 39 #include "UtilPrereqs.h" 40 #include " Convert.h"40 #include "MathConvert.h" 41 41 #include "MultiType.h" 42 42 -
code/branches/objecthierarchy/visual_studio/vc8/util.vcproj
r1841 r2016 227 227 </File> 228 228 <File 229 RelativePath="..\..\src\util\MathConvert.h" 230 > 231 </File> 232 <File 229 233 RelativePath="..\..\src\util\MultiType.h" 230 234 >
Note: See TracChangeset
for help on using the changeset viewer.