// // Parser.h // // Copyright (c) Microsoft Corporation. All rights reserved. // #pragma once #include "stdafx.h" #include "XMLDocument.h" #include "XSDElement.h" #include "Emit.h" #include "SproxyColl.h" #define PTM_WARNING_DISABLE \ __pragma(warning( push )) \ __pragma(warning( disable : 4867 )) #define PTM_WARNING_RESTORE \ __pragma(warning( pop )) #define EMPTY_XMLTAG_MAP() \ virtual const XMLTAG * GetXMLTAGMap() \ { \ return NULL; \ } #define EMPTY_XMLATTR_MAP() \ virtual const XMLATTR * GetXMLATTRMap() \ { \ return NULL; \ } #define BEGIN_XMLTAG_MAP() \ virtual const XMLTAG * GetXMLTAGMap() \ { \ PTM_WARNING_DISABLE \ static const XMLTAG map[] = \ { #define END_XMLTAG_MAP() \ { NULL, NULL } }; \ PTM_WARNING_RESTORE \ return map; \ } #define _XMLTAG_ENTRY_EX(elementName, elementNamespace, elementFunc) \ { L ## elementName, elementName, sizeof(elementName)-1, \ L ## elementNamespace, elementNamespace, sizeof(elementNamespace)-1, \ static_cast(elementFunc), NULL, FALSE }, #define XMLTAG_ENTRY_EX(elementName, elementNamespace, elementFunc) _XMLTAG_ENTRY_EX(elementName, elementNamespace, elementFunc) #define _XMLTAG_ENTRY(elementName, elementFunc) \ { L ## elementName, elementName, sizeof(elementName)-1, \ NULL, NULL, 0, \ static_cast(elementFunc), NULL, FALSE }, #define XMLTAG_ENTRY(elementName, elementFunc) _XMLTAG_ENTRY(elementName, elementFunc) #define BEGIN_XMLATTR_MAP() \ virtual const XMLATTR * GetXMLATTRMap() \ { \ PTM_WARNING_DISABLE \ static const XMLTAG map[] = \ { #define END_XMLATTR_MAP() \ { NULL, NULL } }; \ PTM_WARNING_RESTORE \ return map; \ } #define _XMLATTR_ENTRY_EX(elementName, elementNamespace, elementFunc, required) \ { L ## elementName, elementName, sizeof(elementName)-1, \ L ## elementNamespace, elementNamespace, sizeof(elementNamespace)-1, \ NULL, static_cast(elementFunc), required }, #define XMLATTR_ENTRY_EX(elementName, elementNamespace, elementFunc) \ _XMLATTR_ENTRY_EX(elementName, elementNamespace, elementFunc, FALSE) #define XMLATTR_ENTRY_EX2(elementName, elementNamespace, elementFunc, required) \ _XMLATTR_ENTRY_EX(elementName, elementNamespace, elementFunc, required) #define _XMLATTR_ENTRY(elementName, elementFunc, required) \ { L ## elementName, elementName, sizeof(elementName)-1, \ NULL, NULL, 0, \ NULL, static_cast(elementFunc), required }, #define XMLATTR_ENTRY(elementName, elementFunc) _XMLATTR_ENTRY(elementName, elementFunc, FALSE) #define XMLATTR_ENTRY2(elementName, elementFunc, required) _XMLATTR_ENTRY(elementName, elementFunc, required) class CParserBase; typedef HRESULT (CParserBase::*TAG_DISPATCH_FUNC)( const wchar_t *wszNamespaceUri, int cchNamespaceUri, const wchar_t *wszLocalName, int cchLocalName, const wchar_t *wszQName, int cchQName, ISAXAttributes *pAttributes); typedef HRESULT (CParserBase::*ATTR_DISPATCH_FUNC)( const wchar_t *wszNamespaceUri, int cchNamespaceUri, const wchar_t *wszLocalName, int cchLocalName, const wchar_t *wszQName, int cchQName, const wchar_t *wszValue, int cchValue, ISAXAttributes *pAttributes); #define TAG_METHOD_DECL( name ) \ HRESULT name(const wchar_t *wszNamespaceUri, int cchNamespaceUri, \ const wchar_t *wszLocalName, int cchLocalName, \ const wchar_t *wszQName, int cchQName, \ ISAXAttributes *pAttributes) #define TAG_METHOD_IMPL( class, name ) \ HRESULT class ## :: ## name(const wchar_t *wszNamespaceUri, int cchNamespaceUri, \ const wchar_t *wszLocalName, int cchLocalName, \ const wchar_t *wszQName, int cchQName, \ ISAXAttributes *pAttributes) #define ATTR_METHOD_DECL( name ) \ HRESULT name(const wchar_t *wszNamespaceUri, int cchNamespaceUri, \ const wchar_t *wszLocalName, int cchLocalName, \ const wchar_t *wszQName, int cchQName, \ const wchar_t *wszValue, int cchValue, \ ISAXAttributes *pAttributes) #define ATTR_METHOD_IMPL( class, name ) \ HRESULT class ## :: ## name(const wchar_t *wszNamespaceUri, int cchNamespaceUri, \ const wchar_t *wszLocalName, int cchLocalName, \ const wchar_t *wszQName, int cchQName, \ const wchar_t *wszValue, int cchValue, \ ISAXAttributes *pAttributes) typedef NAMESPACEMAP URIMAP; #ifndef _PREFIX_ #define TRACE_PARSE_ENTRY() \ ATLTRACE( _T("%s") __FUNCTION__ _T("\n"), GetTabs(GetLevel())) #else #define TRACE_PARSE_ENTRY() \ ATLTRACE( _T("%s") _T("\n"), GetTabs(GetLevel())) #endif // _PREFIX_ // // XMLTAG struct // used for dispatching XML entries // struct XMLTAG { LPCWSTR wszElemName; LPCSTR szElemName; int cchElem; LPCWSTR wszElemNamespace; LPCSTR szElemNamespace; int cchNamespaceUri; // // REVIEW: union doesn't work for initialization // TAG_DISPATCH_FUNC pfnTag; ATTR_DISPATCH_FUNC pfnAttr; // // attribute must be present // BOOL bRequired; }; typedef XMLTAG XMLATTR; // // dummy classes for multiple inheritance // (tell compiler to use big pointers for CParserBase member function pointers) // class CDummy1 {}; class CDummy2 {}; // // The base parser class // class CParserBase : public ISAXContentHandler, public CDummy1, public CDummy2 { private: CComPtr m_spParent; CComPtr m_spReader; CComPtr m_spLocator; // // how many levels deep // DWORD m_dwLevel; // // reset to parent handler on endElement // DWORD m_dwReset; // // get only top-level attributes // BOOL m_bGotAttributes; // // dynamically allocated // BOOL m_bDynamicAlloc; private: HRESULT DispatchElement( const XMLTAG *pMap, const wchar_t *wszNamespaceUri, int cchNamespaceUri, const wchar_t *wszLocalName, int cchLocalName, const wchar_t *wszQName, int cchQName, ISAXAttributes *pAttributes) throw (); HRESULT GetAttributes(const XMLATTR *pMap, ISAXAttributes *pAttributes); BOOL CheckTagElement( const XMLTAG *pTag, const wchar_t *wszNamespaceUri, int cchNamespaceUri, const wchar_t *wszLocalName, int cchLocalName, const wchar_t *wszQName, int cchQName); void CrackQName(const wchar_t *wszQName, int cchQName, wchar_t **pwszNs, int *pcchNs, wchar_t **pwszName, int *pcchName); public: // // CParserBase interface // inline CParserBase() :m_dwLevel(0), m_dwReset(0), m_bDynamicAlloc(TRUE), m_bGotAttributes(FALSE) { } inline CParserBase(ISAXXMLReader *pReader, CParserBase *pParent, DWORD dwLevel) :m_spReader(pReader), m_spParent(pParent), m_dwLevel(dwLevel+1), m_dwReset(0), m_bDynamicAlloc(TRUE), m_bGotAttributes(FALSE) { if (m_spReader.p != NULL) { m_spReader->putContentHandler(this); } } inline HRESULT Initialize(ISAXXMLReader *pReader, CParserBase *pParent, DWORD dwLevel, BOOL bDynamicAlloc = FALSE) { m_spReader = pReader; m_spParent = pParent; m_dwLevel = dwLevel+1; m_bDynamicAlloc = bDynamicAlloc; m_bGotAttributes = FALSE; m_dwReset = 0; if (m_spReader.p != NULL) { return m_spReader->putContentHandler(this); } return E_FAIL; } virtual ~CParserBase() { if ((m_spParent.p != NULL) && (m_spReader.p != NULL)) { m_spReader->putContentHandler(m_spParent); } } EMPTY_XMLTAG_MAP() EMPTY_XMLATTR_MAP() HRESULT DispatchElement( const wchar_t *wszNamespaceUri, int cchNamespaceUri, const wchar_t *wszLocalName, int cchLocalName, const wchar_t *wszQName, int cchQName, ISAXAttributes *pAttributes) throw (); HRESULT GetAttributes(ISAXAttributes *pAttributes); inline CParserBase * GetParentHandler() { return m_spParent; } inline void SetParentHandler(CParserBase *pParent) { m_spParent = pParent; } ISAXXMLReader * GetReader() { return m_spReader; } inline void SetReader(ISAXXMLReader *pReader) { m_spReader = pReader; } inline DWORD GetLevel() { return m_dwLevel; } inline void SetLevel(DWORD dwLevel) { m_dwLevel = dwLevel; } virtual HRESULT OnUnrecognizedTag( const wchar_t *wszNamespaceUri, int cchNamespaceUri, const wchar_t *wszLocalName, int cchLocalName, const wchar_t *wszQName, int cchQName, ISAXAttributes *pAttributes) throw (); virtual HRESULT OnMissingAttribute(BOOL bRequired, const wchar_t *wszName, int cchName, const wchar_t *wszNamespace, int cchNamespace); HRESULT SkipElement(); void EmitInvalidValue(const char *szName, const wchar_t *wszValue); void EmitUnsupported(UINT nID, const wchar_t *wszUri, const wchar_t *wszName); void EmitSkip(const wchar_t *wszUri, const wchar_t *wszName); void EmitString(const wchar_t *wszUri, const wchar_t *wszName); inline ISAXLocator * GetLocator() { if (m_spLocator.p != NULL) { return m_spLocator; } if (m_spParent.p != NULL) { return m_spParent->GetLocator(); } return NULL; } virtual HRESULT ValidateElement() { return S_OK; } inline void SetGotAttributes(BOOL bGotAttributes) { m_bGotAttributes = bGotAttributes; } inline BOOL GetGotAttributes() { return m_bGotAttributes; } inline DWORD GetReset() { return m_dwReset; } inline void EnableReset(BOOL bForce = FALSE) { if (bForce != FALSE) { m_dwReset = 0; } else if (m_dwReset > 0) { m_dwReset--; } } inline void DisableReset(DWORD dwCnt = 1) { m_dwReset+= dwCnt; } inline BOOL GetDynamicAlloc() { return m_bDynamicAlloc; } inline void SetDynamicAlloc(BOOL bDynamicAlloc) { m_bDynamicAlloc = bDynamicAlloc; } // // IUnknown interface // HRESULT __stdcall QueryInterface(REFIID riid, void **ppv); ULONG __stdcall AddRef(); ULONG __stdcall Release(); // // ISAXContentHandler interface // HRESULT __stdcall putDocumentLocator(ISAXLocator *pLocator); HRESULT __stdcall startDocument(); HRESULT __stdcall endDocument(); HRESULT __stdcall startPrefixMapping( const wchar_t *wszPrefix, int cchPrefix, const wchar_t *wszUri, int cchUri); HRESULT __stdcall endPrefixMapping( const wchar_t *wszPrefix, int cchPrefix); HRESULT __stdcall startElement( const wchar_t *wszNamespaceUri, int cchNamespaceUri, const wchar_t *wszLocalName, int cchLocalName, const wchar_t *wszQName, int cchQName, ISAXAttributes *pAttributes); HRESULT __stdcall endElement( const wchar_t *wszNamespaceUri, int cchNamespaceUri, const wchar_t *wszLocalName, int cchLocalName, const wchar_t *wszQName, int cchQName); HRESULT __stdcall characters( const wchar_t *wszChars, int cchChars); HRESULT __stdcall ignorableWhitespace( const wchar_t *wszChars, int cchChars); HRESULT __stdcall processingInstruction( const wchar_t *wszTarget, int cchTarget, const wchar_t *wszData, int cchData); HRESULT __stdcall skippedEntity( const wchar_t *wszName, int cchName); }; inline HRESULT CopyNamespaceMap(const NAMESPACEMAP& in, NAMESPACEMAP& out) { out.InitHashTable(in.GetHashTableSize()); out.DisableAutoRehash(); POSITION pos = in.GetStartPosition(); while (pos != NULL) { const NAMESPACEMAP::CPair *p = in.GetNext(pos); if (!out.SetAt(p->m_key, p->m_value)) { return E_FAIL; } } out.EnableAutoRehash(); return S_OK; } // for cleanup purposes #ifndef _PREFIX_ __declspec(selectany) CAtlPtrList g_ParserList; #else CAtlPtrList g_ParserList; #endif // _PREFIX_ inline void SetLocatorInfo(CXMLElement *pElem, ISAXLocator *pLocator) { ATLASSERT( pLocator != NULL ); ATLASSERT( pElem != NULL ); int nLine = 0; int nCol = 0; pLocator->getLineNumber(&nLine); pLocator->getColumnNumber(&nCol); pElem->SetLineNumber(nLine); pElem->SetColumnNumber(nCol); } ATL_NOINLINE inline void SetXMLElementInfo(CXMLElement *pElem, CXMLElement *pParent, ISAXLocator *pLocator) { ATLASSERT( pElem != NULL ); ATLASSERT( pParent != NULL ); ATLASSERT( pLocator != NULL ); pElem->SetParentElement(pParent); pElem->SetParentDocument(pParent->GetParentDocument()); SetLocatorInfo(pElem, pLocator); } ATL_NOINLINE inline void SetXSDElementInfo(CXSDElement *pElem, CXSDElement *pParent, ISAXLocator *pLocator) { ATLASSERT( pElem != NULL ); ATLASSERT( pParent != NULL ); ATLASSERT( pLocator != NULL ); pElem->SetParentSchema(pParent->GetParentSchema()); pElem->SetParentElement(pParent); pElem->SetParentDocument(pParent->GetParentDocument()); SetLocatorInfo(pElem, pLocator); }