windows-nt/Source/XPSP1/NT/admin/activec/designer/vb98ctls/framewrk/strcoll.cpp
2020-09-26 16:20:57 +08:00

354 lines
8.3 KiB
C++

//=--------------------------------------------------------------------------=
// StringsColl.Cpp
//=--------------------------------------------------------------------------=
// Copyright 1995 Microsoft Corporation. All Rights Reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//=--------------------------------------------------------------------------=
//
// implementation for our simple strings collections.
//
#include "pch.h"
#include "SimpleEnumVar.H"
#include "StringsColl.H"
// for asserts
//
SZTHISFILE
//=--------------------------------------------------------------------------=
// CStringsCollection::CStringsCollection
//=--------------------------------------------------------------------------=
// constructor. sets up the safearray pointer.
//
// Parameters:
// SAFEARRAY - [in] the collection we're working with.
//
// Notes:
//
CStringCollection::CStringCollection
(
SAFEARRAY *psa
)
: m_psa(psa)
{
ASSERT(m_psa, "Bogus Safearray pointer!");
}
//=--------------------------------------------------------------------------=
// CStringCollection::~CStringCollection
//=--------------------------------------------------------------------------=
//
// Notes:
//
CStringCollection::~CStringCollection()
{
}
//=--------------------------------------------------------------------------=
// CStringCollection::get_Count
//=--------------------------------------------------------------------------=
// returns the count of the things in the collection
//
// Parameters:
// long * - [out] the count
//
// Output:
// HRESULT - S_OK, one of the SAFEARRAY Scodes.
//
// Notes:
// - we're assuming the safearray's lower bound is zero!
//
STDMETHODIMP CStringCollection::get_Count
(
long *plCount
)
{
HRESULT hr;
ASSERT(m_psa, "Who created a collection without a SAFEARRAY?");
CHECK_POINTER(plCount);
// get the bounds.
//
hr = SafeArrayGetUBound(m_psa, 1, plCount);
CLEARERRORINFORET_ON_FAILURE(hr);
// add one since we're zero-offset
//
(*plCount)++;
return S_OK;
}
//=--------------------------------------------------------------------------=
// CStringCollection::get_Item
//=--------------------------------------------------------------------------=
// returns a string given an INDEX
//
// Parameters:
// long - [in] the index to get it from
// BSTR * - [out] the item
//
// Output:
// HRESULT - S_OK, E_OUTOFMEMORY
//
// Notes:
//
STDMETHODIMP CStringCollection::get_Item
(
long lIndex,
BSTR *pbstrItem
)
{
HRESULT hr;
CHECK_POINTER(pbstrItem);
// get the element from the safearray
//
hr = SafeArrayGetElement(m_psa, &lIndex, pbstrItem);
CLEARERRORINFORET_ON_FAILURE(hr);
// otherwise, we've got it, so we can return
//
return S_OK;
}
//=--------------------------------------------------------------------------=
// CStringCollection::get__NewEnum
//=--------------------------------------------------------------------------=
// returns a new IEnumVARIANT object with the collection in it.
//
// Parameters:
// IUnknown ** - [out] new enumvariant object.
//
// Output:
// HRESULT - S_OK, E_OUTOFMEMORY
//
// Notes:
//
STDMETHODIMP CStringCollection::get__NewEnum
(
IUnknown **ppUnkNewEnum
)
{
HRESULT hr;
long l;
CHECK_POINTER(ppUnkNewEnum);
// get the count of things in the SAFEARRAY
//
hr = get_Count(&l);
CLEARERRORINFORET_ON_FAILURE(hr);
// create the object.
//
*ppUnkNewEnum = (IUnknown *) new CSimpleEnumVariant(m_psa, l);
if (!*ppUnkNewEnum)
CLEARERRORINFORET(E_OUTOFMEMORY);
// refcount is already 1, so we can leave.
//
return S_OK;
}
//=--------------------------------------------------------------------------=
//=--------------------------------------------------------------------------=
// CStringDynaCollection::CStringDynaCollection
//=--------------------------------------------------------------------------=
// constructor for this object. doesn't do very much.
//
// Parameters:
// same as for CStringCollection
//
// Notes:
//
CStringDynaCollection::CStringDynaCollection
(
SAFEARRAY *psa
)
: CStringCollection(psa)
{
}
//=--------------------------------------------------------------------------=
// CStringDynaCollection::~CStringDynaCollection
//=--------------------------------------------------------------------------=
// destructor.
//
// Notes:
//
CStringDynaCollection::~CStringDynaCollection()
{
}
//=--------------------------------------------------------------------------=
// CStringDynaCollection::put_Item
//=--------------------------------------------------------------------------=
// sets the value of an item in the array.
//
// Parameters:
// long - [in] index at which to put it
// BSTR - [in] new value.
//
// Output:
// HRESULT - S_OK, safearray Scode.
//
// Notes:
// - NULLs are converted to ""
//
STDMETHODIMP CStringDynaCollection::put_Item
(
long lIndex,
BSTR bstr
)
{
HRESULT hr;
long l;
BSTR bstr2 = NULL;
// get the count and verify our index
//
hr = get_Count(&l);
RETURN_ON_FAILURE(hr);
if (lIndex < 0 || lIndex >= l)
CLEARERRORINFORET(E_INVALIDARG);
// put out the string, convert NULLs to ""
//
if (!bstr) {
bstr2 = SysAllocString(L"");
RETURN_ON_NULLALLOC(bstr2);
}
hr = SafeArrayPutElement(m_psa, &lIndex, (bstr) ? bstr : bstr2);
if (bstr2) SysFreeString(bstr2);
CLEARERRORINFORET_ON_FAILURE(hr);
return S_OK;
}
//=--------------------------------------------------------------------------=
// CStringDynaCollection::Add
//=--------------------------------------------------------------------------=
// adds a new string to the end of the collection.
//
// Parameters:
// BSTR - [in] the new string to add
//
// Notes:
//
STDMETHODIMP CStringDynaCollection::Add
(
BSTR bstr
)
{
SAFEARRAYBOUND sab;
BSTR bstr2 = NULL;
HRESULT hr;
long l;
// get the current size of the array.
//
hr = get_Count(&l);
RETURN_ON_FAILURE(hr);
// add one new elemnt
//
sab.cElements = l + 1;
sab.lLbound = 0;
// redim the array.
//
hr = SafeArrayRedim(m_psa, &sab);
CLEARERRORINFORET_ON_FAILURE(hr);
// put the out string, converting NULLs to ""
//
if (!bstr) {
bstr2 = SysAllocString(L"");
RETURN_ON_NULLALLOC(bstr2);
}
hr = SafeArrayPutElement(m_psa, &l, (bstr) ? bstr : bstr2);
if (bstr2) SysFreeString(bstr2);
CLEARERRORINFORET_ON_FAILURE(hr);
return S_OK;
}
//=--------------------------------------------------------------------------=
// CStringDynaCollection::Remove
//=--------------------------------------------------------------------------=
// removes an element from the collection, and shuffles all the rest down to
// fill up the space.
//
// Parameters:
// long - [in] index of dude to remove.
//
// Output:
// HRESULT - S_OK, safearray Scodes.
//
// Notes:
//
STDMETHODIMP CStringDynaCollection::Remove
(
long lIndex
)
{
SAFEARRAYBOUND sab;
HRESULT hr;
BSTR bstr;
long lCount;
long x, y;
// first get the count of things in our array.
//
hr = get_Count(&lCount);
RETURN_ON_FAILURE(hr);
// check the index
//
if (lIndex < 0 || lIndex >= lCount)
CLEARERRORINFORET(E_INVALIDARG);
// let's go through, shuffling everything down one.
//
for (x = lIndex, y = x + 1; x < lCount - 1; x++, y++) {
// get the next element.
//
hr = SafeArrayGetElement(m_psa, &y, &bstr);
CLEARERRORINFORET_ON_FAILURE(hr);
// set it at the current location
//
hr = SafeArrayPutElement(m_psa, &x, bstr);
CLEARERRORINFORET_ON_FAILURE(hr);
}
// we're at the last element. let's go and kill it.
//
sab.cElements = lCount - 1;
sab.lLbound = 0;
// CONSIDER: 9.95 -- there is a bug in oleaut32.dll which causes the
// below to fail if cElements = 0.
//
hr = SafeArrayRedim(m_psa, &sab);
CLEARERRORINFORET_ON_FAILURE(hr);
// we're done. go bye-bye.
//
return S_OK;
}