You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
929 lines
24 KiB
929 lines
24 KiB
/* /////////////////////////////////////////////////////////////////////////
|
|
* File: comstl/util/variant.hpp (originally MOVriant.h/.cpp, ::SynesisCom)
|
|
*
|
|
* Purpose: variant class.
|
|
*
|
|
* Created: 12th December 1996
|
|
* Updated: 5th March 2011
|
|
*
|
|
* Home: http://stlsoft.org/
|
|
*
|
|
* Copyright (c) 1996-2011, Matthew Wilson and Synesis Software
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* - Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
* - Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
* - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
|
|
* any contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* ////////////////////////////////////////////////////////////////////// */
|
|
|
|
|
|
/** \file comstl/util/variant.hpp
|
|
*
|
|
* \brief [C++ only; requires COM] Definition of the comstl::variant class
|
|
* (\ref group__library__utility__com "COM Utility" Library).
|
|
*/
|
|
|
|
#ifndef COMSTL_INCL_COMSTL_UTIL_HPP_COMSTL_VARIANT
|
|
#define COMSTL_INCL_COMSTL_UTIL_HPP_COMSTL_VARIANT
|
|
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
# define _COMSTL_VER_COMSTL_UTIL_HPP_COMSTL_VARIANT_MAJOR 2
|
|
# define _COMSTL_VER_COMSTL_UTIL_HPP_COMSTL_VARIANT_MINOR 3
|
|
# define _COMSTL_VER_COMSTL_UTIL_HPP_COMSTL_VARIANT_REVISION 5
|
|
# define _COMSTL_VER_COMSTL_UTIL_HPP_COMSTL_VARIANT_EDIT 158
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Includes
|
|
*/
|
|
|
|
#ifndef COMSTL_INCL_COMSTL_H_COMSTL
|
|
# include <comstl/comstl.h>
|
|
#endif /* !COMSTL_INCL_COMSTL_H_COMSTL */
|
|
#ifndef COMSTL_INCL_COMSTL_STRING_H_BSTR_FUNCTIONS
|
|
# include <comstl/string/BSTR_functions.h>
|
|
#endif /* !COMSTL_INCL_COMSTL_STRING_H_BSTR_FUNCTIONS */
|
|
#ifndef COMSTL_INCL_COMSTL_SHIMS_ACCESS_HPP_STRING
|
|
# include <comstl/shims/access/string.hpp>
|
|
#endif /* !COMSTL_INCL_COMSTL_SHIMS_ACCESS_HPP_STRING */
|
|
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
|
|
# ifndef COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS
|
|
# include <comstl/error/exceptions.hpp>
|
|
# endif /* !COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS */
|
|
#endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
|
|
#ifndef COMSTL_INCL_COMSTL_UTIL_HPP_INTERFACE_TRAITS
|
|
# include <comstl/util/interface_traits.hpp>
|
|
#endif /* !COMSTL_INCL_COMSTL_UTIL_HPP_INTERFACE_TRAITS */
|
|
#ifndef COMSTL_INCL_COMSTL_UTIL_H_VARIANT_FUNCTIONS
|
|
# include <comstl/util/VARIANT_functions.h>
|
|
#endif /* !COMSTL_INCL_COMSTL_UTIL_H_VARIANT_FUNCTIONS */
|
|
#ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_CONSTRAINTS
|
|
# include <stlsoft/util/constraints.hpp>
|
|
#endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_CONSTRAINTS */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Namespace
|
|
*/
|
|
|
|
#ifndef _COMSTL_NO_NAMESPACE
|
|
# if defined(_STLSOFT_NO_NAMESPACE) || \
|
|
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
|
|
/* There is no stlsoft namespace, so must define ::comstl */
|
|
namespace comstl
|
|
{
|
|
# else
|
|
/* Define stlsoft::comstl_project */
|
|
|
|
namespace stlsoft
|
|
{
|
|
|
|
namespace comstl_project
|
|
{
|
|
|
|
# endif /* _STLSOFT_NO_NAMESPACE */
|
|
#endif /* !_COMSTL_NO_NAMESPACE */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Classes
|
|
*/
|
|
|
|
/** \brief Facade for the COM VARIANT type
|
|
*
|
|
* \ingroup group__library__utility__com
|
|
*
|
|
* \remarks comstl::variant publicly derives from \c VARIANT as a measure
|
|
* of expedience, rather than as an act of design sophistication. Any
|
|
* manual manipulation of the instances, or their member variables, is
|
|
* at the user's risk. Notwithstanding, this is helped by the fact that
|
|
* comstl::variant declares no member variables and no virtual member
|
|
* functions - for most compilers this means that the Empty Derived
|
|
* Optimisation (see Section 12.4 of Imperfect C++) will apply.
|
|
*/
|
|
class variant
|
|
: public VARIANT
|
|
{
|
|
/// Member Types
|
|
public:
|
|
typedef variant class_type;
|
|
typedef cs_bool_t bool_type;
|
|
typedef cs_size_t size_type;
|
|
|
|
/// Conversion
|
|
public:
|
|
/** Default constructor
|
|
*
|
|
* Initialises the instance
|
|
*
|
|
* \post <code>assert(VT_EMPTY == this->vt)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant();
|
|
|
|
/** Copying constructor
|
|
*
|
|
* Initialises the instance with a copy of the given \c VARIANT
|
|
*
|
|
* \post <code>assert(rhs == *this)</code>
|
|
*
|
|
* \exception comstl::com_exception If the copy fails
|
|
*/
|
|
variant(VARIANT const& rhs);
|
|
|
|
/** Copy constructor
|
|
*
|
|
* \post <code>assert(rhs == *this)</code>
|
|
*
|
|
* \exception comstl::com_exception If the copy fails
|
|
*/
|
|
variant(class_type const& rhs);
|
|
|
|
/** Copy assignment operator
|
|
*
|
|
* \post <code>assert(rhs == *this)</code>
|
|
*
|
|
* \exception comstl::com_exception If the copy fails
|
|
*/
|
|
class_type& operator =(class_type const& rhs);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given boolean value
|
|
*
|
|
* \post <code>assert(VT_BOOL == this->vt)</code>
|
|
* \post <code>assert(b == (VARIANT_TRUE == this->boolVal))</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(bool b);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given 8-bit signed integer value
|
|
*
|
|
* \post <code>assert(VT_I1 == this->vt)</code>
|
|
* \post <code>assert(i == this->cVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(stlsoft::sint8_t i);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given 8-bit unsigned integer value
|
|
*
|
|
* \post <code>assert(VT_UI1 == this->vt)</code>
|
|
* \post <code>assert(i == this->bVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(stlsoft::uint8_t i);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given 16-bit signed integer value
|
|
*
|
|
* \post <code>assert(VT_I2 == this->vt)</code>
|
|
* \post <code>assert(i == this->iVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(stlsoft::sint16_t i);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given 16-bit unsigned integer value
|
|
*
|
|
* \post <code>assert(VT_UI2 == this->vt)</code>
|
|
* \post <code>assert(i == this->uiVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(stlsoft::uint16_t i);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given 32-bit signed integer value
|
|
*
|
|
* \post <code>assert(VT_I4 == this->vt)</code>
|
|
* \post <code>assert(i == this->lVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(stlsoft::sint32_t i);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given 32-bit unsigned integer value
|
|
*
|
|
* \post <code>assert(VT_UI4 == this->vt)</code>
|
|
* \post <code>assert(i == this->ulVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(stlsoft::uint32_t i);
|
|
|
|
//#ifdef STLSOFT_CF_64BIT_INT_SUPPORT
|
|
// variant(stlsoft::sint64_t i);
|
|
// variant(stlsoft::uint64_t i);
|
|
//#endif /* STLSOFT_CF_64BIT_INT_SUPPORT */
|
|
|
|
#ifdef STLSOFT_CF_SHORT_DISTINCT_INT_TYPE
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given \c short value
|
|
*
|
|
* \post <code>assert(VT_I2 == this->vt)</code>
|
|
* \post <code>assert(i == this->iVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(short i);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given
|
|
* <code>unsigned short</code> value
|
|
*
|
|
* \post <code>assert(VT_UI2 == this->vt)</code>
|
|
* \post <code>assert(i == this->uiVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(unsigned short i);
|
|
#endif /* STLSOFT_CF_SHORT_DISTINCT_INT_TYPE */
|
|
|
|
#ifdef STLSOFT_CF_INT_DISTINCT_INT_TYPE
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given \c int value
|
|
*
|
|
* \post <code>assert(VT_I4 == this->vt)</code>
|
|
* \post <code>assert(i == this->lVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(int i);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given
|
|
* <code>unsigned int</code> value
|
|
*
|
|
* \post <code>assert(VT_UI4 == this->vt)</code>
|
|
* \post <code>assert(i == this->ulVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(unsigned int i);
|
|
#endif /* STLSOFT_CF_INT_DISTINCT_INT_TYPE */
|
|
|
|
#ifdef STLSOFT_CF_LONG_DISTINCT_INT_TYPE
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given \c long value
|
|
*
|
|
* \post <code>assert(VT_I4 == this->vt)</code>
|
|
* \post <code>assert(i == this->lVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(long i);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given
|
|
* <code>unsigned long</code> value
|
|
*
|
|
* \post <code>assert(VT_UI4 == this->vt)</code>
|
|
* \post <code>assert(i == this->ulVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(unsigned long i);
|
|
#endif /* STLSOFT_CF_LONG_DISTINCT_INT_TYPE */
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given \c float value
|
|
*
|
|
* \post <code>assert(VT_R4 == this->vt)</code>
|
|
* \post <code>assert(r == this->fltVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(float r);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given \c double value
|
|
*
|
|
* \post <code>assert(VT_R8 == this->vt)</code>
|
|
* \post <code>assert(r == this->dblVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(double r);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given currency (\c CY) value
|
|
*
|
|
* \post <code>assert(VT_CY == this->vt)</code>
|
|
* \post <code>assert(r == this->cyVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(CY cy);
|
|
|
|
/** Conversion constructor
|
|
*
|
|
* Initialises the instance with the given \c DECIMAL value
|
|
*
|
|
* \post <code>assert(VT_DECIMAL == this->vt)</code>
|
|
* \post <code>assert(dec == this->decVal)</code>
|
|
*
|
|
* \exception - Does not throw an exception
|
|
*/
|
|
variant(DECIMAL const& dec);
|
|
|
|
|
|
variant(LPUNKNOWN punk, bool_type bAddRef);
|
|
variant(LPDISPATCH pdisp, bool_type bAddRef);
|
|
variant(cs_char_a_t const* s, int len = -1);
|
|
variant(cs_char_w_t const* s, int len = -1);
|
|
variant(VARIANT const& var, VARTYPE vt);
|
|
|
|
/** Releases any resources associated with the underlying
|
|
* <code>VARIANT</code>
|
|
*/
|
|
~variant() stlsoft_throw_0()
|
|
{
|
|
stlsoft_constraint_must_be_same_size(class_type, VARIANT);
|
|
|
|
::VariantClear(this);
|
|
}
|
|
|
|
/** Clears the variant
|
|
*
|
|
* \post <code>assert(VT_EMPTY == this->vt)</code>
|
|
*/
|
|
void clear();
|
|
|
|
/// Operations
|
|
public:
|
|
HRESULT try_conversion_copy(VARIANT const& var, VARTYPE vt);
|
|
HRESULT try_convert(VARTYPE vt);
|
|
class_type& convert(VARTYPE vt);
|
|
|
|
/** Returns a pointer to a specified interface on an object to which
|
|
* a client currently holds an interface pointer.
|
|
*
|
|
* \return An <code>HRESULT</code> code indicating the success of the
|
|
* operation.
|
|
* \retval <code>S_OK</code> The interface is supported:
|
|
* <code>*ppv</code> will hold the pointer to the requested interface
|
|
* \retval <code>E_INTERFACE</code> The interface is not supported: the
|
|
* value of <code>*ppv</code> is undefined.
|
|
*
|
|
* \pre <code>NULL != ppv</code>
|
|
*/
|
|
HRESULT QueryInterface(REFIID riid, void** ppv) const;
|
|
|
|
/** Returns a pointer to a specified interface on an object to which
|
|
* a client currently holds an interface pointer.
|
|
*
|
|
* \return An <code>HRESULT</code> code indicating the success of the
|
|
* operation.
|
|
* \retval <code>S_OK</code> The interface is supported:
|
|
* <code>*ppi</code> will hold the pointer to the requested interface
|
|
* \retval <code>E_INTERFACE</code> The interface is not supported: the
|
|
* value of <code>*ppi</code> is undefined.
|
|
*
|
|
* \pre <code>NULL != ppi</code>
|
|
*/
|
|
template <ss_typename_param_k I>
|
|
HRESULT QueryInterfaceValue(I** ppi)
|
|
{
|
|
return QueryInterface(IID_traits<I>::iid(), reinterpret_cast<void**>(ppi));
|
|
}
|
|
|
|
public:
|
|
/** Swaps the contents with another instance
|
|
*/
|
|
void swap(class_type& rhs);
|
|
|
|
/// Comparison
|
|
public:
|
|
bool_type equal(class_type const& rhs) const;
|
|
bool_type equal(VARIANT const& rhs) const;
|
|
|
|
/// Operators
|
|
public:
|
|
|
|
private:
|
|
static void swap_(VARIANT& lhs, VARIANT& rhs);
|
|
void handle_error_(char const* message, HRESULT hr);
|
|
};
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* String access shims
|
|
*/
|
|
|
|
// No string access shims are defined, because there're already a set
|
|
// defined for VARIANT, in comstl/shims/access/string.hpp, which is included
|
|
// by this file.
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Operators
|
|
*/
|
|
|
|
inline cs_bool_t operator ==(variant const& lhs, variant const& rhs)
|
|
{
|
|
return lhs.equal(rhs);
|
|
}
|
|
|
|
inline cs_bool_t operator !=(variant const& lhs, variant const& rhs)
|
|
{
|
|
return !operator ==(lhs, rhs);
|
|
}
|
|
|
|
inline cs_bool_t operator ==(variant const& lhs, VARIANT const& rhs)
|
|
{
|
|
return lhs.equal(rhs);
|
|
}
|
|
|
|
inline cs_bool_t operator !=(variant const& lhs, VARIANT const& rhs)
|
|
{
|
|
return !operator ==(lhs, rhs);
|
|
}
|
|
|
|
inline cs_bool_t operator ==(VARIANT const& lhs, variant const& rhs)
|
|
{
|
|
return rhs.equal(lhs);
|
|
}
|
|
|
|
inline cs_bool_t operator !=(VARIANT const& lhs, variant const& rhs)
|
|
{
|
|
return !operator ==(lhs, rhs);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// Unit-testing
|
|
|
|
#ifdef STLSOFT_UNITTEST
|
|
# include "./unittest/variant_unittest_.h"
|
|
#endif /* STLSOFT_UNITTEST */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Implementation
|
|
*/
|
|
|
|
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
|
|
|
|
inline void variant::handle_error_(char const* message, HRESULT hr)
|
|
{
|
|
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
|
|
|
|
STLSOFT_THROW_X(com_exception(message, hr));
|
|
|
|
#else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
|
|
|
|
STLSOFT_SUPPRESS_UNUSED(message);
|
|
|
|
::VariantClear(this);
|
|
|
|
this->vt = VT_ERROR;
|
|
this->scode = hr;
|
|
|
|
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
|
|
}
|
|
|
|
inline /* static */ void variant::swap_(VARIANT& lhs, VARIANT& rhs)
|
|
{
|
|
VARIANT t;
|
|
|
|
::memcpy(&t, &lhs, sizeof(VARIANT));
|
|
::memcpy(&lhs, &rhs, sizeof(VARIANT));
|
|
::memcpy(&rhs, &t, sizeof(VARIANT));
|
|
}
|
|
|
|
|
|
|
|
|
|
inline variant::variant()
|
|
{
|
|
::VariantInit(this);
|
|
}
|
|
|
|
inline variant::variant(class_type const& rhs)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
class_type& rhs_ = const_cast<class_type&>(rhs);
|
|
HRESULT hr = ::VariantCopy(this, &rhs_);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
handle_error_("failed to copy variant", hr);
|
|
}
|
|
}
|
|
|
|
inline variant::variant(VARIANT const& rhs)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
HRESULT hr = ::VariantCopy(this, const_cast<VARIANT*>(&rhs));
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
handle_error_("failed to copy variant", hr);
|
|
}
|
|
}
|
|
|
|
inline variant::class_type& variant::operator =(variant::class_type const& rhs)
|
|
{
|
|
class_type r(rhs);
|
|
|
|
r.swap(*this);
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline variant::variant(bool b)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_BOOL;
|
|
this->boolVal = b ? VARIANT_TRUE : VARIANT_FALSE;
|
|
}
|
|
|
|
inline variant::variant(stlsoft::sint8_t i)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_I1;
|
|
this->cVal = static_cast<CHAR>(i);
|
|
}
|
|
|
|
inline variant::variant(stlsoft::uint8_t i)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_UI1;
|
|
this->bVal = static_cast<BYTE>(i);
|
|
}
|
|
|
|
inline variant::variant(stlsoft::sint16_t i)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_I2;
|
|
this->iVal = static_cast<SHORT>(i);
|
|
}
|
|
|
|
inline variant::variant(stlsoft::uint16_t i)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_UI2;
|
|
this->uiVal = static_cast<USHORT>(i);
|
|
}
|
|
|
|
inline variant::variant(stlsoft::sint32_t i)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_I4;
|
|
this->lVal = static_cast<LONG>(i);
|
|
}
|
|
|
|
inline variant::variant(stlsoft::uint32_t i)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_UI4;
|
|
this->ulVal = static_cast<ULONG>(i);
|
|
}
|
|
|
|
#ifdef STLSOFT_CF_SHORT_DISTINCT_INT_TYPE
|
|
inline variant::variant(short i)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_I2;
|
|
this->iVal = i;
|
|
}
|
|
inline variant::variant(unsigned short i)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_UI2;
|
|
this->uiVal = i;
|
|
}
|
|
#endif /* STLSOFT_CF_SHORT_DISTINCT_INT_TYPE */
|
|
|
|
#ifdef STLSOFT_CF_INT_DISTINCT_INT_TYPE
|
|
inline variant::variant(int i)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_I4;
|
|
this->lVal = i;
|
|
}
|
|
inline variant::variant(unsigned int i)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_UI4;
|
|
this->ulVal = i;
|
|
}
|
|
#endif /* STLSOFT_CF_INT_DISTINCT_INT_TYPE */
|
|
|
|
#ifdef STLSOFT_CF_LONG_DISTINCT_INT_TYPE
|
|
inline variant::variant(long i)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_I4;
|
|
this->lVal = i;
|
|
}
|
|
inline variant::variant(unsigned long i)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_UI4;
|
|
this->ulVal = i;
|
|
}
|
|
#endif /* STLSOFT_CF_LONG_DISTINCT_INT_TYPE */
|
|
|
|
|
|
inline variant::variant(float r)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_R4;
|
|
this->fltVal = r;
|
|
}
|
|
|
|
inline variant::variant(double r)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_R8;
|
|
this->dblVal = r;
|
|
}
|
|
|
|
inline variant::variant(CY cy)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_CY;
|
|
this->cyVal = cy;
|
|
}
|
|
|
|
inline variant::variant(DECIMAL const& dec)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_DECIMAL;
|
|
this->decVal.scale = dec.scale;
|
|
this->decVal.sign = dec.sign;
|
|
this->decVal.Hi32 = dec.Hi32;
|
|
this->decVal.Mid32 = dec.Mid32;
|
|
this->decVal.Lo32 = dec.Lo32;
|
|
}
|
|
|
|
inline variant::variant(LPUNKNOWN punk, bool_type bAddRef)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_UNKNOWN;
|
|
this->punkVal = punk;
|
|
|
|
if( bAddRef &&
|
|
NULL != punk)
|
|
{
|
|
punk->AddRef();
|
|
}
|
|
}
|
|
|
|
inline variant::variant(LPDISPATCH pdisp, bool_type bAddRef)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_DISPATCH;
|
|
this->pdispVal = pdisp;
|
|
|
|
if( bAddRef &&
|
|
NULL != pdisp)
|
|
{
|
|
pdisp->AddRef();
|
|
}
|
|
}
|
|
|
|
inline variant::variant(cs_char_a_t const* s, int len /* = -1 */)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_BSTR;
|
|
this->bstrVal = (len < 0) ? bstr_create(s) : bstr_create(s, static_cast<size_type>(len));
|
|
|
|
if(NULL == this->bstrVal)
|
|
{
|
|
if( NULL != s &&
|
|
'\0' != 0[s])
|
|
{
|
|
handle_error_("could not initialise from string", E_OUTOFMEMORY);
|
|
}
|
|
}
|
|
}
|
|
|
|
inline variant::variant(cs_char_w_t const* s, int len /* = -1 */)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
this->vt = VT_BSTR;
|
|
this->bstrVal = (len < 0) ? bstr_create(s) : bstr_create(s, static_cast<size_type>(len));
|
|
|
|
if(NULL == this->bstrVal)
|
|
{
|
|
if( NULL != s &&
|
|
'\0' != 0[s])
|
|
{
|
|
handle_error_("could not initialise from string", E_OUTOFMEMORY);
|
|
}
|
|
}
|
|
}
|
|
|
|
inline variant::variant(VARIANT const& var, VARTYPE vt)
|
|
{
|
|
::VariantInit(this);
|
|
|
|
class_type copy;
|
|
HRESULT hr = ::VariantChangeType(©, const_cast<VARIANT*>(&var), 0, vt);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
handle_error_("could not convert variant to requested type", hr);
|
|
}
|
|
else
|
|
{
|
|
copy.swap(*this);
|
|
}
|
|
}
|
|
|
|
inline void variant::clear()
|
|
{
|
|
::VariantClear(this);
|
|
}
|
|
|
|
inline HRESULT variant::try_conversion_copy(VARIANT const& var, VARTYPE vt)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if(vt == this->vt)
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
class_type copy;
|
|
|
|
hr = ::VariantChangeType(©, const_cast<VARIANT*>(&var), 0, vt);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
copy.swap(*this);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
inline HRESULT variant::try_convert(VARTYPE vt)
|
|
{
|
|
return try_conversion_copy(*this, vt);
|
|
}
|
|
|
|
inline variant::class_type& variant::convert(VARTYPE vt)
|
|
{
|
|
HRESULT hr = try_convert(vt);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
handle_error_("could not convert variant to requested type", hr);
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline HRESULT variant::QueryInterface(REFIID riid, void** ppv) const
|
|
{
|
|
COMSTL_ASSERT(NULL != ppv);
|
|
|
|
if( VT_UNKNOWN == this->vt ||
|
|
VT_DISPATCH == this->vt)
|
|
{
|
|
return (NULL == this->punkVal) ? E_POINTER : this->punkVal->QueryInterface(riid, ppv);
|
|
}
|
|
|
|
return DISP_E_BADVARTYPE;
|
|
}
|
|
|
|
|
|
inline void variant::swap(variant::class_type& rhs)
|
|
{
|
|
swap_(*this, rhs);
|
|
}
|
|
|
|
inline variant::bool_type variant::equal(variant::class_type const& rhs) const
|
|
{
|
|
return equal(static_cast<VARIANT const&>(rhs));
|
|
}
|
|
|
|
inline variant::bool_type variant::equal(VARIANT const& rhs) const
|
|
{
|
|
HRESULT comparisonSucceeded;
|
|
int areEqual = VARIANT_equal(*this, rhs, &comparisonSucceeded);
|
|
|
|
if(FAILED(comparisonSucceeded))
|
|
{
|
|
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
|
|
STLSOFT_THROW_X(comstl::com_exception("support for comparison of variant type not currently supported", comparisonSucceeded));
|
|
#else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
|
|
OutputDebugStringA("support for comparison of variant type not currently supported\n");
|
|
|
|
return false;
|
|
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
|
|
}
|
|
|
|
return 0 != areEqual;
|
|
}
|
|
|
|
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
|
|
|
|
/* ////////////////////////////////////////////////////////////////////// */
|
|
|
|
#ifndef _COMSTL_NO_NAMESPACE
|
|
# if defined(_STLSOFT_NO_NAMESPACE) || \
|
|
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
|
|
} // namespace comstl
|
|
# else
|
|
} // namespace stlsoft::comstl_project
|
|
} // namespace stlsoft
|
|
# endif /* _STLSOFT_NO_NAMESPACE */
|
|
#endif /* !_COMSTL_NO_NAMESPACE */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Namespace
|
|
*
|
|
* The string access shims exist either in the stlsoft namespace, or in the
|
|
* global namespace. This is required by the lookup rules.
|
|
*
|
|
*/
|
|
|
|
#ifndef _COMSTL_NO_NAMESPACE
|
|
# if !defined(_STLSOFT_NO_NAMESPACE) && \
|
|
!defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
|
|
namespace stlsoft
|
|
{
|
|
# else /* ? _STLSOFT_NO_NAMESPACE */
|
|
/* There is no stlsoft namespace, so must define in the global namespace */
|
|
# endif /* !_STLSOFT_NO_NAMESPACE */
|
|
|
|
# if !defined(_STLSOFT_NO_NAMESPACE) && \
|
|
!defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
|
|
} // namespace stlsoft
|
|
# else /* ? _STLSOFT_NO_NAMESPACE */
|
|
/* There is no stlsoft namespace, so must define in the global namespace */
|
|
# endif /* !_STLSOFT_NO_NAMESPACE */
|
|
#endif /* !_COMSTL_NO_NAMESPACE */
|
|
|
|
/* ////////////////////////////////////////////////////////////////////// */
|
|
|
|
#endif /* !COMSTL_INCL_COMSTL_UTIL_HPP_COMSTL_VARIANT */
|
|
|
|
/* ///////////////////////////// end of file //////////////////////////// */
|