⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ienumiterator.hpp

📁 Visual C++下的界面设计
💻 HPP
📖 第 1 页 / 共 2 页
字号:
		Next();
		numSkipped++;
	}

	return numSkipped;
}

template <class T, class E>
void TCache<T,E>::Destroy()
{
	EmptyCache();

	delete [] m_pCache;
}

template <class T, class E>
void TCache<T,E>::DestroyItem(E item)
{
	// It's easier to place the replacable code for destroying an 
	// item in the iterator.... So, we'll call a private static member function
	// on our iterator to destroy it
	
	T::DestroyItem(item);
}


template <class T, class E>
E *TCache<T,E>::CopyCache() const
{
	return CopyCache(m_pCache, m_current, m_cached, m_allocatedSize);
}

template <class T, class E>
E *TCache<T,E>::CopyCache(
	E *pCache, 
	unsigned long current, 
	unsigned long cached, 
	unsigned long newSize)
{
	E *pNewCache = 0;
	
	if (newSize)
	{
		pNewCache = new E[newSize];

		// Only copy the valid area of the cache...

		for (unsigned long i = current; i < cached; i++)
		{
			pNewCache[i] = T::CopyItem(pCache[i]);
		}
	}
	
	return pNewCache;
}

///////////////////////////////////////////////////////////////////////////////
// Implement IEnumIterator
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// Construction and destruction
///////////////////////////////////////////////////////////////////////////////

template <class T, class I, class E> 
IEnumIterator<T,I,E>::IEnumIterator(I *pIEnum, unsigned long max /* = 1 */)
   :	m_pIEnum(SafeAddRef(pIEnum)),
		m_cache(max),
		m_bAtEnd(false),
		m_bNotPrimed(true)
{
	if (!m_pIEnum)
	{
		m_bAtEnd = true;
		m_bNotPrimed = false;
	}
}

template <class T, class I, class E> 
IEnumIterator<T,I,E>::IEnumIterator(const IEnumIterator<T,I,E> &rhs)
	:	m_pIEnum(0),
		m_cache(rhs.m_cache),
		m_bAtEnd(rhs.m_bAtEnd),
		m_bNotPrimed(rhs.m_bNotPrimed)
{
   if (rhs.m_pIEnum)
   {
      HRESULT hr = rhs.m_pIEnum->Clone(&m_pIEnum);

      if (FAILED(hr))
      {
         throw CComException(_T("IEnumIterator<T,I,E>::IEnumIterator()"), hr);
      }
   }
}

template <class T, class I, class E> 
IEnumIterator<T,I,E>::~IEnumIterator()
{
	m_pIEnum = SafeRelease(m_pIEnum);
}

template <class T, class I, class E> 
IEnumIterator<T,I,E> &IEnumIterator<T,I,E>::operator=(const IEnumIterator<T,I,E> &rhs)
{
   if (this != &rhs)
   {
      if (rhs.m_pIEnum)
      {
         I *pNewEnum = 0;

         HRESULT hr = rhs.m_pIEnum->Clone(&pNewEnum);

         if (SUCCEEDED(hr))
         {
            m_pIEnum->Release();

            m_pIEnum = pNewEnum;

				m_cache = rhs.m_cache;
			}
         else
         {
            throw CComException("IEnumIterator<T,I,E>::operator=", hr);
         }
      }
      else
      {
         m_pIEnum = 0;
      }

		m_bAtEnd = rhs.m_bAtEnd;
		m_bNotPrimed = rhs.m_bNotPrimed;
   }

   return *this;
}

///////////////////////////////////////////////////////////////////////////////
// Iteration
///////////////////////////////////////////////////////////////////////////////

template <class T, class I, class E> 
IEnumIterator<T,I,E> &IEnumIterator<T,I,E>::operator++()
{
	// Since we no longer call advance in the ctor we must 
	// make sure it's been called once to make the first item
	// valid before we advance away from the first item,
	// It's messier but at least we don't have a fully primed 
	// iterator to copy around straight after construction...

	CheckPrimed();

   Advance();

   return *this;
}

#ifdef IENUM_ITERATOR_USE_POST_INC

template <class T, class I, class E> 
IEnumIterator<T,I,E> IEnumIterator<T,I,E>::operator++(int)
{
	// Since we no longer call advance in the ctor we must 
	// make sure it's been called once to make the first item
	// valid before we advance away from the first item,
	// It's messier but at least we don't have a fully primed 
	// iterator to copy around straight after construction...

	CheckPrimed();

   T oldValue = *this;

   Advance();

   return oldValue;
}

#endif // IENUM_ITERATOR_USE_POST_INC

template <class T, class I, class E> 
bool IEnumIterator<T,I,E>::operator!=(const IEnumIterator<T,I,E> &rhs)
{
   // defer to operator==
   return !(*this == rhs);
}

template <class T, class I, class E> 
bool IEnumIterator<T,I,E>::operator==(const IEnumIterator<T,I,E> &rhs)
{
	// Since we no longer call advance in the ctor we must 
	// make sure it's been called once to make the first item
	// valid before we access it for the first time.
	// It's messier but at least we don't have a fully primed 
	// iterator to copy around straight after construction...

	CheckPrimed();

	// should compare contents of Enumerated?
   return ((m_pIEnum == rhs.m_pIEnum && (true)) || 
		      m_bAtEnd && m_cache.IsEmpty() && 
				rhs.m_bAtEnd && rhs.m_cache.IsEmpty());
}

template <class T, class I, class E> 
const T &IEnumIterator<T,I,E>::End()
{
	static T End(0,0);

	return End;
}

template <class T, class I, class E> 
void IEnumIterator<T,I,E>::Reset()
{
	if (m_pIEnum)
	{
		HRESULT hr = m_pIEnum->Reset();

		if (S_OK != hr)
		{
			throw CComException(_T("IEnumIterator<T,I,E>::Reset()"), hr);
		}
	
		m_bAtEnd = false;

		m_cache.EmptyCache();

		m_bNotPrimed = true;
	}
}

template <class T, class I, class E> 
unsigned long IEnumIterator<T,I,E>::Skip(unsigned long numToSkip)
{
	unsigned long numSkipped = 0;

   if (m_pIEnum)
   {
		numSkipped = m_cache.Skip(numToSkip);

		if (numSkipped != numToSkip)
		{
			// Even after skipping all entries in the cache, we still must
			// skip more...

			if (S_OK == m_pIEnum->Skip(numToSkip - numSkipped))
			{
				numSkipped = numToSkip;
			}
			else
			{
				// That's all folks...

				m_bAtEnd = true;
			}
		
			// cache is empty now, but we'll leave priming it until we need
			// to access it...

			m_bNotPrimed = true;
		}
	}

	return numSkipped;
}

///////////////////////////////////////////////////////////////////////////////
// Access to what we're enumerating...
///////////////////////////////////////////////////////////////////////////////

template <class T, class I, class E> 
const E &IEnumIterator<T,I,E>::Enumerated() const
{
	// Since we no longer call advance in the ctor we must 
	// make sure it's been called once to make the first item
	// valid before we access it for the first time.
	// It's messier but at least we don't have a fully primed 
	// iterator to copy around straight after construction...

	CheckPrimed();

	CheckValid();

   return m_cache.GetCurrent();
}

template <class T, class I, class E> 
IEnumIterator<T,I,E>::operator E() const
{
   return Enumerated();
}

///////////////////////////////////////////////////////////////////////////////
// Helper function for cache management
///////////////////////////////////////////////////////////////////////////////

template <class T, class I, class E> 
void IEnumIterator<T,I,E>::SetCacheSize(unsigned long max)
{
	m_cache.ResizeCache(max);
}

///////////////////////////////////////////////////////////////////////////////
// Helper function for operator ++
///////////////////////////////////////////////////////////////////////////////

template <class T, class I, class E> 
void IEnumIterator<T,I,E>::Advance()
{
   if (m_pIEnum)
   {
		if (!m_cache.Next() && !m_bAtEnd)
		{
			// Grab some more elements and cache them...

			m_cache.EmptyCache();

			unsigned long cached = 0;

			HRESULT hr = m_pIEnum->Next(m_cache.GetSize(), m_cache.GetCache(), &cached);

			m_cache.FillCache(cached);

			if (S_FALSE == hr)
			{
				m_bAtEnd = true;
			}
			else if (S_OK != hr)
			{
				throw CComException(_T("IEnumIterator<T,I,E>::Advance()"), hr);
			}
		}
   }
}

template <class T, class I, class E> 
void IEnumIterator<T,I,E>::CheckValid() const
{
   if (!m_pIEnum || m_cache.IsEmpty())
   {
		// Can't dereference an "End" iterator.
      throw NullIterator();
   }
}

template <class T, class I, class E> 
void IEnumIterator<T,I,E>::CheckPrimed() const
{
	// Since we no longer call advance in the ctor we must 
	// make sure it's been called once to make the first item
	// valid before we advance away from the first item, or
	// access it for the first time. 

	// It's messier but at least we don't have a fully primed 
	// iterator to copy around straight after construction...

	if (m_bNotPrimed)
	{
		// Even though everything is mutable, we still can't call 
		// Advance() as it's a non-const member function. We could
		// declare it as const (which seems wrong, it's not) or
		// we can cheat like this... We'll cheat for now...

	   const_cast<IEnumIterator<T,I,E>*>(this)->Advance();
		
		m_bNotPrimed = false;
	}
}

///////////////////////////////////////////////////////////////////////////////
// Interface for TCache<T,E>
///////////////////////////////////////////////////////////////////////////////

template <class T, class I, class E> 
void IEnumIterator<T,I,E>::DestroyItem(E item)
{
	// Jump through hoops...

	// Access an object known to exist.
	// through a pointer to its base class (us)
	
	const IEnumIterator<T,I,E> *pB = &End();

	// As we can't call a private member function of another class
	// but we can call one of ours... (and it's virtual)

	pB->Destroy(item);
}

template <class T, class I, class E> 
E IEnumIterator<T,I,E>::CopyItem(E item)
{
	// Jump through hoops...

	// Access an object known to exist.
	// through a pointer to its base class (us)
	
	const IEnumIterator<T,I,E> *pB = &End();

	// As we can't call a private member function of another class
	// but we can call one of ours... (and it's virtual)

	return pB->Copy(item);
}


///////////////////////////////////////////////////////////////////////////////
// Namespace: JetByteTools
///////////////////////////////////////////////////////////////////////////////

} // End of namespace JetByteTools 

#endif // __IENUM_ITERATOR__

///////////////////////////////////////////////////////////////////////////////
// End of file
///////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -