#include "pch.h"
#include "TCStrings.h"
TC_OBJECT_EXTERN_IMPL(CTCStrings)
CTCStrings::CTCStrings()
{
}
STDMETHODIMP CTCStrings::get_Count(long* pnCount)
{
CLock lock(this);
CLEAROUT(pnCount, (long)m_vecStrings.size());
return S_OK;
}
STDMETHODIMP CTCStrings::get__NewEnum(IUnknown** ppunkEnum)
{
CLEAROUT(ppunkEnum, (IUnknown*)NULL);
typedef CComObject<CComEnum<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT,
_Copy<VARIANT> > > CEnum;
CEnum* pEnum = new CEnum;
assert(NULL != pEnum);
CLock lock(this);
std::vector<CComVariant> vecTemp(m_vecStrings.size(), CComVariant());
for (UINT i = 0; i < m_vecStrings.size(); ++i)
vecTemp[i] = m_vecStrings[i];
#if _MSC_VER >= 1310
HRESULT hr = pEnum->Init(&(*vecTemp.begin()), &(*vecTemp.end()), NULL, AtlFlagCopy);
#else
HRESULT hr = pEnum->Init(vecTemp.begin(), vecTemp.end(), NULL, AtlFlagCopy);
#endif
if (SUCCEEDED(hr))
hr = pEnum->QueryInterface(IID_IEnumVARIANT, (void**)ppunkEnum);
if (FAILED(hr))
delete pEnum;
return hr;
}
STDMETHODIMP CTCStrings::get_Item(VARIANT* pvIndex, BSTR* pbstr)
{
CLEAROUT(pbstr, (BSTR)NULL);
CComVariant var;
HRESULT hr = VariantChangeType(&var, pvIndex, 0, VT_I4);
if (FAILED(hr))
return hr;
CLock lock(this);
if (V_I4(&var) < 0 || V_I4(&var) >= (int)m_vecStrings.size())
return E_INVALIDARG;
*pbstr = m_vecStrings[V_I4(&var)].Copy();
return S_OK;
}
STDMETHODIMP CTCStrings::Add(BSTR bstr)
{
CLock lock(this);
m_vecStrings.push_back(bstr);
return S_OK;
}
STDMETHODIMP CTCStrings::Remove(VARIANT* pvIndex)
{
CComVariant var;
RETURN_FAILED(VariantChangeType(&var, pvIndex, 0, VT_I4));
CLock lock(this);
if (V_I4(&var) < 0 || V_I4(&var) >= (int)m_vecStrings.size())
return E_INVALIDARG;
m_vecStrings.erase(m_vecStrings.begin() + V_I4(&var));
return S_OK;
}
STDMETHODIMP CTCStrings::RemoveAll()
{
CLock lock(this);
m_vecStrings.clear();
return S_OK;
}
STDMETHODIMP CTCStrings::AddDelimited(BSTR bstrDelimiter, BSTR bstrStrings)
{
UINT cchDelim = SysStringLen(bstrDelimiter);
if (!cchDelim)
return E_INVALIDARG;
LPCOLESTR psz = bstrStrings;
while (psz)
{
LPCOLESTR pszFound = wcsstr(psz, bstrDelimiter);
if (pszFound)
{
m_vecStrings.push_back(CComBSTR(pszFound - psz, psz));
psz = pszFound + cchDelim;
}
else
{
m_vecStrings.push_back(CComBSTR(psz));
psz = NULL;
}
};
return S_OK;
}
STDMETHODIMP CTCStrings::get_DelimitedItems(BSTR bstrDelimiter,
BSTR* pbstrStrings)
{
CLEAROUT(pbstrStrings, (BSTR)NULL);
UINT cchDelim = SysStringLen(bstrDelimiter);
if (!cchDelim)
return E_INVALIDARG;
UINT cchTotal = 1;
UINT nCount = m_vecStrings.size();
for (UINT i = 0; i < nCount; ++i)
{
if (i)
cchTotal += cchDelim;
cchTotal += m_vecStrings[i].Length();
}
LPOLESTR psz = new OLECHAR[cchTotal];
*psz = OLESTR('\0');
for (UINT i = 0; i < nCount; ++i)
{
if (i)
wcscat(psz, bstrDelimiter);
if (m_vecStrings[i].Length())
wcscat(psz, m_vecStrings[i]);
}
*pbstrStrings = SysAllocStringLen(psz, cchTotal - 1);
delete [] psz;
return S_OK;
}
STDMETHODIMP CTCStrings::AddStrings(ITCStrings* pStrings)
{
Lock();
HRESULT hr = S_OK;
BSTR bstr = NULL;
__try
{
long nCount = 0;
if (!pStrings || FAILED(hr = pStrings->get_Count(&nCount)))
{
VARIANT v;
VariantInit(&v);
V_VT(&v) = VT_I4;
V_I4(&v) = 0;
for (; V_I4(&v) < nCount; ++V_I4(&v))
{
if (FAILED(hr = pStrings->get_Item(&v, &bstr)))
break;
if (FAILED(hr = Add(bstr)))
break;
}
}
}
__except(1)
{
hr = E_POINTER;
}
Unlock();
if (bstr)
SysFreeString(bstr);
return hr;
}
STDMETHODIMP CTCStrings::put_Collection1(VARIANT* pvarSafeArray)
{
CLock lock(this);
VARTYPE vt = V_VT(pvarSafeArray);
if ((VT_BSTR | VT_ARRAY) != vt)
{
m_vecStrings.clear();
return E_INVALIDARG;
}
SAFEARRAY* psa = V_ARRAY(pvarSafeArray);
if (1 != SafeArrayGetDim(psa))
{
m_vecStrings.clear();
return E_INVALIDARG;
}
LONG cElements, lLBound, lUBound;
HRESULT hr = SafeArrayGetLBound(psa, 1, &lLBound);
if (SUCCEEDED(hr))
hr = SafeArrayGetUBound(psa, 1, &lUBound);
if (FAILED(hr))
{
m_vecStrings.clear();
return hr;
}
cElements = lUBound - lLBound + 1;
BSTR* pbstr = NULL;
hr = SafeArrayAccessData(psa, (void **)&pbstr);
if (FAILED(hr))
{
m_vecStrings.clear();
return hr;
}
TCSafeArrayAccess saa(psa);
m_vecStrings.clear();
m_vecStrings.resize(cElements);
for (long i = 0; i < cElements; i++)
m_vecStrings[i] = pbstr[i];
return S_OK;
}
STDMETHODIMP CTCStrings::get_Collection1(VARIANT* pvarSafeArray)
{
__try
{
VariantInit(pvarSafeArray);
}
__except(1)
{
return E_POINTER;
}
Lock();
HRESULT hr = S_OK;
__try
{
long nCount = m_vecStrings.size();
SAFEARRAY* psa = SafeArrayCreateVector(VT_BSTR, 0, nCount);
if (!psa)
hr = E_OUTOFMEMORY;
else
{
V_VT(pvarSafeArray) = VT_ARRAY | VT_BSTR;
V_ARRAY(pvarSafeArray) = psa;
for (long i = 0; i < nCount; ++i)
SafeArrayPutElement(psa, &i, m_vecStrings[i].Copy());
}
}
__except(1)
{
hr = RPC_E_SERVERFAULT;
}
Unlock();
if (FAILED(hr))
VariantClear(pvarSafeArray);
return hr;
}