DataVariant.h

Go to the documentation of this file.
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

Software Development Kit - Opticks 4.9.0 Build 16218