00001 #include "xmltk.h"
00002 #include "tokenmap.h"
00003
00004 class CBin2TSAX : public IBin2TSAX
00005 {
00006 public:
00007
00008 CL_STDMETHOD(QueryInterface) (RCLIID riid, void **ppvObj);
00009 CL_STDMETHOD_(ULONG,AddRef) ();
00010 CL_STDMETHOD_(ULONG,Release) ();
00011
00012
00013 CL_STDMETHOD(Parse) (IStream *pstm, ITSAXContentHandler *pch);
00014 CL_STDMETHOD_(unsigned int, getSrcOffset) ();
00015 CL_STDMETHOD(skipReader) (unsigned int skipOffset, unsigned int skipLevel);
00016
00017
00018 CL_STDMETHOD(Init) (bool bExternalStream);
00019
00020 CBin2TSAX() : m_cRef(1), m_cchBuf(0), m_bExternalStream(true)
00021 {
00022 m_pszBuf = (char*)calloc(1024, sizeof(char));
00023 m_cchBufMax = m_pszBuf ? 1024 : 0;
00024 }
00025
00026 virtual ~CBin2TSAX()
00027 {
00028 }
00029
00030 private:
00031
00032 bool _ReallocBuffer(int cch)
00033 {
00034 char *psz = (char*)realloc(m_pszBuf, cch * sizeof(char));
00035 if (psz)
00036 {
00037 m_pszBuf = psz;
00038 m_cchBufMax = cch;
00039 }
00040 return psz != NULL;
00041 }
00042
00043 void _ReadString(IStream *pstm)
00044 {
00045
00046
00047
00048
00049 for (m_cchBuf = 0; ; m_cchBuf++)
00050 {
00051 if (m_cchBuf == m_cchBufMax)
00052 {
00053 if (!_ReallocBuffer(m_cchBufMax * 2))
00054 {
00055 m_pszBuf[m_cchBufMax-1] = 0;
00056 break;
00057 }
00058 }
00059
00060 m_pszBuf[m_cchBuf] = pstm->ReadChar();
00061 if (m_pszBuf[m_cchBuf] == EOF || m_pszBuf[m_cchBuf] == 0)
00062 {
00063 m_pszBuf[m_cchBuf] = 0;
00064 break;
00065 }
00066 }
00067 }
00068
00069 void _ReadCDATA(IStream *pstm)
00070 {
00071
00072
00073
00074 m_cchBuf = 0;
00075
00076 unsigned int iLength;
00077 if (freadMultiByteUINT(pstm, &iLength))
00078 {
00079 if (iLength <= m_cchBufMax || _ReallocBuffer(iLength))
00080 {
00081 m_cchBuf = pstm->Read(m_pszBuf, iLength);
00082 }
00083 else
00084 {
00085
00086
00087
00088 fprintf(stderr, "WARNING: CDATA section too large to fit in memory, skipping\n");
00089 pstm->Seek(iLength, SEEK_CUR);
00090 }
00091 }
00092 }
00093
00094 void _Parse(IStream *pstm, ITSAXContentHandler *pch)
00095 {
00096
00097
00098
00099 if (m_bExternalStream)
00100 pch->startDocument();
00101
00102 bool fContinue = true;
00103
00104 XTOKEN xt;
00105 while (fContinue && freadMultiByteUINT(pstm, &xt))
00106 {
00107 switch (xt)
00108 {
00109 case XT_TABLE:
00110 _ParseTableEntries(pstm);
00111 break;
00112
00113 case XT_END:
00114 pch->endElement(m_sxt.top());
00115 m_sxt.pop();
00116
00117
00118
00119
00120 fContinue = !m_sxt.empty();
00121 break;
00122
00123 case XT_STRING:
00124 _ReadString(pstm);
00125 pch->characters(m_pszBuf, m_cchBuf);
00126 break;
00127
00128 case XT_CDATA:
00129 _ReadCDATA(pstm);
00130 pch->cdata(m_pszBuf, m_cchBuf);
00131 break;
00132
00133 default:
00134 {
00135 XTOKEN xtMapped = m_tmap.GetMapping(xt);
00136 if (xtMapped == XT_UNKNOWN)
00137 {
00138
00139
00140
00141
00142 xtMapped = xt;
00143 }
00144
00145 DWORD dwType = g_ptt->TypeFromXTOKEN(xtMapped);
00146 switch (dwType)
00147 {
00148 case XST_ATTRIBUTE:
00149 _ReadString(pstm);
00150 pch->attribute(xtMapped, m_pszBuf, m_cchBuf);
00151 break;
00152
00153 case XST_ELEMENT:
00154 pch->startElement(xtMapped);
00155 m_sxt.push(xtMapped);
00156 break;
00157
00158 case XST_EXTENDEDINT:
00159 {
00160 int iInt;
00161 freadMultiByteUINT(pstm, (unsigned int*)&iInt);
00162 pch->extendedint(xtMapped, iInt);
00163 }
00164 break;
00165
00166 default:
00167 myassert(0);
00168 break;
00169 }
00170 }
00171 break;
00172 }
00173 }
00174
00175 if (m_bExternalStream)
00176 pch->endDocument();
00177 }
00178
00179 bool _ReadString(IStream *pstm, char *pszBuf, int cch)
00180 {
00181 int ch;
00182 for (ch = pstm->ReadChar(); ch != EOF && ch != 0; ch = pstm->ReadChar())
00183 {
00184 if (cch > 0)
00185 {
00186 *pszBuf++ = ch;
00187 cch--;
00188 }
00189
00190 if (ch == 0)
00191 {
00192 break;
00193 }
00194 }
00195
00196 *pszBuf = 0;
00197 return ch != EOF;
00198 }
00199
00200 void _ParseTableEntries(IStream *pstm)
00201 {
00202 myassert(m_bExternalStream);
00203
00204
00205
00206
00207
00208
00209 XTOKEN xt;
00210 for (freadMultiByteUINT(pstm, &xt); xt != XT_END; freadMultiByteUINT(pstm, &xt))
00211 {
00212 DWORD dwType = pstm->ReadChar();
00213
00214 char sz[512];
00215 _ReadString(pstm, sz, ARRAYSIZE(sz));
00216
00217 if (dwType == XST_EXTENDEDINT)
00218 {
00219 char szSuffix[512];
00220 _ReadString(pstm, szSuffix, ARRAYSIZE(szSuffix));
00221
00222 XTOKEN xtMap = g_ptt->XTOKENFromPair(sz, szSuffix, dwType);
00223 m_tmap.AddMapping(xt, xtMap);
00224 }
00225 else
00226 {
00227 XTOKEN xtMap = g_ptt->XTOKENFromStr(sz, dwType);
00228 m_tmap.AddMapping(xt, xtMap);
00229 }
00230 }
00231 }
00232
00233 bool _ValidateHeader(XBINHEADER* pxbh)
00234 {
00235 return pxbh->uVersion == XBIN_VERSION;
00236 }
00237
00238 ULONG m_cRef;
00239 stack<XTOKEN> m_sxt;
00240 char *m_pszBuf;
00241 unsigned int m_cchBufMax;
00242 unsigned int m_cchBuf;
00243 CTokenMap m_tmap;
00244 bool m_bExternalStream;
00245 };
00246
00247 bool CBin2TSAX::Parse(IStream *pstm, ITSAXContentHandler *pch)
00248 {
00249 bool fRet = true;
00250
00251 if (m_bExternalStream)
00252 {
00253
00254
00255
00256 XBINHEADER xbh;
00257 fRet = pstm->Peek(&xbh, sizeof(XBINHEADER)) &&
00258 _ValidateHeader(&xbh);
00259 if (fRet)
00260 {
00261 pstm->Seek(sizeof(XBINHEADER), SEEK_CUR);
00262 _Parse(pstm, pch);
00263 }
00264 }
00265 else
00266 {
00267 _Parse(pstm, pch);
00268 }
00269
00270 return fRet;
00271 }
00272
00273 unsigned int CBin2TSAX::getSrcOffset(void)
00274 {
00275 return 0;
00276 }
00277
00278 bool CBin2TSAX::skipReader(unsigned int skipOffset, unsigned int skipLevel)
00279 {
00280 return false;
00281 }
00282
00283 bool CBin2TSAX::Init(bool bExternalStream)
00284 {
00285 m_bExternalStream = bExternalStream;
00286 return true;
00287 }
00288
00289 bool CBin2TSAX::QueryInterface(RCLIID riid, void **ppvObj)
00290 {
00291 if (IsEqualCLIID(riid, &IID_IUnknownCL) ||
00292 IsEqualCLIID(riid, &IID_IParse2TSAX) ||
00293 IsEqualCLIID(riid, &IID_IBin2TSAX))
00294 {
00295 *ppvObj = static_cast<IBin2TSAX*>(this);
00296 }
00297 else
00298 {
00299 return false;
00300 }
00301 AddRef();
00302 return true;
00303 }
00304
00305 ULONG CBin2TSAX::AddRef()
00306 {
00307 return ++m_cRef;
00308 }
00309
00310 ULONG CBin2TSAX::Release()
00311 {
00312 --m_cRef;
00313 if (m_cRef > 0)
00314 {
00315 return m_cRef;
00316 }
00317 delete this;
00318 return 0;
00319 }
00320
00321 bool CreateBin2TSAX(RCLIID riid, void **ppvObj)
00322 {
00323 bool fRet = false;
00324
00325 CBin2TSAX* pbin2tsax = new CBin2TSAX();
00326 if (pbin2tsax)
00327 {
00328 fRet = pbin2tsax->QueryInterface(riid, ppvObj);
00329 pbin2tsax->Release();
00330 }
00331
00332 return fRet;
00333 }