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 //////////////////////////// */
							 |