00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00047 #ifndef COMSTL_INCL_COMSTL_UTIL_HPP_COMSTL_VARIANT
00048 #define COMSTL_INCL_COMSTL_UTIL_HPP_COMSTL_VARIANT
00049
00050 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00051 # define _COMSTL_VER_COMSTL_UTIL_HPP_COMSTL_VARIANT_MAJOR 2
00052 # define _COMSTL_VER_COMSTL_UTIL_HPP_COMSTL_VARIANT_MINOR 3
00053 # define _COMSTL_VER_COMSTL_UTIL_HPP_COMSTL_VARIANT_REVISION 4
00054 # define _COMSTL_VER_COMSTL_UTIL_HPP_COMSTL_VARIANT_EDIT 157
00055 #endif
00056
00057
00058
00059
00060
00061 #ifndef COMSTL_INCL_COMSTL_H_COMSTL
00062 # include <comstl/comstl.h>
00063 #endif
00064 #ifndef COMSTL_INCL_COMSTL_STRING_H_BSTR_FUNCTIONS
00065 # include <comstl/string/BSTR_functions.h>
00066 #endif
00067 #ifndef COMSTL_INCL_COMSTL_SHIMS_ACCESS_HPP_STRING
00068 # include <comstl/shims/access/string.hpp>
00069 #endif
00070 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00071 # ifndef COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS
00072 # include <comstl/error/exceptions.hpp>
00073 # endif
00074 #endif
00075 #ifndef COMSTL_INCL_COMSTL_UTIL_HPP_INTERFACE_TRAITS
00076 # include <comstl/util/interface_traits.hpp>
00077 #endif
00078 #ifndef COMSTL_INCL_COMSTL_UTIL_H_VARIANT_FUNCTIONS
00079 # include <comstl/util/VARIANT_functions.h>
00080 #endif
00081 #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_CONSTRAINTS
00082 # include <stlsoft/util/constraints.hpp>
00083 #endif
00084
00085
00086
00087
00088
00089 #ifndef _COMSTL_NO_NAMESPACE
00090 # if defined(_STLSOFT_NO_NAMESPACE) || \
00091 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00092
00093 namespace comstl
00094 {
00095 # else
00096
00097
00098 namespace stlsoft
00099 {
00100
00101 namespace comstl_project
00102 {
00103
00104 # endif
00105 #endif
00106
00107
00108
00109
00110
00123 class variant
00124 : public VARIANT
00125 {
00127 public:
00128 typedef variant class_type;
00129 typedef cs_bool_t bool_type;
00130 typedef cs_size_t size_type;
00131
00133 public:
00142 variant();
00143
00152 variant(VARIANT const& rhs);
00153
00160 variant(class_type const& rhs);
00161
00168 class_type& operator =(class_type const& rhs);
00169
00179 variant(bool b);
00180
00190 variant(stlsoft::sint8_t i);
00191
00201 variant(stlsoft::uint8_t i);
00202
00212 variant(stlsoft::sint16_t i);
00213
00223 variant(stlsoft::uint16_t i);
00224
00234 variant(stlsoft::sint32_t i);
00235
00245 variant(stlsoft::uint32_t i);
00246
00247
00248
00249
00250
00251
00252 #ifdef STLSOFT_CF_SHORT_DISTINCT_INT_TYPE
00253
00262 variant(short i);
00263
00274 variant(unsigned short i);
00275 #endif
00276
00277 #ifdef STLSOFT_CF_INT_DISTINCT_INT_TYPE
00278
00287 variant(int i);
00288
00299 variant(unsigned int i);
00300 #endif
00301
00302 #ifdef STLSOFT_CF_LONG_DISTINCT_INT_TYPE
00303
00312 variant(long i);
00313
00324 variant(unsigned long i);
00325 #endif
00326
00336 variant(float r);
00337
00347 variant(double r);
00348
00358 variant(CY cy);
00359
00369 variant(DECIMAL const& dec);
00370
00371
00372 variant(LPUNKNOWN punk, bool_type bAddRef);
00373 variant(LPDISPATCH pdisp, bool_type bAddRef);
00374 variant(cs_char_a_t const* s, int len = -1);
00375 variant(cs_char_w_t const* s, int len = -1);
00376 variant(VARIANT const& var, VARTYPE vt);
00377
00381 ~variant() stlsoft_throw_0()
00382 {
00383 stlsoft_constraint_must_be_same_size(class_type, VARIANT);
00384
00385 ::VariantClear(this);
00386 }
00387
00392 void clear();
00393
00395 public:
00396 HRESULT try_conversion_copy(VARIANT const& var, VARTYPE vt);
00397 HRESULT try_convert(VARTYPE vt);
00398 class_type& convert(VARTYPE vt);
00399
00412 HRESULT QueryInterface(REFIID riid, void** ppv) const;
00413
00426 template <ss_typename_param_k I>
00427 HRESULT QueryInterfaceValue(I** ppi)
00428 {
00429 return QueryInterface(IID_traits<I>::iid(), reinterpret_cast<void**>(ppi));
00430 }
00431
00432 public:
00435 void swap(class_type& rhs);
00436
00438 public:
00439 bool_type equal(class_type const& rhs) const;
00440 bool_type equal(VARIANT const& rhs) const;
00441
00443 public:
00444
00445 private:
00446 static void swap_(VARIANT& lhs, VARIANT& rhs);
00447 void handle_error_(char const* message, HRESULT hr);
00448 };
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 inline cs_bool_t operator ==(variant const& lhs, variant const& rhs)
00463 {
00464 return lhs.equal(rhs);
00465 }
00466
00467 inline cs_bool_t operator !=(variant const& lhs, variant const& rhs)
00468 {
00469 return !operator ==(lhs, rhs);
00470 }
00471
00472 inline cs_bool_t operator ==(variant const& lhs, VARIANT const& rhs)
00473 {
00474 return lhs.equal(rhs);
00475 }
00476
00477 inline cs_bool_t operator !=(variant const& lhs, VARIANT const& rhs)
00478 {
00479 return !operator ==(lhs, rhs);
00480 }
00481
00482 inline cs_bool_t operator ==(VARIANT const& lhs, variant const& rhs)
00483 {
00484 return rhs.equal(lhs);
00485 }
00486
00487 inline cs_bool_t operator !=(VARIANT const& lhs, variant const& rhs)
00488 {
00489 return !operator ==(lhs, rhs);
00490 }
00491
00493
00494
00495 #ifdef STLSOFT_UNITTEST
00496 # include "./unittest/variant_unittest_.h"
00497 #endif
00498
00499
00500
00501
00502
00503 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00504
00505 inline void variant::handle_error_(char const* message, HRESULT hr)
00506 {
00507 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00508
00509 STLSOFT_THROW_X(com_exception(message, hr));
00510
00511 #else
00512
00513 STLSOFT_SUPPRESS_UNUSED(message);
00514
00515 ::VariantClear(this);
00516
00517 this->vt = VT_ERROR;
00518 this->scode = hr;
00519
00520 #endif
00521 }
00522
00523 inline void variant::swap_(VARIANT& lhs, VARIANT& rhs)
00524 {
00525 VARIANT t;
00526
00527 ::memcpy(&t, &lhs, sizeof(VARIANT));
00528 ::memcpy(&lhs, &rhs, sizeof(VARIANT));
00529 ::memcpy(&rhs, &t, sizeof(VARIANT));
00530 }
00531
00532
00533
00534
00535 inline variant::variant()
00536 {
00537 ::VariantInit(this);
00538 }
00539
00540 inline variant::variant(class_type const& rhs)
00541 {
00542 ::VariantInit(this);
00543
00544 class_type& rhs_ = const_cast<class_type&>(rhs);
00545 HRESULT hr = ::VariantCopy(this, &rhs_);
00546
00547 if(FAILED(hr))
00548 {
00549 handle_error_("failed to copy variant", hr);
00550 }
00551 }
00552
00553 inline variant::variant(VARIANT const& rhs)
00554 {
00555 ::VariantInit(this);
00556
00557 HRESULT hr = ::VariantCopy(this, const_cast<VARIANT*>(&rhs));
00558
00559 if(FAILED(hr))
00560 {
00561 handle_error_("failed to copy variant", hr);
00562 }
00563 }
00564
00565 inline variant::class_type& variant::operator =(variant::class_type const& rhs)
00566 {
00567 class_type r(rhs);
00568
00569 r.swap(*this);
00570
00571 return *this;
00572 }
00573
00574 inline variant::variant(bool b)
00575 {
00576 ::VariantInit(this);
00577
00578 this->vt = VT_BOOL;
00579 this->boolVal = b ? VARIANT_TRUE : VARIANT_FALSE;
00580 }
00581
00582 inline variant::variant(stlsoft::sint8_t i)
00583 {
00584 ::VariantInit(this);
00585
00586 this->vt = VT_I1;
00587 this->cVal = static_cast<CHAR>(i);
00588 }
00589
00590 inline variant::variant(stlsoft::uint8_t i)
00591 {
00592 ::VariantInit(this);
00593
00594 this->vt = VT_UI1;
00595 this->bVal = static_cast<BYTE>(i);
00596 }
00597
00598 inline variant::variant(stlsoft::sint16_t i)
00599 {
00600 ::VariantInit(this);
00601
00602 this->vt = VT_I2;
00603 this->iVal = static_cast<SHORT>(i);
00604 }
00605
00606 inline variant::variant(stlsoft::uint16_t i)
00607 {
00608 ::VariantInit(this);
00609
00610 this->vt = VT_UI2;
00611 this->uiVal = static_cast<USHORT>(i);
00612 }
00613
00614 inline variant::variant(stlsoft::sint32_t i)
00615 {
00616 ::VariantInit(this);
00617
00618 this->vt = VT_I4;
00619 this->lVal = static_cast<LONG>(i);
00620 }
00621
00622 inline variant::variant(stlsoft::uint32_t i)
00623 {
00624 ::VariantInit(this);
00625
00626 this->vt = VT_UI4;
00627 this->ulVal = static_cast<ULONG>(i);
00628 }
00629
00630 #ifdef STLSOFT_CF_SHORT_DISTINCT_INT_TYPE
00631 inline variant::variant(short i)
00632 {
00633 ::VariantInit(this);
00634
00635 this->vt = VT_I2;
00636 this->iVal = i;
00637 }
00638 inline variant::variant(unsigned short i)
00639 {
00640 ::VariantInit(this);
00641
00642 this->vt = VT_UI2;
00643 this->uiVal = i;
00644 }
00645 #endif
00646
00647 #ifdef STLSOFT_CF_INT_DISTINCT_INT_TYPE
00648 inline variant::variant(int i)
00649 {
00650 ::VariantInit(this);
00651
00652 this->vt = VT_I4;
00653 this->lVal = i;
00654 }
00655 inline variant::variant(unsigned int i)
00656 {
00657 ::VariantInit(this);
00658
00659 this->vt = VT_UI4;
00660 this->ulVal = i;
00661 }
00662 #endif
00663
00664 #ifdef STLSOFT_CF_LONG_DISTINCT_INT_TYPE
00665 inline variant::variant(long i)
00666 {
00667 ::VariantInit(this);
00668
00669 this->vt = VT_I4;
00670 this->lVal = i;
00671 }
00672 inline variant::variant(unsigned long i)
00673 {
00674 ::VariantInit(this);
00675
00676 this->vt = VT_UI4;
00677 this->ulVal = i;
00678 }
00679 #endif
00680
00681
00682 inline variant::variant(float r)
00683 {
00684 ::VariantInit(this);
00685
00686 this->vt = VT_R4;
00687 this->fltVal = r;
00688 }
00689
00690 inline variant::variant(double r)
00691 {
00692 ::VariantInit(this);
00693
00694 this->vt = VT_R8;
00695 this->dblVal = r;
00696 }
00697
00698 inline variant::variant(CY cy)
00699 {
00700 ::VariantInit(this);
00701
00702 this->vt = VT_CY;
00703 this->cyVal = cy;
00704 }
00705
00706 inline variant::variant(DECIMAL const& dec)
00707 {
00708 ::VariantInit(this);
00709
00710 this->vt = VT_DECIMAL;
00711 this->decVal.scale = dec.scale;
00712 this->decVal.sign = dec.sign;
00713 this->decVal.Hi32 = dec.Hi32;
00714 this->decVal.Mid32 = dec.Mid32;
00715 this->decVal.Lo32 = dec.Lo32;
00716 }
00717
00718 inline variant::variant(LPUNKNOWN punk, bool_type bAddRef)
00719 {
00720 ::VariantInit(this);
00721
00722 this->vt = VT_UNKNOWN;
00723 this->punkVal = punk;
00724
00725 if( bAddRef &&
00726 NULL != punk)
00727 {
00728 punk->AddRef();
00729 }
00730 }
00731
00732 inline variant::variant(LPDISPATCH pdisp, bool_type bAddRef)
00733 {
00734 ::VariantInit(this);
00735
00736 this->vt = VT_DISPATCH;
00737 this->pdispVal = pdisp;
00738
00739 if( bAddRef &&
00740 NULL != pdisp)
00741 {
00742 pdisp->AddRef();
00743 }
00744 }
00745
00746 inline variant::variant(cs_char_a_t const* s, int len )
00747 {
00748 ::VariantInit(this);
00749
00750 this->vt = VT_BSTR;
00751 this->bstrVal = (len < 0) ? bstr_create(s) : bstr_create(s, static_cast<size_type>(len));
00752
00753 if(NULL == this->bstrVal)
00754 {
00755 if( NULL != s &&
00756 '\0' != 0[s])
00757 {
00758 handle_error_("could not initialise from string", E_OUTOFMEMORY);
00759 }
00760 }
00761 }
00762
00763 inline variant::variant(cs_char_w_t const* s, int len )
00764 {
00765 ::VariantInit(this);
00766
00767 this->vt = VT_BSTR;
00768 this->bstrVal = (len < 0) ? bstr_create(s) : bstr_create(s, static_cast<size_type>(len));
00769
00770 if(NULL == this->bstrVal)
00771 {
00772 if( NULL != s &&
00773 '\0' != 0[s])
00774 {
00775 handle_error_("could not initialise from string", E_OUTOFMEMORY);
00776 }
00777 }
00778 }
00779
00780 inline variant::variant(VARIANT const& var, VARTYPE vt)
00781 {
00782 ::VariantInit(this);
00783
00784 class_type copy;
00785 HRESULT hr = ::VariantChangeType(©, const_cast<VARIANT*>(&var), 0, vt);
00786
00787 if(FAILED(hr))
00788 {
00789 handle_error_("could not convert variant to requested type", hr);
00790 }
00791 else
00792 {
00793 copy.swap(*this);
00794 }
00795 }
00796
00797 inline void variant::clear()
00798 {
00799 ::VariantClear(this);
00800 }
00801
00802 inline HRESULT variant::try_conversion_copy(VARIANT const& var, VARTYPE vt)
00803 {
00804 HRESULT hr;
00805
00806 if(vt == this->vt)
00807 {
00808 hr = S_FALSE;
00809 }
00810 else
00811 {
00812 class_type copy;
00813
00814 hr = ::VariantChangeType(©, const_cast<VARIANT*>(&var), 0, vt);
00815
00816 if(SUCCEEDED(hr))
00817 {
00818 copy.swap(*this);
00819 }
00820 }
00821
00822 return hr;
00823 }
00824
00825 inline HRESULT variant::try_convert(VARTYPE vt)
00826 {
00827 return try_conversion_copy(*this, vt);
00828 }
00829
00830 inline variant::class_type& variant::convert(VARTYPE vt)
00831 {
00832 HRESULT hr = try_convert(vt);
00833
00834 if(FAILED(hr))
00835 {
00836 handle_error_("could not convert variant to requested type", hr);
00837 }
00838
00839 return *this;
00840 }
00841
00842
00843 inline HRESULT variant::QueryInterface(REFIID riid, void** ppv) const
00844 {
00845 COMSTL_ASSERT(NULL != ppv);
00846
00847 if( VT_UNKNOWN == this->vt ||
00848 VT_DISPATCH == this->vt)
00849 {
00850 return (NULL == this->punkVal) ? E_POINTER : this->punkVal->QueryInterface(riid, ppv);
00851 }
00852
00853 return DISP_E_BADVARTYPE;
00854 }
00855
00856
00857 inline void variant::swap(variant::class_type& rhs)
00858 {
00859 swap_(*this, rhs);
00860 }
00861
00862 inline variant::bool_type variant::equal(variant::class_type const& rhs) const
00863 {
00864 return equal(static_cast<VARIANT const&>(rhs));
00865 }
00866
00867 inline variant::bool_type variant::equal(VARIANT const& rhs) const
00868 {
00869 HRESULT comparisonSucceeded;
00870 int areEqual = VARIANT_equal(*this, rhs, &comparisonSucceeded);
00871
00872 if(FAILED(comparisonSucceeded))
00873 {
00874 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00875 throw comstl::com_exception("support for comparison of variant type not currently supported", comparisonSucceeded);
00876 #else
00877 OutputDebugStringA("support for comparison of variant type not currently supported\n");
00878
00879 return false;
00880 #endif
00881 }
00882
00883 return 0 != areEqual;
00884 }
00885
00886 #endif
00887
00888
00889
00890 #ifndef _COMSTL_NO_NAMESPACE
00891 # if defined(_STLSOFT_NO_NAMESPACE) || \
00892 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00893 }
00894 # else
00895 }
00896 }
00897 # endif
00898 #endif
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 #ifndef _COMSTL_NO_NAMESPACE
00909 # if !defined(_STLSOFT_NO_NAMESPACE) && \
00910 !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00911 namespace stlsoft
00912 {
00913 # else
00914
00915 # endif
00916
00917 # if !defined(_STLSOFT_NO_NAMESPACE) && \
00918 !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00919 }
00920 # else
00921
00922 # endif
00923 #endif
00924
00925
00926
00927 #endif
00928
00929