485 lines
11 KiB
C++
485 lines
11 KiB
C++
//
|
|
// Parser.cpp
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "Parser.h"
|
|
#include "SkipParser.h"
|
|
#include "resource.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CParserBase interface
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CParserBase::DispatchElement(
|
|
const XMLTAG *pEntry,
|
|
const wchar_t *wszNamespaceUri, int cchNamespaceUri,
|
|
const wchar_t *wszLocalName, int cchLocalName,
|
|
const wchar_t *wszQName, int cchQName,
|
|
ISAXAttributes *pAttributes) throw()
|
|
{
|
|
if (!pEntry)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
while (pEntry->szElemName)
|
|
{
|
|
if (CheckTagElement(pEntry,
|
|
wszNamespaceUri, cchNamespaceUri,
|
|
wszLocalName, cchLocalName,
|
|
wszQName, cchQName))
|
|
{
|
|
return (this->*pEntry->pfnTag)(wszNamespaceUri,
|
|
cchNamespaceUri, wszLocalName, cchLocalName,
|
|
wszQName, cchQName, pAttributes);
|
|
}
|
|
pEntry++;
|
|
}
|
|
|
|
//
|
|
// unrecognized tag
|
|
//
|
|
return OnUnrecognizedTag(wszNamespaceUri,
|
|
cchNamespaceUri, wszLocalName, cchLocalName,
|
|
wszQName, cchQName, pAttributes);
|
|
}
|
|
|
|
HRESULT CParserBase::GetAttributes(const XMLATTR *pEntry, ISAXAttributes *pAttributes)
|
|
{
|
|
if (!pAttributes)
|
|
{
|
|
EmitError(IDS_SDL_INTERNAL);
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (GetGotAttributes() != FALSE)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
if (!pEntry)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
int nAttrs = 0;
|
|
HRESULT hr = pAttributes->getLength(&nAttrs);
|
|
if (FAILED(hr))
|
|
{
|
|
EmitError(IDS_SDL_MSXML);
|
|
return E_FAIL;
|
|
}
|
|
|
|
while (pEntry->wszElemName)
|
|
{
|
|
int i;
|
|
for (i=0; i<nAttrs; i++)
|
|
{
|
|
const wchar_t *wszNamespaceUri = NULL;
|
|
const wchar_t *wszLocalName = NULL;
|
|
const wchar_t *wszQName = NULL;
|
|
int cchUri = 0;
|
|
int cchLocalName = 0;
|
|
int cchQName = 0;
|
|
|
|
hr = pAttributes->getName(i, &wszNamespaceUri, &cchUri, &wszLocalName, &cchLocalName, &wszQName, &cchQName);
|
|
if (FAILED(hr))
|
|
{
|
|
EmitError(IDS_SDL_MSXML);
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (CheckTagElement(pEntry,
|
|
wszNamespaceUri, cchUri,
|
|
wszLocalName, cchLocalName,
|
|
wszQName, cchQName))
|
|
{
|
|
const wchar_t *wszValue = NULL;
|
|
int cchValue = 0;
|
|
|
|
hr = pAttributes->getValue(i, &wszValue, &cchValue);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = (this->*pEntry->pfnAttr)(wszNamespaceUri,
|
|
cchUri, wszLocalName, cchLocalName,
|
|
wszQName, cchQName, wszValue, cchValue,
|
|
pAttributes);
|
|
}
|
|
else
|
|
{
|
|
EmitError(IDS_SDL_MSXML);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= nAttrs)
|
|
{
|
|
hr = OnMissingAttribute(pEntry->bRequired, pEntry->wszElemName, pEntry->cchElem,
|
|
pEntry->wszElemNamespace, pEntry->cchNamespaceUri);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pEntry++;
|
|
}
|
|
|
|
SetGotAttributes(TRUE);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CParserBase::DispatchElement(
|
|
const wchar_t *wszNamespaceUri, int cchNamespaceUri,
|
|
const wchar_t *wszLocalName, int cchLocalName,
|
|
const wchar_t *wszQName, int cchQName,
|
|
ISAXAttributes *pAttributes) throw()
|
|
{
|
|
|
|
if (FAILED(GetAttributes(pAttributes)))
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
const XMLTAG * pEntry = GetXMLTAGMap();
|
|
|
|
return DispatchElement(pEntry, wszNamespaceUri,
|
|
cchNamespaceUri, wszLocalName, cchLocalName,
|
|
wszQName, cchQName, pAttributes);
|
|
}
|
|
|
|
HRESULT CParserBase::GetAttributes(ISAXAttributes *pAttributes)
|
|
{
|
|
const XMLATTR * pEntry = GetXMLATTRMap();
|
|
return GetAttributes(pEntry, pAttributes);
|
|
}
|
|
|
|
BOOL CParserBase::CheckTagElement(
|
|
const XMLTAG *pTag,
|
|
const wchar_t *wszNamespaceUri, int cchNamespaceUri,
|
|
const wchar_t *wszLocalName, int cchLocalName,
|
|
const wchar_t *wszQName, int cchQName)
|
|
{
|
|
if (!pTag->wszElemName)
|
|
{
|
|
EmitError(IDS_SDL_INTERNAL);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pTag->cchElem == cchLocalName &&
|
|
!wcsncmp(pTag->wszElemName, wszLocalName, pTag->cchElem))
|
|
{
|
|
//
|
|
// Don't need to check default namespace for tags since SAX gives it in wszElemNamespace
|
|
//
|
|
if ((!pTag->wszElemNamespace) ||
|
|
(!pTag->cchNamespaceUri && !cchNamespaceUri) ||
|
|
(pTag->cchNamespaceUri == cchNamespaceUri &&
|
|
!wcsncmp(pTag->wszElemNamespace, wszNamespaceUri, pTag->cchNamespaceUri)))
|
|
{
|
|
//
|
|
// namespace and tag match
|
|
// it is okay if there is no namespace ("") or if the user doesn't care (NULL)
|
|
//
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CParserBase::CrackQName(const wchar_t *wszQName, int cchQName,
|
|
wchar_t **pwszNs, int *pcchNs,
|
|
wchar_t **pwszName, int *pcchName)
|
|
{
|
|
wchar_t * wszQNameTmp = (wchar_t *) wszQName;
|
|
wchar_t * wszColon = wcschr(wszQNameTmp, L':');
|
|
if (wszColon && (wszColon-wszQNameTmp) <= cchQName)
|
|
{
|
|
*pwszNs = wszQNameTmp;
|
|
*pcchNs = (int)(wszColon-wszQNameTmp);
|
|
|
|
*pwszName = wszColon+1;
|
|
*pcchName = cchQName-(*pcchNs)-1;
|
|
}
|
|
else
|
|
{
|
|
*pwszNs = NULL;
|
|
*pcchNs = 0;
|
|
*pwszName = wszQNameTmp;
|
|
*pcchName = cchQName;
|
|
}
|
|
}
|
|
|
|
HRESULT CParserBase::OnUnrecognizedTag(
|
|
const wchar_t *wszNamespaceUri, int cchNamespaceUri,
|
|
const wchar_t *wszLocalName, int cchLocalName,
|
|
const wchar_t *wszQName, int cchQName,
|
|
ISAXAttributes *pAttributes) throw()
|
|
{
|
|
wszNamespaceUri;
|
|
cchNamespaceUri;
|
|
wszLocalName;
|
|
cchLocalName;
|
|
wszQName;
|
|
cchQName;
|
|
pAttributes;
|
|
|
|
ATLTRACE( _T("%sUnrecoginzed Tag: %.*ws\n"), GetTabs(m_dwLevel), cchQName, wszQName );
|
|
|
|
int nLine;
|
|
int nCol;
|
|
|
|
GetLocator()->getLineNumber(&nLine);
|
|
GetLocator()->getColumnNumber(&nCol);
|
|
|
|
EmitFileError(IDS_SDL_UNRECOGNIZED_TAG, GetWSDLFile(), nLine, nCol, 0, wszNamespaceUri, wszLocalName);
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT CParserBase::OnMissingAttribute(BOOL bRequired,
|
|
const wchar_t *wszName, int cchName,
|
|
const wchar_t *wszNamespace, int cchNamespace)
|
|
{
|
|
if (bRequired != FALSE)
|
|
{
|
|
ATLTRACE( _T("%sMissing Required Attribute: name %.*ws, uri %.*ws\n"),
|
|
GetTabs(m_dwLevel), cchName, wszName, cchNamespace, wszNamespace );
|
|
|
|
int nLine;
|
|
int nCol;
|
|
|
|
GetLocator()->getLineNumber(&nLine);
|
|
GetLocator()->getColumnNumber(&nCol);
|
|
|
|
EmitFileError(IDS_SDL_MISSING_ATTRIBUTE, GetWSDLFile(), nLine, nCol, 0, wszNamespace, wszName);
|
|
return E_FAIL;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
void CParserBase::EmitInvalidValue(const char *szName, const wchar_t *wszValue)
|
|
{
|
|
int nLine;
|
|
int nCol;
|
|
GetLocator()->getLineNumber(&nLine);
|
|
GetLocator()->getColumnNumber(&nCol);
|
|
EmitFileError(IDS_SDL_INVALID_VALUE, GetWSDLFile(), nLine, nCol, 0, szName, wszValue);
|
|
}
|
|
|
|
void CParserBase::EmitUnsupported(UINT nID, const wchar_t *wszUri, const wchar_t *wszName)
|
|
{
|
|
int nLine;
|
|
int nCol;
|
|
GetLocator()->getLineNumber(&nLine);
|
|
GetLocator()->getColumnNumber(&nCol);
|
|
EmitFileWarning(nID, GetWSDLFile(), nLine, nCol, 0, wszUri, wszName);
|
|
}
|
|
|
|
void CParserBase::EmitSkip(const wchar_t *wszUri, const wchar_t *wszName)
|
|
{
|
|
EmitUnsupported(IDS_SDL_UNSUPPORTED_TAG, wszUri, wszName);
|
|
}
|
|
|
|
void CParserBase::EmitString(const wchar_t *wszUri, const wchar_t *wszName)
|
|
{
|
|
EmitUnsupported(IDS_SDL_UNSUPPORTED_STRING, wszUri, wszName);
|
|
}
|
|
|
|
HRESULT CParserBase::SkipElement()
|
|
{
|
|
CAutoPtr<CSkipParser> p( new CSkipParser(m_spReader, this, GetLevel()) );
|
|
if (p != NULL)
|
|
{
|
|
if (g_ParserList.AddHead(p) != NULL)
|
|
{
|
|
p.Detach();
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
EmitErrorHr(E_OUTOFMEMORY);
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IUnknown
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT __stdcall CParserBase::QueryInterface(REFIID riid, void **ppv)
|
|
{
|
|
if (!ppv)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (InlineIsEqualGUID(riid, __uuidof(ISAXContentHandler)) ||
|
|
InlineIsEqualGUID(riid, __uuidof(IUnknown)))
|
|
{
|
|
*ppv = static_cast<IUnknown*>(this);
|
|
return S_OK;
|
|
}
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
ULONG __stdcall CParserBase::AddRef()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
ULONG __stdcall CParserBase::Release()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ISAXContentHandler
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT __stdcall CParserBase::putDocumentLocator(ISAXLocator *pLocator)
|
|
{
|
|
m_spLocator = pLocator;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT __stdcall CParserBase::startDocument()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT __stdcall CParserBase::endDocument()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT __stdcall CParserBase::startPrefixMapping(
|
|
const wchar_t *wszPrefix,
|
|
int cchPrefix,
|
|
const wchar_t *wszUri,
|
|
int cchUri)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT __stdcall CParserBase::endPrefixMapping(
|
|
const wchar_t *wszPrefix,
|
|
int cchPrefix)
|
|
{
|
|
wszPrefix;
|
|
cchPrefix;
|
|
|
|
// REVIEW: remove from map?
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT __stdcall CParserBase::startElement(
|
|
const wchar_t *wszNamespaceUri,
|
|
int cchNamespaceUri,
|
|
const wchar_t *wszLocalName,
|
|
int cchLocalName,
|
|
const wchar_t *wszQName,
|
|
int cchQName,
|
|
ISAXAttributes *pAttributes)
|
|
{
|
|
return DispatchElement(wszNamespaceUri, cchNamespaceUri,
|
|
wszLocalName, cchLocalName,
|
|
wszQName, cchQName,
|
|
pAttributes);
|
|
}
|
|
|
|
HRESULT __stdcall CParserBase::endElement(
|
|
const wchar_t *wszNamespaceUri,
|
|
int cchNamespaceUri,
|
|
const wchar_t *wszLocalName,
|
|
int cchLocalName,
|
|
const wchar_t *wszQName,
|
|
int cchQName)
|
|
{
|
|
HRESULT hr = ValidateElement();
|
|
|
|
if (GetReset() > 0)
|
|
{
|
|
EnableReset();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Restore the parent handler
|
|
//
|
|
CComPtr<CParserBase> spParentHandler = GetParentHandler();
|
|
if (spParentHandler.p != NULL)
|
|
{
|
|
m_spReader->putContentHandler(spParentHandler);
|
|
}
|
|
|
|
if (GetDynamicAlloc() != FALSE)
|
|
{
|
|
POSITION pos = g_ParserList.Find(this);
|
|
if (pos != NULL)
|
|
{
|
|
g_ParserList.RemoveAt(pos);
|
|
}
|
|
delete this;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT __stdcall CParserBase::characters(
|
|
const wchar_t *wszChars,
|
|
int cchChars)
|
|
{
|
|
//
|
|
// REVIEW: what to do here?
|
|
//
|
|
// ATLTRACE( _T("CParserBase::characters: %*.ws\n"), cchChars, wszChars );
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT __stdcall CParserBase::ignorableWhitespace(
|
|
const wchar_t *wszChars,
|
|
int cchChars)
|
|
{
|
|
// ATLTRACE( _T("CParserBase::ignorableWhitespace: %.*ws\n"), cchChars, wszChars );
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT __stdcall CParserBase::processingInstruction(
|
|
const wchar_t *wszTarget,
|
|
int cchTarget,
|
|
const wchar_t *wszData,
|
|
int cchData)
|
|
{
|
|
wszTarget;
|
|
cchTarget;
|
|
wszData;
|
|
cchData;
|
|
|
|
ATLTRACE( _T("CParserBase::processingInstruction: target: %.*ws, data: %.*ws\n"), cchTarget, wszTarget, cchData, wszData );
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT __stdcall CParserBase::skippedEntity(
|
|
const wchar_t *wszName,
|
|
int cchName)
|
|
{
|
|
wszName;
|
|
cchName;
|
|
|
|
ATLTRACE( _T("CParserBase::skippedEntity: %.*ws\n"), wszName, cchName );
|
|
return S_OK;
|
|
} |