- /***********************************************************************
- *
- * This module is part of the XMLGUI system
- *
- * File name: XMLIterator.h
- *
- * Creation date: [15 AUGUST 2002]
- *
- * Author(s): [Kolosenko Ruslan]
- *
- * Description: Declares the template class CXMLIteratable
- *
- **********************************************************************/
- #ifndef AFX_XML_ITERATOR_H_RKOL_8_15_2002_
- #define AFX_XML_ITERATOR_H_RKOL_8_15_2002_
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
- #include "XMLTags.h"
- template <class TagType> class CXMLIteratable
- {
- public:
- // constructor, accepts pointer to the enclosing tag element
- CXMLIteratable(IXMLElement* pEnclosingTag)
- {
- HRESULT hr;
- // set initial values for data members
- m_pCollection = NULL;
- m_pCurrent = NULL;
- m_nCurrIndex = 0;
- m_nChildrenCount = 0;
- // get reference to IXMLElement interface of the enclosing tag
- hr = pEnclosingTag->QueryInterface(IID_IXMLElement,(void**)&m_pEnclosing);
- WATCH_XML_EXCEPTION(hr);
- // get and store reference to the XMLElementCollection interface
- // and number of child nodes of the enclosing tag
- hr = m_pEnclosing->get_children(&m_pCollection);
- if ( SUCCEEDED(hr) && m_pCollection )
- {
- hr = m_pCollection->get_length(&m_nChildrenCount);
- WATCH_XML_EXCEPTION(hr)
- }
- }
- virtual ~CXMLIteratable()
- {
- // free all used COM interfaces
- if ( m_pCurrent ) m_pCurrent->Release();
- if ( m_pCollection ) m_pCollection->Release();
- if ( m_pEnclosing ) m_pEnclosing->Release();
- }
- // dereference operator, returns TagType object corresponding
- // to the current XMLElement
- TagType operator*()
- {
- if ( !m_pCurrent )
- {
- throw CXMLParsingException(_T("Dereferencing a non-positioned iterator"));
- }
- return TagType(m_pCurrent);
- }
- // start iterating, moves cursor to the beginning of the nodes collection
- void Begin()
- {
- // release previously used COM interface pointers if any
- if ( m_pCurrent ) m_pCurrent->Release();
- m_pCurrent = NULL;
- // try to find first child node that can be converted to TagType
- // start from the beginning of the collection
- m_nCurrIndex = 0;
- FindNext();
- }
- // determines whether the end of the iterating loop was reached
- BOOL AtEnd()
- {
- // if no next element was previously found - we finished iterating
- return m_pCurrent ? FALSE : TRUE;
- }
- // prefix increment
- // moves the cursor to the next child element of type TagType
- // returns the modified iterator object
- CXMLIteratable& operator++()
- {
- if ( AtEnd() )
- { // cannot move over the end of the list
- throw CXMLParsingException(_T("Moving iterator out of range"));
- }
- m_nCurrIndex++;
- FindNext(); // try to find the next acceptable element
- return *this; // return the object with the cursor moved
- }
- protected:
- // help function for retrieving next element while iterating
- void FindNext()
- {
- HRESULT hr;
- // release current element pointer
- if ( m_pCurrent ) m_pCurrent->Release();
- m_pCurrent = NULL;
- VARIANT var1; // variants for retrieving control's IXMLElement pointer
- VARIANT var2; // needed for the call to pChildren->item() only
- var1.vt = VT_UINT;
- var2.vt = VT_EMPTY;
- // and now try to find the next child node matching TagType
- while ( m_nCurrIndex < m_nChildrenCount )
- {
- var1.uintVal = m_nCurrIndex;
- hr = m_pCollection->item(var1,var2,(IDispatch**)&m_pCurrent);
- if ( SUCCEEDED(hr) && TagType::IsTypeValid(m_pCurrent) )
- {
- break; // next element of type TagType found
- }
- // element does not match or COM failure - release obtained pointer
- if ( m_pCurrent ) m_pCurrent->Release();
- m_pCurrent = NULL;
- if ( FAILED(hr) ) break; // break the loop in the case of COM failure
- m_nCurrIndex++; // and check the next element if just TagType mismatch
- }
- }
- // data members
- long m_nCurrIndex; // current position in the collection
- long m_nChildrenCount; // total number of child elements
- IXMLElementCollection* m_pCollection; // COM pointer to the collection
- IXMLElement* m_pEnclosing; // COM pointer to the enclosing element
- IXMLElement* m_pCurrent; // pointer to the current element (cursor)
- };
- // instantiations of CXMLIteratable for some commonly used tag types
- typedef CXMLIteratable<CXMLTag> CXMLIterator;
- typedef CXMLIteratable<CXMLDialogTag> CXMLDialogIterator;
- typedef CXMLIteratable<CXMLControlTag> CXMLControlIterator;
- #endif // AFX_XML_ITERATOR_H_RKOL_8_15_2002_