#include "stdafx.h"
#include <comutil.h>
#include "SgxVariant.h"
CSgxVariant::CSgxVariant(void)
{
}
CSgxVariant::CSgxVariant(VARTYPE vtNew, ULONG nCount, void* pData)
{
Redim(nCount, vtNew);
int nElementSize = GetElementSizeFromVt(vtNew);
if(nElementSize >= 0 && pData != NULL)
SetData(pData, nCount, nElementSize);
}
CSgxVariant::CSgxVariant(VARIANT v) : _variant_t(v) {}
CSgxVariant::~CSgxVariant(void)
{
}
VARTYPE CSgxVariant::GetDataType()
{
VARTYPE vta;
if (IsArray())
{
SAFEARRAY** ppArr = GetSafeArrayPtrPtr();
if (*ppArr == NULL) //空数组
return VT_ERROR;
HRESULT hr = SafeArrayGetVartype(*ppArr, &vta);
if (FAILED(hr))
{
ASSERT(FALSE);
return VT_ERROR;
}
return vta;
}
else
{
return vt;
}
}
int CSgxVariant::GetArrayType()
{
//支持四种形式, 1 传值模式的数组,vt : VT_ARRAY parray保存
// 2 引用形式的数组,vt: VT_ARRAY | VT_BYREFT pparray保存
// 3 引用传递VARIANT,vt:VT_BYREF | VT_VARIANT , pvarVal->vt: VT_ARRAY pvarVal->parray 或 4 pvalVal->pparray保存
if(vt & VT_ARRAY )
{
if(vt & VT_BYREF)
return VARIANT_ARRAY_TYPE_PP;
else
return VARIANT_ARRAY_TYPE_P;
}
else if(vt & VT_BYREF && vt & VT_VARIANT && pvarVal->vt & VT_ARRAY )
{
if(pvarVal->vt & VT_BYREF)
return VARIANT_ARRAY_TYPE_V_PP;
else
return VARIANT_ARRAY_TYPE_V_P;
}
return 0;
}
VARTYPE CSgxVariant::GetArrayVT()
{
if(vt & VT_ARRAY )
{
return vt;
}
else if(vt & VT_BYREF && vt & VT_VARIANT && pvarVal->vt & VT_ARRAY )
{
return pvarVal->vt;
}
return 0;
}
BOOL CSgxVariant::IsArray()
{
return GetArrayType() > 0;
}
SAFEARRAY** CSgxVariant::GetSafeArrayPtrPtr()
{
int nType = GetArrayType();
ASSERT(nType > 0);
switch (nType)
{
case VARIANT_ARRAY_TYPE_P:
return &parray;
break;
case VARIANT_ARRAY_TYPE_PP:
return pparray;
break;
case VARIANT_ARRAY_TYPE_V_P:
return &pvarVal->parray;
break;
case VARIANT_ARRAY_TYPE_V_PP:
return pvarVal->pparray;
break;
}
return NULL;
}
void* CSgxVariant::GetArrayData()
{
SAFEARRAY** ppArr = GetSafeArrayPtrPtr();
if(ppArr == NULL)
return NULL;
else
return (*ppArr)->pvData;
}
long CSgxVariant::GetDimensions()
{
SAFEARRAY** ppArr = GetSafeArrayPtrPtr();
if(ppArr == NULL)
return -1;
return (*ppArr)->cDims;
}
long CSgxVariant::GetSize()
{
SAFEARRAY** ppArr = GetSafeArrayPtrPtr();
if(ppArr == NULL)
return -1;
ASSERT((*ppArr)->cDims == 1);
return (*ppArr)->rgsabound[0].cElements;
}
long CSgxVariant::GetSize(long nDim)
{
SAFEARRAY** ppArr = GetSafeArrayPtrPtr();
if(ppArr == NULL)
return -1;
long Lbound, Ubound;
SafeArrayGetLBound(*ppArr, nDim + 1, &Lbound);//nDim base 1
SafeArrayGetUBound(*ppArr, nDim + 1, &Ubound);//nDim base 1
return Ubound - Lbound + 1;
//return (*ppArr)->rgsabound[nDim].cElements;
}
BOOL CSgxVariant::Redim(long n1, VARTYPE vtNew)
{
ASSERT(n1 >=0);
SAFEARRAYBOUND MyBound[1];
MyBound[0].cElements = n1;
MyBound[0].lLbound = 0;
if(!(vt & VT_ARRAY) || GetDataType() != vtNew)
{
VariantInit(this);
vt = VT_ARRAY | vtNew;
this->parray=SafeArrayCreateVector(vtNew, 0, n1);
if (parray == NULL)
return FALSE;
}
else
{
SAFEARRAY** ppArr = GetSafeArrayPtrPtr();
HRESULT hr = SafeArrayRedim(*ppArr, MyBound);
if (FAILED(hr))
return FALSE;
}
if (vtNew == VT_BSTR)
_InitBStrArray();
return TRUE;
}
BOOL CSgxVariant::Redim(long n1, long n2, VARTYPE vtNew)
{
ASSERT(n1 >=0 && n2 >=0);
SAFEARRAYBOUND MyBound[2];
MyBound[0].cElements = n1;
MyBound[0].lLbound = 0;
MyBound[1].cElements = n2;
MyBound[1].lLbound = 0;
if (!(vt & VT_ARRAY) || GetDataType() != vtNew)
{
VariantInit(this);
vt = VT_ARRAY | vtNew;
this->parray=SafeArrayCreate(vtNew, 2, MyBound);
if (parray == NULL)
return FALSE;
}
else
{
SAFEARRAY** ppArr = GetSafeArrayPtrPtr();
if (*ppArr != NULL)
SafeArrayDestroy(*ppArr);
*ppArr = SafeArrayCreate(vtNew, 2, MyBound);
if (*ppArr == NULL)
return FALSE;
//return SafeArrayRedim(*ppArr, MyBound) == S_OK;
}
return TRUE;
}
BOOL CSgxVariant::Redim(long n1, long n2, long n3, VARTYPE vtNew)
{
ASSERT(n1 >=0 && n2 >=0 && n3 >= 0);
SAFEARRAYBOUND MyBound[3];
MyBound[0].cElements = n1;
MyBound[0].lLbound = 0;
MyBound[1].cElements = n2;
MyBound[1].lLbound = 0;
MyBound[2].cElements = n3;
MyBound[2].lLbound = 0;
if (!(vt & VT_ARRAY) || GetDataType() != vtNew)
{
VariantInit(this);
vt = VT_ARRAY | vtNew;
this->parray=SafeArrayCreate(vtNew, 3, MyBound);
if (parray == NULL)
return FALSE;
}
else
{
SAFEARRAY** ppArr = GetSafeArrayPtrPtr();
if (*ppArr != NULL)
SafeArrayDestroy(*ppArr);
*ppArr = SafeArrayCreate(vtNew, 3, MyBound);
if (*ppArr == NULL)
return FALSE;
//return SafeArrayRedim(*ppArr, MyBound) == S_OK;
}
return TRUE;
}
BOOL CSgxVariant::Redim(long n1, long n2, long n3, long n4, VARTYPE vtNew)
{
ASSERT(n1 >= 0 && n2 >= 0 && n3 >= 0 && n4 >= 0);
SAFEARRAYBOUND MyBound[4];
MyBound[0].cElements = n1;
MyBound[0].lLbound = 0;
MyBound[1].cElements = n2;
MyBound[1].lLbound = 0;
MyBound[2].cElements = n3;
MyBound[2].lLbound = 0;
MyBound[3].cElements = n4;
MyBound[3].lLbound = 0;
if (!(vt & VT_ARRAY) || GetDataType() != vtNew)
{
VariantInit(this);
vt = VT_ARRAY | vtNew;
this->parray=SafeArrayCreate(vtNew, 3, MyBound);
if (parray == NULL)
return FALSE;
}
else
{
SAFEARRAY** ppArr = GetSafeArrayPtrPtr();
if (*ppArr != NULL)
SafeArrayDestroy(*ppArr);
*ppArr = SafeArrayCreate(vtNew, 4, MyBound);
if (*ppArr == NULL)
return FALSE;
//return SafeArrayRedim(*ppArr, MyBound) == S_OK;
}
return TRUE;
}
BOOL CSgxVariant::RedimPreserve(long nNewCount)
{
ASSERT(nNewCount >= 0);
SAFEARRAY** ppArr = GetSafeArrayPtrPtr();
if(ppArr == NULL)
return FALSE;
int nElementSize = GetElementSizeFromVt(vt);
if(nElementSize <= 0)
return FALSE;
//保留原始数据
BYTE* pNewData=NULL, *pOldData=(BYTE*)(*ppArr)->pvData;
try{
pNewData= new BYTE[nNewCount * nElementSize];
}
catch(...)
{
return FALSE;
}
int nCopyCount;
if(nNewCount < GetSize())//缩小数组
nCopyCount=nNewCount;
else //增大数组
{
nCopyCount=GetSize();
ZeroMemory(pNewData + nCopyCount*nElementSize,(nNewCount-GetSize())* nElementSize);
}
memcpy(pNewData, pOldData, nElementSize*nCopyCount);
//重新设置大小
SAFEARRAYBOUND BoundNew[1];
BoundNew[0].cElements = nNewCount;
BoundNew[0].lLbound = 0;
SafeArrayRedim(*ppArr,BoundNew);
//赋值
//ULONG i;
//long ix[1];
//BYTE* p = pNewData;
//for(i=0; i<nNewCount; ++i)
//{
// ix[0]=i;
// SafeArrayPutElement(parray, ix, (void *)p);
// p += nElementSize;
//}
BOOL bRet = SetData((void*)pNewData, nNewCount, nElementSize);
//清理
delete [] pNewData;
return bRet;
}
BOOL CSgxVariant::SetData(void* pData, long nCount, int nElemenstSize)
{
long nOldCount=GetSize();
ASSERT(!(nOldCount < 1 || nCount > nOldCount || nElemenstSize <= 0));
if(nOldCount < 1 || nCount > nOldCount || nElemenstSize <= 0)
return FALSE;
if(pData == NULL || nCount == 0)
return TRUE;
SAFEARRAY** ppArr = GetSafeArrayPtrPtr();
if(ppArr == NULL)
return FALSE;
ASSERT((*ppArr)->cbElements == nElemenstSize);
BYTE* p = (BYTE*)pData;
long ix[1];
//指定的数据个数不够
if(!::AfxIsValidAddress(p, nElemenstSize * nCount, TRUE))
return FALSE;
for(long i = 0; i < nCount; i++)
{
ix[0]=i;
SafeArrayPutElement(*ppArr, ix, (void *)p);
p += nElemenstSize;
}
return TRUE;
}
//static functions
long CSgxVariant::_GetSize(VARIANT& v)
{
CSgxVariant sv;
sv.Attach(v);
long nSize = sv.GetSize();
v = sv.Detach();
return nSize;
}
BOOL CSgxVariant::EqualVt(VARTYPE vt1, VARTYPE vt2)
{
NormalizeVt(vt1);
Normaliz

哆啦刘小洋
- 粉丝: 250
- 资源: 5