#pragma once
//
// this class creates an ISequentialStream from a string
//
class CStringStream : public ISequentialStream
{
public:
// factory method
__checkReturn static HRESULT Create(
__in LPWSTR psBuffer,
__deref_out ISequentialStream **ppStream)
{
HRESULT hr = S_OK;
void *pNewBuff = NULL;
size_t buffSize = 0;
if (!psBuffer)
{
return E_INVALIDARG;
}
*ppStream = NULL;
buffSize = (wcslen(psBuffer)+1) * sizeof(wchar_t);
pNewBuff = malloc(buffSize);
if (!pNewBuff)
{
return E_OUTOFMEMORY;
}
hr = StringCbCopy((LPWSTR)pNewBuff, buffSize, psBuffer);
if (S_OK == hr)
{
*ppStream = new CStringStream(
buffSize,
pNewBuff);
}
if (!*ppStream)
{
hr = E_FAIL;
}
return hr;
};
// ISequentialStream
__checkReturn HRESULT STDMETHODCALLTYPE Read(
__out_bcount_part(cb, *pcbRead) void *pv,
/* [in] */ ULONG cb,
__out_opt ULONG *pcbRead)
{
HRESULT hr = S_OK;
for (*pcbRead = 0; *pcbRead < cb; ++*pcbRead, ++m_buffSeekIndex)
{
// we are seeking past the end of the buffer
if (m_buffSeekIndex == m_buffSize)
{
hr = S_FALSE;
break;
}
((BYTE*)pv)[*pcbRead] = ((BYTE*)m_pBuffer)[m_buffSeekIndex];
}
return hr;
};
HRESULT STDMETHODCALLTYPE Write(
__in_bcount(cb) const void *pv,
/* [in] */ ULONG cb,
__out_opt ULONG *pcbWritten)
{
return E_NOTIMPL;
};
// IUnknown
STDMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&m_cRef);
};
STDMETHODIMP_(ULONG) Release()
{
LONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef)
{
delete this;
}
return cRef;
};
STDMETHODIMP QueryInterface(REFIID riid, __deref_out_opt void **ppv)
{
HRESULT hr = S_OK;
if (ppv)
{
*ppv = NULL;
}
else
{
hr = E_INVALIDARG;
}
if (S_OK == hr)
{
if ((__uuidof(IUnknown) == riid) || (riid == __uuidof(ISequentialStream)))
{
AddRef();
*ppv = (ISequentialStream*)this;
}
else
{
hr = E_NOINTERFACE;
}
}
return hr;
};
protected:
LONG m_cRef;
void *m_pBuffer;
size_t m_buffSize;
size_t m_buffSeekIndex;
// constructor/deconstructor
CStringStream(
__in size_t buffSize,
__in void *pBuff)
:
m_cRef(1),
m_pBuffer(pBuff),
m_buffSize(buffSize),
m_buffSeekIndex(0)
{
};
~CStringStream()
{
free(m_pBuffer);
};
};
Wednesday, August 12, 2009
Creating an IStream or ISequentialStream From a String for XmlLite
XmlLite needs an IStream or an ISequentialStream to parse from. You can get one by opening a file like I showed in the previous post, but in my real code I didn’t have a file, I had a string. No biggie, you can always implement your own if there isn’t one already. This CStringStream class implements ISequentialStream using a string as an input. The class factory method takes in a string, creates a buffer, and gives back an ISequentialStream. Awesome, just what you need if you want to use XmlLite on XML in a string. Here is the class implementation:
Subscribe to:
Post Comments (Atom)
can you post your xmllite code which actually uses the CStringStream to read XML from a string and write XML to a string. thanks. this is useful.
ReplyDeleteI will try to dig it up, and sanitize it for the internet.
ReplyDeletehttp://samscode.blogspot.com/2009/10/how-to-use-string-stream-implementation.html
ReplyDeleteThis is where you can see how to use it with xml lite.