Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

bin2tsax.cpp

Go to the documentation of this file.
00001 #include "xmltk.h"
00002 #include "tokenmap.h"
00003 
00004 class CBin2TSAX : public IBin2TSAX
00005 {
00006 public:
00007     // *** IUnknownCL methods ***
00008     CL_STDMETHOD(QueryInterface) (RCLIID riid, void **ppvObj);
00009     CL_STDMETHOD_(ULONG,AddRef) ();
00010     CL_STDMETHOD_(ULONG,Release) ();
00011 
00012     // *** IParse2TSAX methods ***
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     // *** IBin2TSAX methods ***
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         // we always use the same buffer and dynamically
00047         // reallocate upon overflow
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         // cdata := length buffer
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                 // can't alloc a big enough buffer.  output error, skip section, keep going.
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         // do the actual work of parsing
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                 // quit if this XT_END closed the root tag
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                         // we must be parsing a stream that doesn't have
00140                         // table entries.
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);  // what happened?
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);    // else shouldn't have table entries
00203         
00204         //
00205         // table := XT_TABLE (mapping)* XT_END
00206         // mapping := token tokentype termstr [ termstr ]       second termstr is present if tokentype is XST_EXTENDEDINT
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         // first read and validate the header
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 }

Generated on Sat Dec 22 16:01:48 2001 for XMILLforBinaryFormat by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001