//IPersistVarXMLImpl.h
/////////////////////////////////////////////////////
//
// This is a part of the ATL PersistXML add-on
//
// Copyright (c) VitalyKatasonov. All rights reserved.
//
// free to use everywhere!
//
// any comments send to: vkatasonov@yahoo.com
//
/////////////////////////////////////////////////////
#ifndef __IPersistVarXMLImp_h_
#define __IPersistVarXMLImp_h_
#include "IPersistVarXML.h"
#include "atlsax.h"
#define _FACPersistVarXMLERR 0x301
#define MAKE_PERSISTVARXMLERRHRESULT( code ) MAKE_HRESULT( SEVERITY_ERROR, _FACPersistVarXMLERR, code )
#define ERR_CoCreateInstance_SAXAttributes MAKE_PERSISTVARXMLERRHRESULT( 1 )
#define ERR_CoCreateInstance_SAXXMLReader MAKE_PERSISTVARXMLERRHRESULT( 2 )
#define ERR_CoCreateInstance_MXXMLWriter MAKE_PERSISTVARXMLERRHRESULT( 3 )
#define DECLARE_XML_ELEMENT_NAME(strName) \
STDMETHOD(get_ElementName)(BSTR* pElementName) \
{ \
*pElementName = ::SysAllocString(OLESTR(#strName)); \
return S_OK;\
}
struct IPersistVarXML_CONTENT_ENTRY
{
const wchar_t* wszDesc;
DWORD dwOffsetData;
DWORD dwSizeData;
VARTYPE vt;
};
#define BEGIN_XML_CONTENT_MAP(theClass) \
public: \
HRESULT SaveLoadContent(ISAXContentHandler* pISAXContentHandler,ISAXAttributes * pAttributes, BSTR bstrElementName) \
{\
HRESULT hRes=S_OK;\
CComPtr<IPersistVarXML> pPersistVarXML;\
CComBSTR bstrEntryName;
#define XML_CONTENT_LOAD_HANDLER(szName,func)\
if(!pISAXContentHandler)\
if(!wcscmp(OLESTR(szName), bstrElementName))\
hRes = func(pAttributes);
#define XML_CONTENT_CREATE_OBJECT(szName,pclsid,pmember) \
if(!pISAXContentHandler)\
if(!wcscmp(OLESTR(szName), bstrElementName))\
if(SUCCEEDED(pPersistVarXML.CoCreateInstance(pclsid)))\
{\
if(SUCCEEDED(hRes = pPersistVarXML->LoadXML(CComVariant(m_pCurrentXMLReader),pAttributes)))\
hRes = pmember(pPersistVarXML);\
pPersistVarXML.Release();\
}else\
ATLASSERT(0);\
#define XML_CONTENT_ENTRY(pmember) \
if(!pPersistVarXML)\
if(SUCCEEDED(hRes=(pmember)->QueryInterface(__uuidof(IPersistVarXML), (void**)&pPersistVarXML)))\
{\
if(pISAXContentHandler)\
{\
hRes=pPersistVarXML->SaveXML(CComVariant(pISAXContentHandler));\
pPersistVarXML.Release();\
}else\
{\
pPersistVarXML->get_ElementName(&bstrEntryName);\
if(wcscmp(bstrEntryName, bstrElementName))\
pPersistVarXML.Release();\
bstrEntryName.Empty();\
}\
}
#define XML_CONTENT_SAVE_ENTRY(pmember) \
if(pISAXContentHandler)\
if(SUCCEEDED(hRes=(pmember)->QueryInterface(__uuidof(IPersistVarXML), (void**)&pPersistVarXML)))\
{\
if(pISAXContentHandler)\
hRes=pPersistVarXML->SaveXML(CComVariant(pISAXContentHandler));\
pPersistVarXML.Release();\
}
#define END_XML_CONTENT_MAP() \
if(pPersistVarXML && !pISAXContentHandler)\
{\
hRes = pPersistVarXML->LoadXML(CComVariant(m_pCurrentXMLReader),pAttributes);\
pPersistVarXML.Release();\
}\
return hRes;\
}
HRESULT AtlIPersistVarXML_Load(ISAXAttributes * pAttributes, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk);
HRESULT AtlIPersistVarXML_Save(IMXAttributes* pIMXAttributes, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk);
// IPersistFile Help functions! :)
HRESULT ATLIPersistFile_Load(LPCOLESTR pszFileName, IUnknown* pUnk);
HRESULT ATLIPersistFile_Save( LPCOLESTR pszFileName, IUnknown* pUnk);
template <class T>
class ATL_NO_VTABLE IPersistVarXMLImpl : public IPersistVarXML,
public ISAXContentHandlerImpl<T>
{
public:
HRESULT IPersistVarXML_SaveContent(ISAXContentHandler* pISAXContentHandler) \
{
T* pT = static_cast<T*>(this);
return pT->SaveLoadContent(pISAXContentHandler,NULL,NULL);
}
HRESULT IPersistVarXML_LoadContent(BSTR bstrIlementName, ISAXAttributes * pAttributes)
{
T* pT = static_cast<T*>(this);
return pT->SaveLoadContent(NULL,pAttributes,bstrIlementName);
}
HRESULT SaveLoadContent(ISAXContentHandler* pISAXContentHandler,ISAXAttributes * pAttributes, BSTR bstrElementName)
{
//Default Implimentation
return S_OK;
}
HRESULT IPersistVarXML_Load(ISAXAttributes * pAttributes)
{
T* pT = static_cast<T*>(this);
ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap();
ATLASSERT(pMap != NULL);
HRESULT hr = AtlIPersistVarXML_Load(pAttributes, pMap, pT, pT->GetUnknown());
if (SUCCEEDED(hr))
pT->m_bRequiresSave = FALSE;
return hr;
}
HRESULT IPersistVarXML_Save(IMXAttributes* pIMXAttributes)
{
T* pT = static_cast<T*>(this);
ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap();
ATLASSERT(pMap != NULL);
return AtlIPersistVarXML_Save(pIMXAttributes, pMap, pT, pT->GetUnknown());
}
//Default Implementations:
HRESULT StartElement (ISAXAttributes * pAttributes, BSTR ElementName)
{
T* pT = static_cast<T*>(this);
HRESULT hRes = S_OK;
USES_CONVERSION;
if(::SysStringLen(ElementName)==0 )
{
//Load THIS Object!!
return pT->IPersistVarXML_Load(pAttributes);
}else
return pT->IPersistVarXML_LoadContent(ElementName, pAttributes);
return hRes;
}
HRESULT SaveElement (ISAXContentHandler* pISAXContentHandler)
{
USES_CONVERSION;
T* pT = static_cast<T*>(this);
HRESULT hRes = E_FAIL;
CComBSTR bstrThisItemName;
hRes = pT->get_ElementName(&bstrThisItemName);
unsigned short Lenght;
ATLASSERT(bstrThisItemName.Length());
if(Lenght = bstrThisItemName.Length())
{
CComPtr<IMXAttributes> pIMXAttributes;
if(SUCCEEDED(hRes = pIMXAttributes.CoCreateInstance(__uuidof(SAXAttributes ))))
{
CComQIPtr<ISAXAttributes> pISAXAttributes(pIMXAttributes);
if(pISAXAttributes)
{
if(SUCCEEDED(hRes = pT->IPersistVarXML_Save(pIMXAttributes)))
{
pISAXContentHandler->startElement(L"",0,OLE2W(bstrThisItemName),Lenght,OLE2W(bstrThisItemName),Lenght,pISAXAttributes);
}
}
if(SUCCEEDED(hRes))
{
hRes = pT->IPersistVarXML_SaveContent(pISAXContentHandler);
pISAXContentHandler->endElement(L"",0,OLE2W(bstrThisItemName),Lenght,OLE2W(bstrThisItemName),Lenght);
}
}else
hRes = ERR_CoCreateInstance_SAXAttributes;
}
return hRes;
}
// for IPersistVarXML
CComPtr<ISAXContentHandler> m_pPrevContentHandler;
CComQIPtr<ISAXXMLReader> m_pCurrentXMLReader;
BOOL m_nStarted;
// ISAXContentHandler
STDMETHOD(startElement) (
unsigned short * pwchNamespaceUri,
int cchNamespaceUri,
unsigned short * pwchLocalName,
int cchLocalName,
unsigned short * pwchQName,
int cchQName,
struct ISAXAttributes * pAttributes )
{
T* pT = static_cast<T*>(this);
USES_CONVERSION;
CComBSTR bstrName(cchQName,pwchQName);
if(m_nStarted==0)
{
CComBSTR bstrThisItemName;
pT->get_ElementName(&bstrThisItemName);
if(bstrThisItemName==bstrName)
{
m_nStarted++;
return pT->StartElement (pAttributes, CComBSTR(""));
}
}
return pT->StartElement (pAttributes,bstrName);
}
STDMETHOD(endElement)(
unsigned short * pwchNamespaceUri,
int cchNamespaceUri,
unsigned short * pwchLocalName,
int cchLocalName,
unsigned short * pwchQName,
int cchQName )
{
T* pT = static_cast<T*>(this);
if(m_pPrevContentHandler)
{
USES_CONVERSION;
CComBSTR bstrName(cchQName,pwchQName);
CComBSTR bstrThisItemName;
pT->get_ElementName(&bstrThisItemName);
if(bstrThisItemName == bstrName)
{
ATLASSERT(m_nStarted>0);
m_nStarted--;
if(m_nStarted==0)
{
ATLASSERT(m_pPrevContentHandler);
m_pCurrentXMLReader->putContentHandler(m_pPrevContentHandler);
m_pPrevContentHandler.Release();
m_pCurrentXMLReader.Release();
}
}
}
return S_OK;
}
STDMETHOD(LoadXML)(
/* [in] */ VARIANT varSource, IUnknown * pAttributes = 0L)
{
T* pT = static_cast<T*>(this);
HRESULT hRes;
if(V_VT(&varSource)==VT_UNKNOWN)
{
m_pCurrentXMLReader = V_UNKNOWN(&varSource);
}
if(m_pCurrentXMLReader)
{
ATLASSERT(!m_pPrevContentHandler);
m_nStarted = 1;
hRes = m_pCurrentXMLReader->getContentHandler(&m_pPrevContentHandler);
hRes = m_pCurrentXMLReader->putContentHandler((ISAXContentHandler*)(this));
hRes = pT->StartElement((ISAXAttributes*)pAttributes, CComBSTR(""));
ATLASSERT(SUCCEEDED(hRes));
}else
{
m_nStarted = 0;
if(SUCCEEDED(hRes = m_pCurrentXMLReader.CoCreateInstance(__uuidof(SAXXMLReader))))
{
if(SUCCEEDED(hRes = m_pCurrentXMLReader->putContentHandler(static_cast<ISAXContentHandler*>(this))))
{
hRes = m_pCurrentXMLReader->parse(varSource);
ATLASSERT(SUCCEEDED(hRes));
}
m_pCurrentXMLReader.Release();
}else
{
hRes = ERR_CoCreateInstance_SAXXMLReader;
}
}
return hRes;
}
STDMETHOD(SaveXML)(
/* [in] */ VARIANT VarOutput)
{
T* pT = static_cast<T*>(this);
HRESULT hRes;
CComQIPtr<ISAXContentHandler> pISAXContentHandler;
if(V_VT(&VarOutput) == VT_UNKNOWN)
{
pISAXContentHandler = V_UNKNOWN(&VarOutput);
if(pISAXContentHandler)
return pT->SaveElement(pISAXContentHandler);
}
CComPtr<IMXWriter> pXMLWriter;
if(SUCCEEDED(hRes = pXMLWriter.CoCreateInstance(__uuidof(MXXMLWriter))))
{
pISAXContentHandler = pXMLWriter;
if(pISAXContentHandler)
{
//Setup
hRes = pXMLWriter->put_omitXMLDeclaration(-1);
hRes = pXMLWriter->put_standalone(-1);
hRes = pXMLWriter->put_indent(-1);
hRes = pXMLWriter->put_encoding(L"ASCII");
hRes = pXMLWriter->put_output(VarOutput);
//Start
hRes = pISAXContentHandler->startDocument();
//Save this object
hRes = pT->SaveElement(pISAXContentHandler);
//Finishing
hRes = pISAXContentHandler->endDocument();
if(V_VT(&VarOutput) == (VT_VARIANT|VT_BYREF) )
hRes = pXMLWriter->get_output(V_VARIANTREF(&VarOutput));
hRes = pXMLWriter->put_output(CComVariant(""));
}
pXMLWriter.Release();
}else
hRes = ERR_CoCreateInstance_MXXMLWriter;
return hRes;
}
//IPersistFile Implementation (Help functions)
HRESULT IPersistFile_Load( /* [in] */ LPCOLESTR pszFileName,/* [in] */ DWORD dwMode)
{
T* pT = static_cast<T*>(this);
return ATLIPersistFile_Load( pszFileName, pT->GetUnknown());
}
HRESULT IPersistFile_Save( /* [unique][in] */ LPCOLESTR pszFileName,/* [in] */ BOOL fRemember)
{
T* pT = static_cast<T*>(this);
return ATLIPersistFile_Save( pszFileName, pT->GetUnknown());
}
};
#endif //__IPersistVarXMLImp_h_