00001 /* 00002 * The information in this file is 00003 * Copyright(c) 2007 Ball Aerospace & Technologies Corporation 00004 * and is subject to the terms and conditions of the 00005 * GNU Lesser General Public License Version 2.1 00006 * The license text is available from 00007 * http://www.gnu.org/licenses/lgpl.html 00008 */ 00009 00010 #ifndef DATAVARIANT_H 00011 #define DATAVARIANT_H 00012 00013 #include <string> 00014 #include <typeinfo> 00015 #include <vector> 00016 00017 #include "AppVerify.h" 00018 #include "AppConfig.h" 00019 #include "DataVariantValidator.h" 00020 #include "EnumWrapper.h" 00021 #include "XercesIncludes.h" 00022 00023 class DataValueWrapper; 00024 00025 using XERCES_CPP_NAMESPACE_QUALIFIER DOMNode; 00026 class XMLWriter; 00027 00028 /** 00029 * \cond INTERNAL 00030 * These template specializations are required to allow these types to be put into a DataVariant. 00031 */ 00032 template <> class VariantTypeValidator<unsigned char> {}; 00033 template <> class VariantTypeValidator<signed char> {}; 00034 template <> class VariantTypeValidator<char> {}; 00035 template <> class VariantTypeValidator<unsigned short> {}; 00036 template <> class VariantTypeValidator<short> {}; 00037 template <> class VariantTypeValidator<unsigned int> {}; 00038 template <> class VariantTypeValidator<int> {}; 00039 template <> class VariantTypeValidator<unsigned long> {}; 00040 template <> class VariantTypeValidator<long> {}; 00041 #ifdef WIN_API 00042 template <> class VariantTypeValidator<uint64_t> {}; 00043 template <> class VariantTypeValidator<int64_t> {}; 00044 #endif 00045 template <> class VariantTypeValidator<float> {}; 00046 template <> class VariantTypeValidator<double> {}; 00047 template <> class VariantTypeValidator<bool> {}; 00048 template <> class VariantTypeValidator<std::string> {}; 00049 template <> class VariantTypeValidator<std::vector<unsigned char> > {}; 00050 template <> class VariantTypeValidator<std::vector<signed char> > {}; 00051 template <> class VariantTypeValidator<std::vector<char> > {}; 00052 template <> class VariantTypeValidator<std::vector<unsigned short> > {}; 00053 template <> class VariantTypeValidator<std::vector<short> > {}; 00054 template <> class VariantTypeValidator<std::vector<unsigned int> > {}; 00055 template <> class VariantTypeValidator<std::vector<int> > {}; 00056 template <> class VariantTypeValidator<std::vector<unsigned long> > {}; 00057 template <> class VariantTypeValidator<std::vector<long> > {}; 00058 #ifdef WIN_API 00059 template <> class VariantTypeValidator<std::vector<uint64_t> > {}; 00060 template <> class VariantTypeValidator<std::vector<int64_t> > {}; 00061 #endif 00062 template <> class VariantTypeValidator<std::vector<float> > {}; 00063 template <> class VariantTypeValidator<std::vector<double> > {}; 00064 template <> class VariantTypeValidator<std::vector<bool> > {}; 00065 template <> class VariantTypeValidator<std::vector<std::string> > {}; 00066 /// \endcond 00067 00068 /** 00069 * A type-safe variant type that allows variants to be passed by value. 00070 * The DataVariant class is a type-safe alternative to void pointers. 00071 * 00072 * @warning For serialization and deserialization, use of \c long, \c unsigned \c long, 00073 * \c int64_t, and \c uint64_t and their associated \c vector types is strongly discouraged 00074 * due to cross-platform compatibility issues. Use Int64 or UInt64 instead. 00075 */ 00076 class DataVariant 00077 { 00078 public: 00079 enum StatusEnum 00080 { 00081 SUCCESS, /**< The conversion succeeded. */ 00082 FAILURE, /**< The conversion failed. */ 00083 NOT_SUPPORTED /**< The given conversion is not supported by the type contained in the DataVariant. */ 00084 }; 00085 00086 /** 00087 * @EnumWrapper DataVariant::StatusEnum. 00088 */ 00089 typedef EnumWrapper<StatusEnum> Status; 00090 00091 /** 00092 * An exception that indicates that the type 00093 * contained with the DataVariant does not support 00094 * the given operation. 00095 */ 00096 class UnsupportedOperation : public std::exception 00097 { 00098 public: 00099 /** 00100 * Constructor. 00101 * 00102 * @param message 00103 * The string used to provide additional information about 00104 * why the operation was not supported. 00105 */ 00106 explicit UnsupportedOperation(const std::string& message) : std::exception(), mMessage() {} 00107 00108 /** 00109 * Destructor. 00110 */ 00111 virtual ~UnsupportedOperation() throw() {} 00112 00113 /** 00114 * Query for additional information. 00115 * 00116 * @return Returns a string providing additional information on why 00117 * the operation was unsupported. 00118 */ 00119 const char* what() const throw() 00120 { 00121 return mMessage.c_str(); 00122 } 00123 private: 00124 std::string mMessage; 00125 }; 00126 00127 /** 00128 * Default constructor. Creates an empty variant object. 00129 */ 00130 DataVariant() : 00131 mpValue(NULL) 00132 { 00133 } 00134 00135 /** 00136 * Constructor. 00137 * 00138 * It performs a deep copy on the value and stores the result 00139 * in the variant. The deep copy is performed by the DataVariantFactory. 00140 * The valid types are as follows: 00141 * - unsigned char 00142 * - signed char 00143 * - char 00144 * - unsigned short 00145 * - short 00146 * - unsigned int 00147 * - int 00148 * - unsigned long 00149 * - long 00150 * - uint64_t (Windows only) 00151 * - int64_t (Windows only) 00152 * - UInt64 00153 * - Int64 00154 * - float 00155 * - double 00156 * - bool 00157 * - std::string 00158 * - std::vector<unsigned char> 00159 * - std::vector<signed char> 00160 * - std::vector<char> 00161 * - std::vector<unsigned short> 00162 * - std::vector<short> 00163 * - std::vector<unsigned int> 00164 * - std::vector<int> 00165 * - std::vector<unsigned long> 00166 * - std::vector<long> 00167 * - std::vector<uint64_t> (Windows only) 00168 * - std::vector<int64_t> (Windows only) 00169 * - std::vector<UInt64> 00170 * - std::vector<Int64> 00171 * - std::vector<float> 00172 * - std::vector<double> 00173 * - std::vector<bool> 00174 * - std::vector<std::string> 00175 * - #AnimationCycle 00176 * - #AnimationState 00177 * - #ArcRegion 00178 * - ColorType 00179 * - #ComplexComponent 00180 * - #DataOrigin 00181 * - DateTime (const and non-const) 00182 * - #DisplayMode 00183 * - #DistanceUnits 00184 * - #DmsFormatType 00185 * - DynamicObject (const and non-const) 00186 * - #EncodingType 00187 * - #EndianType 00188 * - Filename (const and non-const) 00189 * - std::vector<Filename*> (const and non-const pointers) 00190 * - #FillStyle 00191 * - FloatComplex 00192 * - #GcpSymbol 00193 * - #GeocoordType 00194 * - #GraphicObjectType 00195 * - #InsetZoomMode 00196 * - IntegerComplex 00197 * - #InterleaveFormatType 00198 * - #LatLonStyle 00199 * - #LayerType 00200 * - #LineStyle 00201 * - #LocationType 00202 * - #PanLimitType 00203 * - #PassArea 00204 * - #PlotObjectType 00205 * - Point::PointSymbolType 00206 * - #PositionType 00207 * - #ProcessingLocation 00208 * - #SessionSaveType 00209 * - #RasterChannelType 00210 * - #RegionUnits 00211 * - #ReleaseType 00212 * - #StretchType 00213 * - #SymbolType 00214 * - #UnitSystem 00215 * - #UnitType 00216 * - #WavelengthUnitsType 00217 * - #WindowSizeType 00218 * - #WindowType 00219 * 00220 * @param value 00221 * The value to copy into the variant. If the type of value isn't 00222 * one of the supported types, an empty variant is created. In the 00223 * case of pointers, a deep copy of the object pointed to is 00224 * performed, unless the pointer is NULL, in which case an empty 00225 * variant is created. 00226 */ 00227 #if defined(WIN_API) 00228 #pragma warning( push ) 00229 #pragma warning( disable: 4101 ) 00230 #endif 00231 template <typename T> 00232 DataVariant(const T& value) : 00233 mpValue(NULL) 00234 { 00235 VariantTypeValidator<T> validator HIDE_UNUSED_VARIABLE_WARNING; 00236 00237 mpValue = createWrapper(static_cast<const void*>(&value), typeid(T).name()); 00238 } 00239 00240 /** 00241 * Copy Constructor. It performs a deep copy on the value and stores the result 00242 * in the new variant. 00243 * 00244 * @param value 00245 * The source variant to copy. If the source variant is empty, the new 00246 * copy will also be empty. 00247 */ 00248 DataVariant(const DataVariant& value); 00249 00250 /** 00251 * Constructor. 00252 * 00253 * It performs a deep copy on the value and stores the result 00254 * in the variant. The deep copy is performed by the DataVariantFactory. 00255 * 00256 * @param type 00257 * The type of the object to wrap in the variant. The format of the 00258 * string should match that used by getTypeName(). 00259 * 00260 * @param pValue 00261 * A pointer to the object to copy into the variant. If this is NULL, 00262 * a default initialized object of the specified type will be created. 00263 * 00264 * @param strict 00265 * If true, a verification error message will be generated if 00266 * a DataVariant of the given type cannot be constructed. If 00267 * false, no verification error message will be generated. 00268 */ 00269 DataVariant(const std::string& type, const void *pValue, bool strict = true) : 00270 mpValue(NULL) 00271 { 00272 mpValue = createWrapper(pValue, type.c_str(), strict); 00273 } 00274 00275 /** 00276 * Destructor. Deletes the wrapped object. 00277 */ 00278 ~DataVariant(); 00279 00280 /** 00281 * Indicates if the DataVariant is empty or not. On an empty variant, any 00282 * attempt to extract its value will fail. 00283 * 00284 * @return true if the variant contains a wrapped object, or false otherwise 00285 */ 00286 bool isValid() const; 00287 00288 /** 00289 * Gets the type of the object wrapped in the variant. 00290 * 00291 * @return The type_info of the wrapped object, if the variant is not empty, 00292 * or typeid(void) otherwise. 00293 */ 00294 const std::type_info &getType() const; 00295 00296 /** 00297 * Gets the name of the type of the object wrapped in the variant. The 00298 * format of the string will match that of TypeConverter. If T is a value 00299 * type, it will be \#T. For example if T is vector<int> it will return 00300 * "vector<int>". If T is a pointer type, it will strip the '*' from the 00301 * type before creating the string. For example, if T is Filename*, it will 00302 * return "Filename". If T is vector<Filename*> it will return 00303 * "vector<Filename>". 00304 * 00305 * @return The name of the type of the object or "void" if invalid. 00306 */ 00307 std::string getTypeName() const; 00308 00309 /** 00310 * Converts the value in the variant to a string. 00311 * 00312 * @param pStatus 00313 * If this value is non-NULL, it will be populated 00314 * with a value of DataVariant::SUCCESS, 00315 * DataVariant::FAILURE or DataVariant::NOT_SUPPORTED 00316 * depending on the result of the toXmlString operation. 00317 * 00318 * @return The value in the variant converted to a string. If the variant 00319 * is invalid, an empty string will be returned. If pStatus 00320 * is set to DataVariant::FAILURE or DataVariant::NOT_SUPPORTED, 00321 * empty string will be returned. 00322 */ 00323 std::string toXmlString(Status* pStatus = NULL) const; 00324 00325 /** 00326 * Initializes the variant from input text. 00327 * 00328 * @param type 00329 * The type of object represented by the text. 00330 * 00331 * @param text 00332 * The textual representation of the object. 00333 * 00334 * @return Returns DataVariant::SUCCESS if the variant was successfully 00335 * initialized from the text, DataVariant::FAILURE if the variant 00336 * was not successfully initialized from the 00337 * text or DataVariant::NOT_SUPPORTED if the given type does not support 00338 * being initialized from text. 00339 */ 00340 Status fromXmlString(const std::string &type, const std::string &text); 00341 00342 /** 00343 * Converts the value in the variant to a string. 00344 * 00345 * @param pStatus 00346 * If this value is non-NULL, it will be populated 00347 * with a value of DataVariant::SUCCESS, 00348 * DataVariant::FAILURE or DataVariant::NOT_SUPPORTED 00349 * depending on the result of the toXmlString operation. 00350 * 00351 * @return The value in the variant converted to a string. If the variant 00352 * is invalid, an empty string will be returned. If pStatus 00353 * is set to DataVariant::FAILURE or DataVariant::NOT_SUPPORTED, 00354 * empty string will be returned. 00355 */ 00356 std::string toDisplayString(Status* pStatus = NULL) const; 00357 00358 /** 00359 * Initializes the variant from input text. 00360 * 00361 * @param type 00362 * The type of object represented by the text. 00363 * 00364 * @param text 00365 * The textual representation of the object. 00366 * 00367 * @return Returns DataVariant::SUCCESS if the variant was successfully 00368 * initialized from the text, DataVariant::FAILURE if the variant 00369 * was not successfully initialized from the 00370 * text or DataVariant::NOT_SUPPORTED if the given type does not support 00371 * being initialized from text. 00372 */ 00373 Status fromDisplayString(const std::string &type, const std::string &text); 00374 00375 /** 00376 * Converts the contents of this object to XML data. 00377 * 00378 * @param pWriter 00379 * Pointer to an XMLWriter object in which the object's contents 00380 * are written. 00381 * 00382 * @throw XmlBase::XmlException 00383 * This exception (or a subclass) is thrown if there is a problem 00384 * serializing the object. 00385 * 00386 * @return Returns true if the object was successfully converted to XML 00387 * data. Returns false if the object cannot be represented in 00388 * XML format. 00389 */ 00390 bool toXml(XMLWriter* pWriter) const; 00391 00392 /** 00393 * Sets the contents of this object from given XML data. 00394 * 00395 * @param pDocument 00396 * The Xerces DOM node. 00397 * 00398 * @param version 00399 * This is the version of the XML which is being deserialized. 00400 * 00401 * @throw XmlBase::XmlException 00402 * This exception (or a subclass) is thrown if there is a problem 00403 * deserializing the object. 00404 * 00405 * @return Returns true if the object's data values were successfully 00406 * set from the given XML data. Returns false if the object 00407 * cannot be represented in XML format. 00408 */ 00409 bool fromXml(DOMNode* pDocument, unsigned int version); 00410 00411 /** 00412 * Extracts the value of the variant. 00413 * 00414 * If the type of the supplied argument matches the type of the wrapped 00415 * object, the method extracts the value of the wrapped object into the 00416 * supplied argument. 00417 * 00418 * @code 00419 * int i = 5; 00420 * DataVariant variant(i); 00421 * int j = 0; 00422 * bool success = variant.getValue(j); 00423 * // j == 5 and success == true at this point 00424 * float f = 0.0; 00425 * success = variant.getValue(f); 00426 * // f == 0.0 and success == false at this point 00427 * @endcode 00428 * 00429 * @return true if the value was successfully extracted, or false otherwise. 00430 * If the variant is empty, this will always return false. 00431 */ 00432 template <typename T> 00433 bool getValue(T& value) const 00434 { 00435 VariantTypeValidator<T> validator HIDE_UNUSED_VARIABLE_WARNING; 00436 T* pValue = const_cast<DataVariant*>(this)->getPointerToValue<T>(); 00437 if (pValue != NULL) 00438 { 00439 value = *pValue; 00440 return true; 00441 } 00442 00443 return false; 00444 } 00445 00446 /** 00447 * Returns a pointer to the wrapped object. 00448 * 00449 * If the type used in calling the method matches the type of the wrapped 00450 * object, the method returns a pointer to the wrapped object. 00451 * 00452 * @code 00453 * int i = 5; 00454 * DataVariant variant(i); 00455 * int *pIntValue = variant.getPointerToValue<int>(); 00456 * int j = pIntValue ? *pIntValue : 0; 00457 * // j == 5 at this point; 00458 * float *pFloatValue = variant.getPointerToValue<float>(); 00459 * // pFloatValue == NULL at this point 00460 * @endcode 00461 * 00462 * @return A pointer to the wrapped value if the type used in calling the 00463 * method matches the type of the wrapped object, or NULL otherwise. 00464 * If the variant is empty, this will always return NULL. 00465 */ 00466 template <typename T> 00467 const T* getPointerToValue() const 00468 { 00469 VariantTypeValidator<T> validator HIDE_UNUSED_VARIABLE_WARNING; 00470 if (getType() == typeid(T)) 00471 { 00472 return reinterpret_cast<T*> (getPointerToValueAsVoid()); 00473 } 00474 00475 return NULL; 00476 } 00477 00478 /** 00479 * Returns a pointer to the wrapped object. 00480 * 00481 * If the type used in calling the method matches the type of the wrapped 00482 * object, the method returns a pointer to the wrapped object. 00483 * 00484 * @code 00485 * int i = 5; 00486 * DataVariant variant(i); 00487 * int *pIntValue = variant.getPointerToValue<int>(); 00488 * int j = pIntValue ? *pIntValue : 0; 00489 * // j == 5 at this point; 00490 * float *pFloatValue = variant.getPointerToValue<float>(); 00491 * // pFloatValue == NULL at this point 00492 * @endcode 00493 * 00494 * @return A pointer to the wrapped value if the type used in calling the 00495 * method matches the type of the wrapped object, or NULL otherwise. 00496 * If the variant is empty, this will always return NULL. 00497 */ 00498 template <typename T> 00499 T* getPointerToValue() 00500 { 00501 VariantTypeValidator<T> validator HIDE_UNUSED_VARIABLE_WARNING; 00502 return const_cast<T*>(const_cast<const DataVariant*>(this)->getPointerToValue<T>()); 00503 } 00504 00505 /** 00506 * Assignment operator. 00507 * 00508 * Performs a deep copy of the object 00509 * on the right-hand side of the = into the variant on the left-hand side of 00510 * the =. If the variant on the left-hand side is not empty prior to the 00511 * assignment, its existing wrapped object will be deleted. 00512 * 00513 * @code 00514 * int i = 5; 00515 * float f = 6.0; 00516 * DataVariant variant(i); 00517 * variant = f; 00518 * i = 0; 00519 * bool success = variant.getValue(i); 00520 * // success == false and i == 0 at this point 00521 * float g = 0.0; 00522 * success = variant.getValue(g); 00523 * // success == true and g == 6.0 at this point 00524 * @endcode 00525 * 00526 * @param rhs 00527 * The object on the right-hand side of the assignment 00528 * 00529 * @return A reference to the variant on the left-hand side of the assignment. 00530 */ 00531 template<typename ValueType> 00532 DataVariant & operator=(const ValueType & rhs) 00533 { 00534 DataVariant(rhs).swap(*this); 00535 return *this; 00536 } 00537 00538 /** 00539 * Swaps the internal contents of two variants. 00540 * 00541 * @param rhs 00542 * The variant to swap 00543 * 00544 * @return A reference to the variant on which the method was invoked. 00545 */ 00546 DataVariant& swap(DataVariant & rhs); 00547 00548 /** 00549 * Assignment operator. 00550 * 00551 * Performs a deep copy of the contents of the variant 00552 * on the right-hand side of the = into the variant on the left-hand side of 00553 * the =. If the variant on the left-hand side is not empty prior to the 00554 * assignment, its existing wrapped object will be deleted. 00555 * 00556 * @param rhs 00557 * The variant on the right-hand side of the assignment 00558 * 00559 * @return A reference to the variant on the left-hand side of the assignment. 00560 */ 00561 DataVariant & operator=(const DataVariant & rhs); 00562 00563 /** 00564 * Comparison operator. 00565 * 00566 * Compares a %DataVariant object with a value object. It will return true 00567 * if the types are the same and the internal value of the DataVariant compares 00568 * equal with the value object and false otherwise. If the types are the 00569 * same but the type doesn't support comparison, DataVariant::UnsupportedOperation will be 00570 * thrown. 00571 * 00572 * @param rhs 00573 * The value object to compare with 00574 * 00575 * @return true if the types are the same and the internal value of the 00576 * DataVariant compares equal with the value object and false 00577 * otherwise. 00578 */ 00579 template<typename ValueType> 00580 bool operator==(const ValueType & rhs) const 00581 { 00582 VariantTypeValidator<ValueType> validator HIDE_UNUSED_VARIABLE_WARNING; 00583 DataVariant rhsVariant(rhs); 00584 return *this == rhsVariant; 00585 } 00586 00587 /** 00588 * Comparison operator. 00589 * 00590 * Compares two %DataVariant objects. It will return true if the types are 00591 * the same and the internal values compare equal and false otherwise. If 00592 * the types are the same but the type doesn't support comparison, 00593 * DataVariant::UnsupportedOperation will be thrown. 00594 * 00595 * @param rhs 00596 * The variant to compare with 00597 * 00598 * @return true if the types are the same and the internal values compare 00599 * equal and false otherwise. 00600 */ 00601 bool operator==(const DataVariant& rhs) const; 00602 00603 /** 00604 * Returns a pointer to the wrapped object. 00605 * 00606 * @return A pointer to the wrapped value. If the variant is empty, this 00607 * will return NULL. 00608 */ 00609 void *getPointerToValueAsVoid() const; 00610 00611 private: 00612 DataValueWrapper* mpValue; 00613 00614 DataValueWrapper *createWrapper(const void *pValue, const char *pTypeName, bool strict = true) const; 00615 }; 00616 00617 /** 00618 * Extracts an object from a variant. 00619 * 00620 * @code 00621 * Filename *pFilename = (Filename*)pObjFact->createObject("Filename"); 00622 * DataVariant variant(pFilename); 00623 * const Filename *pFilename2 = NULL; 00624 * const DateTime *pDateTime = NULL; 00625 * int i = 5; 00626 * DataVariant ivariant(i); 00627 * j = 0; 00628 * try 00629 * { 00630 * j = dv_cast<int>(ivariant); 00631 * pFilename2 = &dv_cast<Filename>(variant); 00632 * pDateTime = &dv_cast<DateTime>(variant); // will throw 00633 * } 00634 * catch (std::bad_cast &e) 00635 * { 00636 * } 00637 * // j == 5 at this point 00638 * // pFilename2 != NULL at this point 00639 * // pDateTime == NULL at this point 00640 * @endcode 00641 * 00642 * @param variant 00643 * The variant from which to extract 00644 * 00645 * @throw std::bad_cast 00646 * If the type of the 'cast' and the type of the DataVariant do not 00647 * match, this method will throw std::bad_cast. 00648 * 00649 * @return A reference to the wrapped object. 00650 * 00651 * @relates DataVariant 00652 */ 00653 template<typename T> 00654 const T &dv_cast(const DataVariant &variant) 00655 { 00656 VariantTypeValidator<T> validator HIDE_UNUSED_VARIABLE_WARNING; 00657 const T* pT = variant.getPointerToValue<T>(); 00658 if (pT == NULL) 00659 { 00660 throw std::bad_cast(); 00661 } 00662 return *pT; 00663 } 00664 00665 /** 00666 * Extracts an object from a variant. 00667 * 00668 * @code 00669 * Filename *pFilename = (Filename*)pObjFact->createObject("Filename"); 00670 * DataVariant variant(pFilename); 00671 * const Filename *pFilename2 = NULL; 00672 * const DateTime *pDateTime = NULL; 00673 * int i = 5; 00674 * DataVariant ivariant(i); 00675 * j = 0; 00676 * try 00677 * { 00678 * j = dv_cast<int>(ivariant); 00679 * pFilename2 = &dv_cast<Filename>(variant); 00680 * pDateTime = &dv_cast<DateTime>(variant); // will throw 00681 * } 00682 * catch (std::bad_cast &e) 00683 * { 00684 * } 00685 * // j == 5 at this point 00686 * // pFilename2 != NULL at this point 00687 * // pDateTime == NULL at this point 00688 * @endcode 00689 * 00690 * @param variant 00691 * The variant from which to extract 00692 * 00693 * @throw std::bad_cast 00694 * If the type of the 'cast' and the type of the DataVariant do not 00695 * match, this method will throw std::bad_cast. 00696 * 00697 * @return A reference to the wrapped object. 00698 * 00699 * @relates DataVariant 00700 */ 00701 template<typename T> 00702 T &dv_cast(DataVariant &variant) 00703 { 00704 VariantTypeValidator<T> validator HIDE_UNUSED_VARIABLE_WARNING; 00705 T* pT = variant.getPointerToValue<T>(); 00706 if (pT == NULL) 00707 { 00708 throw std::bad_cast(); 00709 } 00710 return *pT; 00711 } 00712 00713 /** 00714 * Extracts an object from a variant. 00715 * 00716 * @code 00717 * int i = 5; 00718 * DataVariant ivariant(i); 00719 * int j, l; 00720 * double k; 00721 * j = dv_cast_with_verification<int>(ivariant); 00722 * k = dv_cast_with_verification<double>(ivariant, 10.0); 00723 * l = dv_cast_with_verification<int>(ivariant, 25); 00724 * // j == 5 at this point 00725 * // k == 10.0 at this point, because ivariant is of type int, not type double so default value used. 00726 * // l == 5 at this point, because ivariant is valid and of type int, so default value ignored. 00727 * @endcode 00728 * 00729 * @param variant 00730 * The variant from which to extract 00731 * @param defaultValue 00732 * The default value to return from dv_cast_with_verification if the variant provided is invalid 00733 * or if the type of the 'cast' and the type of the DataVariant do not match. 00734 * If the dv_cast_with_verification uses the default value it is considered a defect in the code 00735 * calling dv_cast_with_verification and therefore a VERIFY message will be logged 00736 * to the message log. 00737 * 00738 * @return A copy of the type requested. 00739 * 00740 * @relates DataVariant 00741 */ 00742 template<typename T> 00743 T dv_cast_with_verification(const DataVariant &variant, const T& defaultValue) 00744 { 00745 VariantTypeValidator<T> validator HIDE_UNUSED_VARIABLE_WARNING; 00746 T retValue = defaultValue; 00747 bool success = variant.getValue(retValue); 00748 if (!success) 00749 { 00750 VERIFYNR_MSG(false, std::string("Invalid dv_cast when provided variant is of type " + 00751 variant.getTypeName()).c_str()); 00752 } 00753 return retValue; 00754 } 00755 00756 /** 00757 * Extracts an object from a variant. 00758 * 00759 * @code 00760 * int i = 5; 00761 * DataVariant ivariant(i); 00762 * int j, l; 00763 * double k; 00764 * j = dv_cast<int>(ivariant); 00765 * k = dv_cast<double>(ivariant, 10.0); 00766 * l = dv_cast<int>(ivariant, 25); 00767 * // j == 5 at this point 00768 * // k == 10.0 at this point, because ivariant is of type int, not type double so default value used. 00769 * // l == 5 at this point, because ivariant is valid and of type int, so default value ignored. 00770 * @endcode 00771 * 00772 * @param variant 00773 * The variant from which to extract 00774 * @param defaultValue 00775 * The default value to return from dv_cast if the variant provided is invalid 00776 * or if the type of the 'cast' and the type of the DataVariant do not match. 00777 * Unlike dv_cast_with_verification(), if the dv_cast uses the default value it is not 00778 * considered a defect in the code. 00779 * 00780 * @return A copy of the type requested. 00781 * 00782 * @relates DataVariant 00783 * @see dv_cast_with_verification 00784 */ 00785 template<typename T> 00786 T dv_cast(const DataVariant &variant, const T& defaultValue) 00787 { 00788 VariantTypeValidator<T> validator HIDE_UNUSED_VARIABLE_WARNING; 00789 T retValue = defaultValue; 00790 variant.getValue(retValue); 00791 return retValue; 00792 } 00793 00794 /** 00795 * Extracts a pointer to the object wrapped in a variant. 00796 * 00797 * @code 00798 * int i = 5; 00799 * DataVariant variant(i); 00800 * DataVariant *pVariant(&variant); 00801 * int *pInt = dv_cast<int>(pVariant); 00802 * int j = pInt?*pInt:0; 00803 * float *pFloat = dv_cast<float>(pVariant); 00804 * // j == 5 at this point; 00805 * // pFloat == NULL at this point 00806 * @endcode 00807 * 00808 * @param pVariant 00809 * A pointer to the variant from which to extract 00810 * 00811 * @return A pointer to the wrapped object or NULL if the 00812 * types don't match. 00813 * 00814 * @relates DataVariant 00815 */ 00816 template<typename T> 00817 const T* dv_cast(const DataVariant *pVariant) 00818 { 00819 VariantTypeValidator<T> validator HIDE_UNUSED_VARIABLE_WARNING; 00820 if (pVariant == NULL) 00821 { 00822 return NULL; 00823 } 00824 return pVariant->getPointerToValue<T>(); 00825 } 00826 00827 /** 00828 * Extracts a pointer to the object wrapped in a variant. 00829 * 00830 * @code 00831 * int i = 5; 00832 * DataVariant variant(i); 00833 * DataVariant *pVariant(&variant); 00834 * int *pInt = dv_cast<int>(pVariant); 00835 * int j = pInt?*pInt:0; 00836 * float *pFloat = dv_cast<float>(pVariant); 00837 * // j == 5 at this point; 00838 * // pFloat == NULL at this point 00839 * @endcode 00840 * 00841 * @param pVariant 00842 * A pointer to the variant from which to extract 00843 * 00844 * @return A pointer to the wrapped object or NULL if the 00845 * types don't match. 00846 * 00847 * @relates DataVariant 00848 */ 00849 template<typename T> 00850 T* dv_cast(DataVariant *pVariant) 00851 { 00852 VariantTypeValidator<T> validator HIDE_UNUSED_VARIABLE_WARNING; 00853 if (pVariant == NULL) 00854 { 00855 return NULL; 00856 } 00857 return pVariant->getPointerToValue<T>(); 00858 } 00859 #if defined(WIN_API) 00860 #pragma warning( pop ) 00861 #endif 00862 00863 #endif