michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "IEnumFE.h" michael@0: #include "nsAlgorithm.h" michael@0: #include michael@0: michael@0: CEnumFormatEtc::CEnumFormatEtc() : michael@0: mRefCnt(0), michael@0: mCurrentIdx(0) michael@0: { michael@0: } michael@0: michael@0: // Constructor used by Clone() michael@0: CEnumFormatEtc::CEnumFormatEtc(nsTArray& aArray) : michael@0: mRefCnt(0), michael@0: mCurrentIdx(0) michael@0: { michael@0: // a deep copy, calls FormatEtc's copy constructor on each michael@0: mFormatList.AppendElements(aArray); michael@0: } michael@0: michael@0: CEnumFormatEtc::~CEnumFormatEtc() michael@0: { michael@0: } michael@0: michael@0: /* IUnknown impl. */ michael@0: michael@0: STDMETHODIMP michael@0: CEnumFormatEtc::QueryInterface(REFIID riid, LPVOID *ppv) michael@0: { michael@0: *ppv = nullptr; michael@0: michael@0: if (IsEqualIID(riid, IID_IUnknown) || michael@0: IsEqualIID(riid, IID_IEnumFORMATETC)) michael@0: *ppv = (LPVOID)this; michael@0: michael@0: if (*ppv == nullptr) michael@0: return E_NOINTERFACE; michael@0: michael@0: // AddRef any interface we'll return. michael@0: ((LPUNKNOWN)*ppv)->AddRef(); michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP_(ULONG) michael@0: CEnumFormatEtc::AddRef() michael@0: { michael@0: ++mRefCnt; michael@0: NS_LOG_ADDREF(this, mRefCnt, "CEnumFormatEtc",sizeof(*this)); michael@0: return mRefCnt; michael@0: } michael@0: michael@0: STDMETHODIMP_(ULONG) michael@0: CEnumFormatEtc::Release() michael@0: { michael@0: uint32_t refReturn; michael@0: michael@0: refReturn = --mRefCnt; michael@0: NS_LOG_RELEASE(this, mRefCnt, "CEnumFormatEtc"); michael@0: michael@0: if (mRefCnt == 0) michael@0: delete this; michael@0: michael@0: return refReturn; michael@0: } michael@0: michael@0: /* IEnumFORMATETC impl. */ michael@0: michael@0: STDMETHODIMP michael@0: CEnumFormatEtc::Next(ULONG aMaxToFetch, FORMATETC *aResult, ULONG *aNumFetched) michael@0: { michael@0: // If the method retrieves the number of items requested, the return michael@0: // value is S_OK. Otherwise, it is S_FALSE. michael@0: michael@0: if (aNumFetched) michael@0: *aNumFetched = 0; michael@0: michael@0: // aNumFetched can be null if aMaxToFetch is 1 michael@0: if (!aNumFetched && aMaxToFetch > 1) michael@0: return S_FALSE; michael@0: michael@0: if (!aResult) michael@0: return S_FALSE; michael@0: michael@0: // We're done walking the list michael@0: if (mCurrentIdx >= mFormatList.Length()) michael@0: return S_FALSE; michael@0: michael@0: uint32_t left = mFormatList.Length() - mCurrentIdx; michael@0: michael@0: if (!aMaxToFetch) michael@0: return S_FALSE; michael@0: michael@0: uint32_t count = std::min(static_cast(aMaxToFetch), left); michael@0: michael@0: uint32_t idx = 0; michael@0: while (count > 0) { michael@0: // Copy out to aResult michael@0: mFormatList[mCurrentIdx++].CopyOut(&aResult[idx++]); michael@0: count--; michael@0: } michael@0: michael@0: if (aNumFetched) michael@0: *aNumFetched = idx; michael@0: michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: CEnumFormatEtc::Skip(ULONG aSkipNum) michael@0: { michael@0: // If the method skips the number of items requested, the return value is S_OK. michael@0: // Otherwise, it is S_FALSE. michael@0: michael@0: if ((mCurrentIdx + aSkipNum) >= mFormatList.Length()) michael@0: return S_FALSE; michael@0: michael@0: mCurrentIdx += aSkipNum; michael@0: michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: CEnumFormatEtc::Reset(void) michael@0: { michael@0: mCurrentIdx = 0; michael@0: return S_OK; michael@0: } michael@0: michael@0: STDMETHODIMP michael@0: CEnumFormatEtc::Clone(LPENUMFORMATETC *aResult) michael@0: { michael@0: // Must return a new IEnumFORMATETC interface with the same iterative state. michael@0: michael@0: if (!aResult) michael@0: return E_INVALIDARG; michael@0: michael@0: CEnumFormatEtc * pEnumObj = new CEnumFormatEtc(mFormatList); michael@0: michael@0: if (!pEnumObj) michael@0: return E_OUTOFMEMORY; michael@0: michael@0: pEnumObj->AddRef(); michael@0: pEnumObj->SetIndex(mCurrentIdx); michael@0: michael@0: *aResult = pEnumObj; michael@0: michael@0: return S_OK; michael@0: } michael@0: michael@0: /* utils */ michael@0: michael@0: void michael@0: CEnumFormatEtc::AddFormatEtc(LPFORMATETC aFormat) michael@0: { michael@0: if (!aFormat) michael@0: return; michael@0: FormatEtc * etc = mFormatList.AppendElement(); michael@0: // Make a copy of aFormat michael@0: if (etc) michael@0: etc->CopyIn(aFormat); michael@0: } michael@0: michael@0: /* private */ michael@0: michael@0: void michael@0: CEnumFormatEtc::SetIndex(uint32_t aIdx) michael@0: { michael@0: mCurrentIdx = aIdx; michael@0: }