00001 #include "xmltk.h"
00002
00003 class CMemoryStream : public IMemoryStream
00004 {
00005 public:
00006
00007 CL_STDMETHOD(QueryInterface) (RCLIID riid, void **ppvObj);
00008 CL_STDMETHOD_(ULONG,AddRef) ();
00009 CL_STDMETHOD_(ULONG,Release) ();
00010
00011
00012 CL_STDMETHOD_(long, CopyTo) (IStream *pstm, long cb);
00013 CL_STDMETHOD_(long, Peek) (void *pv, long cb);
00014 CL_STDMETHOD_(long, Read) (void *pv, long cb);
00015 CL_STDMETHOD_(int, ReadChar) ();
00016 CL_STDMETHOD_(int, Seek) (long offset, int origin);
00017 CL_STDMETHOD_(long, SetSize) (long lsize);
00018 CL_STDMETHOD_(long, Tell) ();
00019 CL_STDMETHOD_(long, Write) (void *pv, long cb);
00020 CL_STDMETHOD(WriteChar) (int ch);
00021
00022
00023 CL_STDMETHOD_(int, getSize) ();
00024 CL_STDMETHOD_(char*, getBuffer) ();
00025 CL_STDMETHOD(setBuffer) (void *pv, int iSize);
00026 CL_STDMETHOD_(int, getGrowSize) ();
00027 CL_STDMETHOD(setGrowSize) (int cchGrow);
00028
00029
00030 CMemoryStream() : m_cRef(1), m_pszBuf(NULL), m_cchBuf(0),
00031 m_iCur(0), m_cchGrow(256), m_iLast(0)
00032 {
00033 }
00034
00035 virtual ~CMemoryStream()
00036 {
00037 if (m_pszBuf)
00038 free(m_pszBuf);
00039 }
00040
00041 private:
00042
00043 void _SetPosition(long iPos)
00044 {
00045 m_iCur = iPos;
00046 m_iLast = max(m_iCur, m_iLast);
00047 }
00048
00049 bool _SizeBuffer(int cchNew)
00050 {
00051 bool bRet = false;
00052
00053 if (m_pszBuf == NULL)
00054 {
00055 m_pszBuf = (char*)malloc(cchNew * sizeof(*m_pszBuf));
00056 if (m_pszBuf)
00057 {
00058 m_cchBuf = cchNew;
00059 bRet = true;
00060 }
00061 }
00062 else
00063 {
00064 char *pszNew = (char*)realloc(m_pszBuf, cchNew / sizeof(*pszNew));
00065 if (pszNew)
00066 {
00067 m_pszBuf = pszNew;
00068 m_cchBuf = cchNew;
00069 bRet = true;
00070 }
00071 }
00072 return bRet;
00073 }
00074
00075 bool _GrowBuffer(int cchNew)
00076 {
00077 cchNew += m_iCur;
00078 if (cchNew >= m_cchBuf)
00079 {
00080 cchNew += m_cchGrow - (cchNew % m_cchGrow);
00081 return _SizeBuffer(cchNew);
00082 }
00083
00084 return true;
00085 }
00086
00087 long _Read(void *pv, long cb, bool fUpdatePosition)
00088 {
00089 cb = min(cb, m_iLast - m_iCur);
00090 memcpy(pv, &m_pszBuf[m_iCur], cb);
00091 if (fUpdatePosition)
00092 _SetPosition(m_iCur + cb);
00093 return cb;
00094 }
00095
00096 ULONG m_cRef;
00097 char *m_pszBuf;
00098 int m_cchBuf;
00099 int m_iCur;
00100 int m_cchGrow;
00101 int m_iLast;
00102 };
00103
00104
00105
00106 bool CMemoryStream::QueryInterface(RCLIID riid, void **ppvObj)
00107 {
00108 if (IsEqualCLIID(riid, &IID_IUnknownCL) ||
00109 IsEqualCLIID(riid, &IID_IStream) ||
00110 IsEqualCLIID(riid, &IID_IMemoryStream))
00111 {
00112 *ppvObj = static_cast<IMemoryStream*>(this);
00113 }
00114 else
00115 {
00116 *ppvObj = NULL;
00117 return false;
00118 }
00119 AddRef();
00120 return true;
00121 }
00122
00123 ULONG CMemoryStream::AddRef()
00124 {
00125 return ++m_cRef;
00126 }
00127
00128 ULONG CMemoryStream::Release()
00129 {
00130 if (--m_cRef > 0)
00131 return m_cRef;
00132
00133 delete this;
00134 return 0;
00135 }
00136
00137
00138 long CMemoryStream::CopyTo(IStream *pstm, long cb)
00139 {
00140 cb = min(cb, (long)(m_iLast - m_iCur));
00141 return pstm->Write((void*)&m_pszBuf[m_iCur], cb);
00142 }
00143
00144 long CMemoryStream::Peek(void *pv, long cb)
00145 {
00146 return _Read(pv, cb, false);
00147 }
00148
00149 long CMemoryStream::Read(void *pv, long cb)
00150 {
00151 return _Read(pv, cb, true);
00152 }
00153
00154 int CMemoryStream::ReadChar()
00155 {
00156 if (m_iCur < m_iLast)
00157 {
00158 int iRet = m_pszBuf[m_iCur];
00159 _SetPosition(m_iCur+1);
00160 return iRet;
00161 }
00162 return EOF;
00163 }
00164
00165 int CMemoryStream::Seek(long offset, int origin)
00166 {
00167 switch (origin)
00168 {
00169 case SEEK_SET:
00170 _SetPosition(offset);
00171 break;
00172
00173 case SEEK_END:
00174 _SetPosition(m_iLast - offset);
00175 break;
00176
00177 case SEEK_CUR:
00178 _SetPosition(m_iCur + offset);
00179 break;
00180 }
00181
00182 return 0;
00183 }
00184
00185 long CMemoryStream::SetSize(long lsize)
00186 {
00187 _SetPosition(min(m_iCur, lsize-1));
00188 return _SizeBuffer(lsize) ? lsize : 0;
00189 }
00190
00191 long CMemoryStream::Tell()
00192 {
00193 return m_iCur;
00194 }
00195
00196 long CMemoryStream::Write(void *pv, long cb)
00197 {
00198 if (_GrowBuffer(cb))
00199 {
00200 memcpy(&m_pszBuf[m_iCur], pv, cb);
00201 _SetPosition(m_iCur + cb);
00202 return cb;
00203 }
00204 return EOF;
00205 }
00206
00207 bool CMemoryStream::WriteChar(int ch)
00208 {
00209 if (_GrowBuffer(1))
00210 {
00211 m_pszBuf[m_iCur] = ch;
00212 _SetPosition(m_iCur+1);
00213 return true;
00214 }
00215 return false;
00216 }
00217
00218
00219 int CMemoryStream::getSize()
00220 {
00221 return m_iLast;
00222 }
00223
00224 char *CMemoryStream::getBuffer()
00225 {
00226 return m_pszBuf;
00227 }
00228
00229 bool CMemoryStream::setBuffer(void *pv, int iSize)
00230 {
00231 m_pszBuf = (char*)pv;
00232 m_cchBuf = iSize;
00233 m_iCur = 0;
00234 m_iLast = iSize - 1;
00235 return true;
00236 }
00237
00238 int CMemoryStream::getGrowSize()
00239 {
00240 return m_cchGrow;
00241 }
00242
00243 bool CMemoryStream::setGrowSize(int cchGrow)
00244 {
00245 m_cchGrow = cchGrow;
00246 return true;
00247 }
00248
00249
00250 bool CreateMemoryStream(RCLIID riid, void **ppvObj)
00251 {
00252 bool bRet = false;
00253 CMemoryStream* pms = new CMemoryStream();
00254 if (pms)
00255 {
00256 bRet = pms->QueryInterface(riid, ppvObj);
00257 pms->Release();
00258 }
00259
00260 return bRet;
00261 }
00262