XMLFormatter.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:21k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /**
  57.  * $Id: XMLFormatter.cpp,v 1.12 2003/05/16 21:36:55 knoaman Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <xercesc/util/PlatformUtils.hpp>
  63. #include <xercesc/util/XMLUniDefs.hpp>
  64. #include <xercesc/util/XMLString.hpp>
  65. #include <xercesc/util/TransService.hpp>
  66. #include <xercesc/util/TranscodingException.hpp>
  67. #include <xercesc/util/XMLExceptMsgs.hpp>
  68. #include <xercesc/framework/XMLFormatter.hpp>
  69. #include <xercesc/util/Janitor.hpp>
  70. #include <xercesc/util/XMLChar.hpp>
  71. #include <string.h>
  72. XERCES_CPP_NAMESPACE_BEGIN
  73. // ---------------------------------------------------------------------------
  74. //  Local data
  75. //
  76. //  gXXXRef
  77. //      These are hard coded versions of the char refs we put out for the
  78. //      standard char refs.
  79. //
  80. //  gEscapeChars
  81. //      For each style of escape, we have a list of the chars that must
  82. //      be escaped for that style. The first null hit in each list indicates
  83. //      no more valid entries in that list. The first entry is a dummy for
  84. //      the NoEscapes style.
  85. // ---------------------------------------------------------------------------
  86. static const XMLCh  gAmpRef[] =
  87. {
  88.     chAmpersand, chLatin_a, chLatin_m, chLatin_p, chSemiColon, chNull
  89. };
  90. static const XMLCh  gAposRef[] =
  91. {
  92.     chAmpersand, chLatin_a, chLatin_p, chLatin_o, chLatin_s, chSemiColon, chNull
  93. };
  94. static const XMLCh  gGTRef[] =
  95. {
  96.     chAmpersand, chLatin_g, chLatin_t, chSemiColon, chNull
  97. };
  98. static const XMLCh  gLTRef[] =
  99. {
  100.     chAmpersand, chLatin_l, chLatin_t, chSemiColon, chNull
  101. };
  102. static const XMLCh  gQuoteRef[] =
  103. {
  104.     chAmpersand, chLatin_q, chLatin_u, chLatin_o, chLatin_t, chSemiColon, chNull
  105. };
  106. static const unsigned int kEscapeCount = 6;
  107. static const XMLCh gEscapeChars[XMLFormatter::EscapeFlags_Count][kEscapeCount] =
  108. {
  109.         { chNull      , chNull       , chNull        , chNull       , chNull        , chNull }
  110.     ,   { chAmpersand , chCloseAngle , chDoubleQuote , chOpenAngle  , chSingleQuote , chNull }
  111.     ,   { chAmpersand , chOpenAngle  , chDoubleQuote , chNull       , chNull        , chNull }
  112.     ,   { chAmpersand , chOpenAngle  , chNull        , chNull       , chNull        , chNull }
  113. };
  114. // ---------------------------------------------------------------------------
  115. //  Local methods
  116. // ---------------------------------------------------------------------------
  117. bool XMLFormatter::inEscapeList(const XMLFormatter::EscapeFlags escStyle
  118.                               , const XMLCh                     toCheck)
  119. {
  120.     const XMLCh* escList = gEscapeChars[escStyle];
  121.     while (*escList)
  122.     {
  123.         if (*escList++ == toCheck)
  124.             return true;
  125.     }
  126.     /***
  127.      *  XML1.1
  128.      *
  129.      *  Finally, there is considerable demand to define a standard representation of 
  130.      *  arbitrary Unicode characters in XML documents. Therefore, XML 1.1 allows the 
  131.      *  use of character references to the control characters #x1 through #x1F, 
  132.      *  most of which are forbidden in XML 1.0. For reasons of robustness, however, 
  133.      *  these characters still cannot be used directly in documents.
  134.      *  In order to improve the robustness of character encoding detection, the 
  135.      *  additional control characters #x7F through #x9F, which were freely allowed in 
  136.      *  XML 1.0 documents, now must also appear only as character references. 
  137.      *  (Whitespace characters are of course exempt.) The minor sacrifice of backward 
  138.      *  compatibility is considered not significant. 
  139.      *  Due to potential problems with APIs, #x0 is still forbidden both directly and 
  140.      *  as a character reference.
  141.      *
  142.     ***/
  143.     if (fIsXML11)
  144.     {
  145.         // for XML11
  146.         if ( XMLChar1_1::isControlChar(toCheck, 0) &&
  147.             !XMLChar1_1::isWhitespace(toCheck, 0)   )
  148.         {
  149.             return true;    
  150.         }
  151.         else
  152.         {    
  153.             return false;
  154.         }
  155.     }
  156.     else
  157.     {
  158.         return false;
  159.     }
  160. }
  161. // ---------------------------------------------------------------------------
  162. //  XMLFormatter: Constructors and Destructor
  163. // ---------------------------------------------------------------------------
  164. XMLFormatter::XMLFormatter( const   char* const             outEncoding
  165.                             , const char* const             docVersion
  166.                             ,       XMLFormatTarget* const  target
  167.                             , const EscapeFlags             escapeFlags
  168.                             , const UnRepFlags              unrepFlags
  169.                             ,       MemoryManager* const    manager)
  170.     : fEscapeFlags(escapeFlags)
  171.     , fOutEncoding(0)
  172.     , fTarget(target)
  173.     , fUnRepFlags(unrepFlags)
  174.     , fXCoder(0)  
  175.     , fAposRef(0)
  176.     , fAposLen(0)
  177.     , fAmpRef(0)    
  178.     , fAmpLen(0)    
  179.     , fGTRef(0)
  180.     , fGTLen(0)
  181.     , fLTRef(0)
  182.     , fLTLen(0)
  183.     , fQuoteRef(0)
  184.     , fQuoteLen(0) 
  185.     , fIsXML11(false)
  186.     , fMemoryManager(manager)
  187. {
  188.     // Transcode the encoding string
  189.     fOutEncoding = XMLString::transcode(outEncoding, fMemoryManager);
  190.     // Try to create a transcoder for this encoding
  191.     XMLTransService::Codes resCode;
  192.     fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
  193.     (
  194.         fOutEncoding
  195.         , resCode
  196.         , kTmpBufSize
  197.         , fMemoryManager
  198.     );
  199.     if (!fXCoder)
  200.     {
  201.         fMemoryManager->deallocate(fOutEncoding); //delete [] fOutEncoding;
  202.         ThrowXML1
  203.         (
  204.             TranscodingException
  205.             , XMLExcepts::Trans_CantCreateCvtrFor
  206.             , outEncoding
  207.         );
  208.     }
  209.     XMLCh* const tmpDocVer = XMLString::transcode(docVersion, fMemoryManager);
  210.     ArrayJanitor<XMLCh> jname(tmpDocVer, fMemoryManager);
  211.     fIsXML11 = XMLString::equals(tmpDocVer, XMLUni::fgVersion1_1);
  212. }
  213. XMLFormatter::XMLFormatter( const   XMLCh* const            outEncoding
  214.                             , const XMLCh* const            docVersion
  215.                             ,       XMLFormatTarget* const  target
  216.                             , const EscapeFlags             escapeFlags
  217.                             , const UnRepFlags              unrepFlags
  218.                             ,       MemoryManager* const    manager)
  219.     : fEscapeFlags(escapeFlags)
  220.     , fOutEncoding(0)
  221.     , fTarget(target)
  222.     , fUnRepFlags(unrepFlags)
  223.     , fXCoder(0)  
  224.     , fAposRef(0)
  225.     , fAposLen(0)
  226.     , fAmpRef(0)    
  227.     , fAmpLen(0)    
  228.     , fGTRef(0)
  229.     , fGTLen(0)
  230.     , fLTRef(0)
  231.     , fLTLen(0)
  232.     , fQuoteRef(0)
  233.     , fQuoteLen(0) 
  234.     , fIsXML11(false)
  235.     , fMemoryManager(manager)
  236. {
  237.     // Try to create a transcoder for this encoding
  238.     XMLTransService::Codes resCode;
  239.     fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
  240.     (
  241.         outEncoding
  242.         , resCode
  243.         , kTmpBufSize
  244.         , fMemoryManager
  245.     );
  246.     if (!fXCoder)
  247.     {
  248.         ThrowXML1
  249.         (
  250.             TranscodingException
  251.             , XMLExcepts::Trans_CantCreateCvtrFor
  252.             , outEncoding
  253.         );
  254.     }
  255.     // Copy the encoding string
  256.     fOutEncoding = XMLString::replicate(outEncoding, fMemoryManager);
  257.     fIsXML11 = XMLString::equals(docVersion, XMLUni::fgVersion1_1);
  258. }
  259. XMLFormatter::~XMLFormatter()
  260. {
  261.     fMemoryManager->deallocate(fAposRef); //delete [] fAposRef;
  262.     fMemoryManager->deallocate(fAmpRef); //delete [] fAmpRef;
  263.     fMemoryManager->deallocate(fGTRef); //delete [] fGTRef;
  264.     fMemoryManager->deallocate(fLTRef); //delete [] fLTRef;
  265.     fMemoryManager->deallocate(fQuoteRef); //delete [] fQuoteRef;
  266.     fMemoryManager->deallocate(fOutEncoding); //delete [] fOutEncoding;
  267.     delete fXCoder;
  268.     // We DO NOT own the target object!
  269. }
  270. // ---------------------------------------------------------------------------
  271. //  XMLFormatter: Formatting methods
  272. // ---------------------------------------------------------------------------
  273. void
  274. XMLFormatter::formatBuf(const   XMLCh* const    toFormat
  275.                         , const unsigned int    count
  276.                         , const EscapeFlags     escapeFlags
  277.                         , const UnRepFlags      unrepFlags)
  278. {
  279.     //
  280.     //  Figure out the actual escape flag value. If the parameter is not
  281.     //  the default, then take it. Else take the current default.
  282.     //
  283.     const EscapeFlags actualEsc = (escapeFlags == DefaultEscape)
  284.                                 ? fEscapeFlags : escapeFlags;
  285.     // And do the same for the unrep flags
  286.     const UnRepFlags  actualUnRep = (unrepFlags == DefaultUnRep)
  287.                                     ? fUnRepFlags : unrepFlags;
  288.     //
  289.     //  If the actual unrep action is that they want to provide char refs
  290.     //  for unrepresentable chars, then this one is a much more difficult
  291.     //  one to do cleanly, and we handle it separately.
  292.     //
  293.     if (actualUnRep == UnRep_CharRef)
  294.     {
  295.         specialFormat(toFormat, count, actualEsc);
  296.         return;
  297.     }
  298.     //
  299.     //  If we don't have any escape flags set, then we can do the most
  300.     //  efficient loop, else we have to do it the hard way.
  301.     //
  302.     const XMLCh*    srcPtr = toFormat;
  303.     const XMLCh*    endPtr = toFormat + count;
  304.     if (actualEsc == NoEscapes)
  305.     {
  306.         //
  307.         //  Just do a whole buffer at a time into the temp buffer, cap 
  308.         //  it off, and send it to the target. 
  309.         //
  310.         if (srcPtr < endPtr)
  311.            srcPtr += handleUnEscapedChars(srcPtr, endPtr - srcPtr, actualUnRep); 
  312.     }
  313.      else
  314.     {
  315.         //
  316.         //  Escape chars that require it according tot he scale flags 
  317.         //  we were given. For the others, try to accumulate them and 
  318.         //  format them in as big as bulk as we can. 
  319.         //
  320.         while (srcPtr < endPtr)
  321.         {
  322.             //
  323.             //  Run a temp pointer up until we hit a character that we have
  324.             //  to escape. Then we can convert all the chars between our
  325.             //  current source pointer and here all at once.
  326.             //
  327.             const XMLCh* tmpPtr = srcPtr;
  328.             while (!inEscapeList(actualEsc, *tmpPtr) && (tmpPtr < endPtr))
  329.                 tmpPtr++;
  330.             //
  331.             //  If we got any chars, then lets convert them and write them
  332.             //  out.
  333.             //
  334.             if (tmpPtr > srcPtr)
  335.                srcPtr += handleUnEscapedChars(srcPtr, tmpPtr - srcPtr,  
  336.                                               actualUnRep); 
  337.              else if (tmpPtr < endPtr)
  338.             {
  339.                 //
  340.                 //  Ok, so we've hit a char that must be escaped. So do
  341.                 //  this one specially.
  342.                 //
  343.                 const XMLByte * theChars;                
  344.                 switch (*srcPtr) { 
  345.                     case chAmpersand :
  346.                         theChars = getCharRef(fAmpLen, fAmpRef, gAmpRef); 
  347.                         fTarget->writeChars(theChars, fAmpLen, this);
  348.                         break;
  349.                     case chSingleQuote :
  350.                         theChars = getCharRef(fAposLen, fAposRef, gAposRef); 
  351.                         fTarget->writeChars(theChars, fAposLen, this);
  352.                         break;
  353.                     case chDoubleQuote :
  354.                         theChars = getCharRef(fQuoteLen, fQuoteRef, gQuoteRef); 
  355.                         fTarget->writeChars(theChars, fQuoteLen, this);
  356.                         break;
  357.                     case chCloseAngle :
  358.                         theChars = getCharRef(fGTLen, fGTRef, gGTRef); 
  359.                         fTarget->writeChars(theChars, fGTLen, this);
  360.                         break;
  361.                     case chOpenAngle :
  362.                         theChars = getCharRef(fLTLen, fLTRef, gLTRef); 
  363.                         fTarget->writeChars(theChars, fLTLen, this);
  364.                         break;
  365.                     default:
  366.                         // control characters
  367.                         writeCharRef(*srcPtr);
  368.                         break;
  369.                 }
  370.                 srcPtr++;
  371.             }
  372.         }
  373.     }
  374. }
  375. unsigned int 
  376. XMLFormatter::handleUnEscapedChars(const XMLCh *                  srcPtr, 
  377.                                    const unsigned int             oCount, 
  378.                                    const UnRepFlags               actualUnRep) 
  379.    //
  380.    //  Use that to figure out what I should pass to the transcoder. If we
  381.    //  are doing character references or failing for unrepresentable chars,
  382.    //  then we just throw, since we should never get a call for something
  383.    //  we cannot represent. Else, we tell it to just use the replacement
  384.    //  char.
  385.    //
  386.    const XMLTranscoder::UnRepOpts unRepOpts = (actualUnRep == UnRep_Replace)
  387.                                              ? XMLTranscoder::UnRep_RepChar
  388.                                              : XMLTranscoder::UnRep_Throw;
  389.                                              
  390.    unsigned int charsEaten; 
  391.    unsigned int count = oCount; 
  392.  
  393.    while (count) { 
  394.       const unsigned srcChars  
  395.          = count > kTmpBufSize ? kTmpBufSize : count; 
  396.  
  397.       const unsigned int outBytes  
  398.          = fXCoder->transcodeTo(srcPtr, srcChars,  
  399.                                 fTmpBuf, kTmpBufSize, 
  400.                                 charsEaten, unRepOpts); 
  401.  
  402.       if (outBytes) { 
  403.          fTmpBuf[outBytes]     = 0; fTmpBuf[outBytes + 1] = 0; 
  404.          fTmpBuf[outBytes + 2] = 0; fTmpBuf[outBytes + 3] = 0; 
  405.          fTarget->writeChars(fTmpBuf, outBytes, this); 
  406.       } 
  407.  
  408.       srcPtr += charsEaten; 
  409.       count  -= charsEaten; 
  410.    } 
  411.     
  412.    return oCount; // This should be an assertion that count == 0. 
  413.  
  414.  
  415. XMLFormatter& XMLFormatter::operator<<(const XMLCh* const toFormat)
  416. {
  417.     const unsigned int len = XMLString::stringLen(toFormat);
  418.     formatBuf(toFormat, len);
  419.     return *this;
  420. }
  421. XMLFormatter& XMLFormatter::operator<<(const XMLCh toFormat)
  422. {
  423.     // Make a temp string format that
  424.     XMLCh szTmp[2];
  425.     szTmp[0] = toFormat;
  426.     szTmp[1] = 0;
  427.     formatBuf(szTmp, 1);
  428.     return *this;
  429. }
  430. /**
  431.  * the parameter, count, is needed since stringLen()
  432.  * does not work on a BOM like "0xFE0xFF0x000x00" or
  433.  * "0x000x000xFF0xFE"
  434.  **/
  435. void XMLFormatter::writeBOM(const XMLByte* const toFormat
  436.                           , const unsigned int   count)
  437. {
  438.     fTarget->writeChars(toFormat, count, this);    
  439. }
  440. // ---------------------------------------------------------------------------
  441. //  XMLFormatter: Private helper methods
  442. // ---------------------------------------------------------------------------
  443. const void XMLFormatter::writeCharRef(const XMLCh &toWrite)
  444. {
  445.     XMLCh tmpBuf[32];
  446.     tmpBuf[0] = chAmpersand;
  447.     tmpBuf[1] = chPound;
  448.     tmpBuf[2] = chLatin_x;
  449.     // Build a char ref for the current char
  450.     XMLString::binToText(toWrite, &tmpBuf[3], 8, 16);
  451.     const unsigned int bufLen = XMLString::stringLen(tmpBuf);
  452.     tmpBuf[bufLen] = chSemiColon;
  453.     tmpBuf[bufLen+1] = chNull;
  454.     // write it out
  455.     formatBuf(tmpBuf
  456.             , bufLen + 1
  457.             , XMLFormatter::NoEscapes
  458.             , XMLFormatter::UnRep_Fail);
  459. }
  460. const XMLByte* XMLFormatter::getCharRef(unsigned int & count, 
  461.                                         XMLByte*       &ref, 
  462.                                         const XMLCh *  stdRef) 
  463. {
  464.    if (!ref) { 
  465.        unsigned int charsEaten;
  466.        const unsigned int outBytes = 
  467.            fXCoder->transcodeTo(stdRef, XMLString::stringLen(stdRef), 
  468.                                 fTmpBuf, kTmpBufSize, charsEaten, 
  469.                                 XMLTranscoder::UnRep_Throw); 
  470.        fTmpBuf[outBytes] = 0; 
  471.        fTmpBuf[outBytes + 1] = 0;
  472.        fTmpBuf[outBytes + 2] = 0; 
  473.        fTmpBuf[outBytes + 3] = 0;
  474.        ref = (XMLByte*) fMemoryManager->allocate
  475.        (
  476.            (outBytes + 4) * sizeof(XMLByte)
  477.        );//new XMLByte[outBytes + 4]; 
  478.        memcpy(ref, fTmpBuf, outBytes + 4); 
  479.        count = outBytes; 
  480.    }
  481.    return ref; 
  482. }
  483. void XMLFormatter::specialFormat(const  XMLCh* const    toFormat
  484.                                 , const unsigned int    count
  485.                                 , const EscapeFlags     escapeFlags)
  486. {
  487.     //
  488.     //  We have to check each character and see if it could be represented.
  489.     //  As long as it can, we just keep up with where we started and how
  490.     //  many chars we've checked. When we hit an unrepresentable one, we
  491.     //  stop, transcode everything we've collected, then start handling
  492.     //  the unrepresentables via char refs. We repeat this until we get all
  493.     //  the chars done.
  494.     //
  495.     const XMLCh*    srcPtr = toFormat;
  496.     const XMLCh*    endPtr = toFormat + count;
  497.     while (srcPtr < endPtr)
  498.     {
  499.         const XMLCh* tmpPtr = srcPtr;
  500.         while (tmpPtr < endPtr)
  501.         {
  502.             if (fXCoder->canTranscodeTo(*tmpPtr))
  503.                 tmpPtr++;
  504.             else
  505.                 break;
  506.         }
  507.         if (tmpPtr > srcPtr)
  508.         {
  509.             // We got at least some chars that can be done normally
  510.             formatBuf
  511.             (
  512.                 srcPtr
  513.                 , tmpPtr - srcPtr
  514.                 , escapeFlags
  515.                 , XMLFormatter::UnRep_Fail
  516.             );
  517.             // Update the source pointer to our new spot
  518.             srcPtr = tmpPtr;
  519.         }
  520.          else
  521.         {
  522.  
  523.             //  We hit something unrepresentable. So continue forward doing
  524.             //  char refs until we hit something representable again or the
  525.             //  end of input.
  526.             //
  527.             while (srcPtr < endPtr)
  528.             {
  529.                 writeCharRef(*srcPtr);
  530.                 // Move up the source pointer and break out if needed
  531.                 srcPtr++;
  532.                 if (fXCoder->canTranscodeTo(*srcPtr))
  533.                     break;
  534.             }
  535.         }
  536.     }
  537. }
  538. XERCES_CPP_NAMESPACE_END