XMLFormatter.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:21k
源码类别:

xml/soap/webservice

开发平台:

C/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.11 2001/06/20 15:06:59 peiyongz Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <util/PlatformUtils.hpp>
  63. #include <util/XMLUniDefs.hpp>
  64. #include <util/XMLString.hpp>
  65. #include <util/TransService.hpp>
  66. #include <util/TranscodingException.hpp>
  67. #include <util/XMLExceptMsgs.hpp>
  68. #include <framework/XMLFormatter.hpp>
  69. #include <string.h>
  70. // ---------------------------------------------------------------------------
  71. //  Local data
  72. //
  73. //  gXXXRef
  74. //      These are hard coded versions of the char refs we put out for the
  75. //      standard char refs.
  76. //
  77. //  gEscapeChars
  78. //      For each style of escape, we have a list of the chars that must
  79. //      be escaped for that style. The first null hit in each list indicates
  80. //      no more valid entries in that list. The first entry is a dummy for
  81. //      the NoEscapes style.
  82. // ---------------------------------------------------------------------------
  83. static const XMLCh  gAmpRef[] =
  84. {
  85.     chAmpersand, chLatin_a, chLatin_m, chLatin_p, chSemiColon, chNull
  86. };
  87. static const XMLCh  gAposRef[] =
  88. {
  89.     chAmpersand, chLatin_a, chLatin_p, chLatin_o, chLatin_s, chSemiColon, chNull
  90. };
  91. static const XMLCh  gGTRef[] =
  92. {
  93.     chAmpersand, chLatin_g, chLatin_t, chSemiColon, chNull
  94. };
  95. static const XMLCh  gLTRef[] =
  96. {
  97.     chAmpersand, chLatin_l, chLatin_t, chSemiColon, chNull
  98. };
  99. static const XMLCh  gQuoteRef[] =
  100. {
  101.     chAmpersand, chLatin_q, chLatin_u, chLatin_o, chLatin_t, chSemiColon, chNull
  102. };
  103. static const unsigned int kEscapeCount = 6;
  104. static const XMLCh gEscapeChars[XMLFormatter::EscapeFlags_Count][kEscapeCount] =
  105. {
  106.         { chNull      , chNull       , chNull        , chNull       , chNull        , chNull }
  107.     ,   { chAmpersand , chCloseAngle , chDoubleQuote , chOpenAngle  , chSingleQuote , chNull }
  108.     ,   { chAmpersand , chOpenAngle  , chDoubleQuote , chNull       , chNull        , chNull }
  109.     ,   { chAmpersand , chOpenAngle  , chNull        , chNull       , chNull        , chNull }
  110. };
  111. // ---------------------------------------------------------------------------
  112. //  Local methods
  113. // ---------------------------------------------------------------------------
  114. static inline bool inEscapeList(const   XMLFormatter::EscapeFlags escStyle
  115.                                 , const XMLCh                     toCheck)
  116. {
  117.     const XMLCh* escList = gEscapeChars[escStyle];
  118.     while (*escList)
  119.     {
  120.         if (*escList++ == toCheck)
  121.             return true;
  122.     }
  123.     return false;
  124. }
  125. // ---------------------------------------------------------------------------
  126. //  XMLFormatter: Constructors and Destructor
  127. // ---------------------------------------------------------------------------
  128. XMLFormatter::XMLFormatter( const   char* const             outEncoding
  129.                             ,       XMLFormatTarget* const  target
  130.                             , const EscapeFlags             escapeFlags
  131.                             , const UnRepFlags              unrepFlags) :
  132.     fEscapeFlags(escapeFlags)
  133.     , fOutEncoding(0)
  134.     , fTarget(target)
  135.     , fUnRepFlags(unrepFlags)
  136.     , fXCoder(0)
  137.     , fAposRef(0)
  138.     , fAmpRef(0)
  139.     , fGTRef(0)
  140.     , fLTRef(0)
  141.     , fQuoteRef(0)
  142.     , fAposLen(0)
  143.     , fAmpLen(0)
  144.     , fGTLen(0)
  145.     , fLTLen(0)
  146.     , fQuoteLen(0)
  147. {
  148.     // Transcode the encoding string
  149.     fOutEncoding = XMLString::transcode(outEncoding);
  150.     // Try to create a transcoder for this encoding
  151.     XMLTransService::Codes resCode;
  152.     fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
  153.     (
  154.         fOutEncoding
  155.         , resCode
  156.         , kTmpBufSize
  157.     );
  158.     if (!fXCoder)
  159.     {
  160.         delete [] fOutEncoding;
  161.         fOutEncoding = 0;
  162.         ThrowXML1
  163.         (
  164.             TranscodingException
  165.             , XMLExcepts::Trans_CantCreateCvtrFor
  166.             , outEncoding
  167.         );
  168.     }
  169. }
  170. XMLFormatter::XMLFormatter( const   XMLCh* const            outEncoding
  171.                             ,       XMLFormatTarget* const  target
  172.                             , const EscapeFlags             escapeFlags
  173.                             , const UnRepFlags              unrepFlags) :
  174.     fEscapeFlags(escapeFlags)
  175.     , fOutEncoding(0)
  176.     , fTarget(target)
  177.     , fUnRepFlags(unrepFlags)
  178.     , fXCoder(0)
  179.     , fAposRef(0)
  180.     , fAmpRef(0)
  181.     , fGTRef(0)
  182.     , fLTRef(0)
  183.     , fQuoteRef(0)
  184. {
  185.     // Copy the encoding string
  186.     fOutEncoding = XMLString::replicate(outEncoding);
  187.     // Try to create a transcoder for this encoding
  188.     XMLTransService::Codes resCode;
  189.     fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
  190.     (
  191.         fOutEncoding
  192.         , resCode
  193.         , kTmpBufSize
  194.     );
  195.     if (!fXCoder)
  196.     {
  197.         delete [] fOutEncoding;
  198.         fOutEncoding = 0;
  199.         ThrowXML1
  200.         (
  201.             TranscodingException
  202.             , XMLExcepts::Trans_CantCreateCvtrFor
  203.             , outEncoding
  204.         );
  205.     }
  206. }
  207. XMLFormatter::~XMLFormatter()
  208. {
  209.     delete [] fAposRef;
  210.     delete [] fAmpRef;
  211.     delete [] fGTRef;
  212.     delete [] fLTRef;
  213.     delete [] fQuoteRef;
  214.     delete [] fOutEncoding;
  215.     delete fXCoder;
  216.     // We DO NOT own the target object!
  217. }
  218. // ---------------------------------------------------------------------------
  219. //  XMLFormatter: Formatting methods
  220. // ---------------------------------------------------------------------------
  221. void
  222. XMLFormatter::formatBuf(const   XMLCh* const    toFormat
  223.                         , const unsigned int    count
  224.                         , const EscapeFlags     escapeFlags
  225.                         , const UnRepFlags      unrepFlags)
  226. {
  227.     //
  228.     //  Figure out the actual escape flag value. If the parameter is not
  229.     //  the default, then take it. Else take the current default.
  230.     //
  231.     const EscapeFlags actualEsc = (escapeFlags == DefaultEscape)
  232.                                 ? fEscapeFlags : escapeFlags;
  233.     // And do the same for the unrep flags
  234.     const UnRepFlags  actualUnRep = (unrepFlags == DefaultUnRep)
  235.                                     ? fUnRepFlags : unrepFlags;
  236.     //
  237.     //  If the actual unrep action is that they want to provide char refs
  238.     //  for unrepresentable chars, then this one is a much more difficult
  239.     //  one to do cleanly, and we handle it separately.
  240.     //
  241.     if (actualUnRep == UnRep_CharRef)
  242.     {
  243.         specialFormat(toFormat, count, actualEsc);
  244.         return;
  245.     }
  246.     //
  247.     //  Use that to figure out what I should pass to the transcoder. If we
  248.     //  are doing character references or failing for unrepresentable chars,
  249.     //  then we just throw, since we should never get a call for something
  250.     //  we cannot represent. Else, we tell it to just use the replacement
  251.     //  char.
  252.     //
  253.     const XMLTranscoder::UnRepOpts unRepOpts = (actualUnRep == UnRep_Replace)
  254.                                              ? XMLTranscoder::UnRep_RepChar
  255.                                              : XMLTranscoder::UnRep_Throw;
  256.     //
  257.     //  If we don't have any escape flags set, then we can do the most
  258.     //  efficient loop, else we have to do it the hard way.
  259.     //
  260.     const XMLCh*    srcPtr = toFormat;
  261.     const XMLCh*    endPtr = toFormat + count;
  262.     unsigned int    charsEaten;
  263.     if (actualEsc == NoEscapes)
  264.     {
  265.         //
  266.         //  Just do a whole buffer at a time into the temp buffer, cap it
  267.         //  off, and send it to the target.
  268.         //
  269.         while (srcPtr < endPtr)
  270.         {
  271.             const unsigned int srcCount = endPtr - srcPtr;
  272.             const unsigned srcChars = srcCount > kTmpBufSize ?
  273.                                       kTmpBufSize : srcCount;
  274.             const unsigned int outBytes = fXCoder->transcodeTo
  275.             (
  276.                 srcPtr
  277.                 , srcChars
  278.                 , fTmpBuf
  279.                 , kTmpBufSize
  280.                 , charsEaten
  281.                 , unRepOpts
  282.             );
  283.             #if defined(XML_DEBUG)
  284.             if ((outBytes > kTmpBufSize)
  285.             ||  (charsEaten > srcCount))
  286.             {
  287.                 // <TBD> The transcoder is freakin out maaaannn
  288.             }
  289.             #endif
  290.             // If we get any bytes out, then write them
  291.             if (outBytes)
  292.             {
  293.                 fTmpBuf[outBytes] = 0; fTmpBuf[outBytes + 1] = 0;
  294.                 fTmpBuf[outBytes + 2] = 0; fTmpBuf[outBytes + 3] = 0;
  295.                 fTarget->writeChars(fTmpBuf, outBytes, this);
  296.             }
  297.             // And bump up our pointer
  298.             srcPtr += charsEaten;
  299.         }
  300.     }
  301.      else
  302.     {
  303.         //
  304.         //  Escap chars that require it according tot he scale flags we were
  305.         //  given. For the others, try to accumulate them and format them in
  306.         //  as big as bulk as we can.
  307.         //
  308.         while (srcPtr < endPtr)
  309.         {
  310.             //
  311.             //  Run a temp pointer up until we hit a character that we have
  312.             //  to escape. Then we can convert all the chars between our
  313.             //  current source pointer and here all at once.
  314.             //
  315.             const XMLCh* tmpPtr = srcPtr;
  316.             while (!inEscapeList(actualEsc, *tmpPtr) && (tmpPtr < endPtr))
  317.                 tmpPtr++;
  318.             //
  319.             //  If we got any chars, then lets convert them and write them
  320.             //  out.
  321.             //
  322.             if (tmpPtr > srcPtr)
  323.             {
  324.                 const unsigned int srcCount = tmpPtr - srcPtr;
  325.                 const unsigned srcChars = srcCount > kTmpBufSize ?
  326.                                           kTmpBufSize : srcCount;
  327.                 const unsigned int outBytes = fXCoder->transcodeTo
  328.                 (
  329.                     srcPtr
  330.                     , srcChars
  331.                     , fTmpBuf
  332.                     , kTmpBufSize
  333.                     , charsEaten
  334.                     , unRepOpts
  335.                 );
  336.                 #if defined(XML_DEBUG)
  337.                 if ((outBytes > kTmpBufSize)
  338.                 ||  (charsEaten > srcCount))
  339.                 {
  340.                     // <TBD> The transcoder is freakin out maaaannn
  341.                 }
  342.                 #endif
  343.                 // If we get any bytes out, then write them
  344.                 if (outBytes)
  345.                 {
  346.                     fTmpBuf[outBytes] = 0; fTmpBuf[outBytes + 1] = 0;
  347.                     fTmpBuf[outBytes + 2] = 0; fTmpBuf[outBytes + 3] = 0;
  348.                     fTarget->writeChars(fTmpBuf, outBytes, this);
  349.                 }
  350.                 // And bump up our pointer
  351.                 srcPtr += charsEaten;
  352.             }
  353.              else if (tmpPtr < endPtr)
  354.             {
  355.                 //
  356.                 //  Ok, so we've hit a char that must be escaped. So do
  357.                 //  this one specially.
  358.                 //
  359.                 const XMLByte * theChars;
  360.                 unsigned int count = 0;
  361.                 switch(*srcPtr)
  362.                 {
  363.                     case chAmpersand :
  364.                         theChars = getAmpRef(count);
  365.                         fTarget->writeChars(theChars, count, this);
  366.                         break;
  367.                     case chSingleQuote :
  368.                         theChars = getAposRef(count);
  369.                         fTarget->writeChars(theChars, count, this);
  370.                         break;
  371.                     case chDoubleQuote :
  372.                         theChars = getQuoteRef(count);
  373.                         fTarget->writeChars(theChars, count, this);
  374.                         break;
  375.                     case chCloseAngle :
  376.                         theChars = getGTRef(count);
  377.                         fTarget->writeChars(theChars, count, this);
  378.                         break;
  379.                     case chOpenAngle :
  380.                         theChars = getLTRef(count);
  381.                         fTarget->writeChars(theChars, count, this);
  382.                         break;
  383.                     default:
  384.                         // <TBD> This is obviously an error
  385.                         break;
  386.                 }
  387.                 srcPtr++;
  388.             }
  389.         }
  390.     }
  391. }
  392. XMLFormatter& XMLFormatter::operator<<(const XMLCh* const toFormat)
  393. {
  394.     const unsigned int len = XMLString::stringLen(toFormat);
  395.     formatBuf(toFormat, len);
  396.     return *this;
  397. }
  398. XMLFormatter& XMLFormatter::operator<<(const XMLCh toFormat)
  399. {
  400.     // Make a temp string format that
  401.     XMLCh szTmp[2];
  402.     szTmp[0] = toFormat;
  403.     szTmp[1] = 0;
  404.     formatBuf(szTmp, 1);
  405.     return *this;
  406. }
  407. // ---------------------------------------------------------------------------
  408. //  XMLFormatter: Private helper methods
  409. // ---------------------------------------------------------------------------
  410. const XMLByte* XMLFormatter::getAposRef(unsigned int & count)
  411. {
  412.     if (fAposRef)
  413.     {
  414.         count = fAposLen;
  415.         return fAposRef;
  416.     }
  417.     unsigned int charsEaten;
  418.     const unsigned int outBytes = fXCoder->transcodeTo
  419.     (
  420.         gAposRef
  421.         , XMLString::stringLen(gAposRef)
  422.         , fTmpBuf
  423.         , kTmpBufSize
  424.         , charsEaten
  425.         , XMLTranscoder::UnRep_Throw
  426.     );
  427.     fTmpBuf[outBytes] = 0; fTmpBuf[outBytes + 1] = 0;
  428.     fTmpBuf[outBytes + 2] = 0; fTmpBuf[outBytes + 3] = 0;
  429.     ((XMLFormatter*)this)->fAposRef = new XMLByte[outBytes + 4];
  430.     memcpy(fAposRef, fTmpBuf, outBytes + 4);
  431.     count = fAposLen = outBytes;
  432.     return fAposRef;
  433. }
  434. const XMLByte* XMLFormatter::getAmpRef(unsigned int & count)
  435. {
  436.     if (fAmpRef)
  437.     {
  438.         count = fAmpLen;
  439.         return fAmpRef;
  440.     }
  441.     unsigned int charsEaten;
  442.     const unsigned int outBytes = fXCoder->transcodeTo
  443.     (
  444.         gAmpRef
  445.         , XMLString::stringLen(gAmpRef)
  446.         , fTmpBuf
  447.         , kTmpBufSize
  448.         , charsEaten
  449.         , XMLTranscoder::UnRep_Throw
  450.     );
  451.     fTmpBuf[outBytes] = 0; fTmpBuf[outBytes + 1] = 0;
  452.     fTmpBuf[outBytes + 2] = 0; fTmpBuf[outBytes + 3] = 0;
  453.     ((XMLFormatter*)this)->fAmpRef = new XMLByte[outBytes + 4];
  454.     memcpy(fAmpRef, fTmpBuf, outBytes + 4);
  455.     count = fAmpLen = outBytes;
  456.     return fAmpRef;
  457. }
  458. const XMLByte* XMLFormatter::getGTRef(unsigned int & count)
  459. {
  460.     if (fGTRef)
  461.     {
  462.         count = fGTLen;
  463.         return fGTRef;
  464.     }
  465.     unsigned int charsEaten;
  466.     const unsigned int outBytes = fXCoder->transcodeTo
  467.     (
  468.         gGTRef
  469.         , XMLString::stringLen(gGTRef)
  470.         , fTmpBuf
  471.         , kTmpBufSize
  472.         , charsEaten
  473.         , XMLTranscoder::UnRep_Throw
  474.     );
  475.     fTmpBuf[outBytes] = 0; fTmpBuf[outBytes + 1] = 0;
  476.     fTmpBuf[outBytes + 2] = 0; fTmpBuf[outBytes + 3] = 0;
  477.     ((XMLFormatter*)this)->fGTRef = new XMLByte[outBytes + 4];
  478.     memcpy(fGTRef, fTmpBuf, outBytes + 4);
  479.     count = fGTLen = outBytes;
  480.     return fGTRef;
  481. }
  482. const XMLByte* XMLFormatter::getLTRef(unsigned int & count)
  483. {
  484.     if (fLTRef)
  485.     {
  486.         count = fLTLen;
  487.         return fLTRef;
  488.     }
  489.     unsigned int charsEaten;
  490.     const unsigned int outBytes = fXCoder->transcodeTo
  491.     (
  492.         gLTRef
  493.         , XMLString::stringLen(gLTRef)
  494.         , fTmpBuf
  495.         , kTmpBufSize
  496.         , charsEaten
  497.         , XMLTranscoder::UnRep_Throw
  498.     );
  499.     fTmpBuf[outBytes] = 0; fTmpBuf[outBytes + 1] = 0;
  500.     fTmpBuf[outBytes + 2] = 0; fTmpBuf[outBytes + 3] = 0;
  501.     ((XMLFormatter*)this)->fLTRef = new XMLByte[outBytes + 4];
  502.     memcpy(fLTRef, fTmpBuf, outBytes + 4);
  503.     count = fLTLen = outBytes;
  504.     return fLTRef;
  505. }
  506. const XMLByte* XMLFormatter::getQuoteRef(unsigned int & count)
  507. {
  508.     if (fQuoteRef)
  509.     {
  510.         count = fQuoteLen;
  511.         return fQuoteRef;
  512.     }
  513.     unsigned int charsEaten;
  514.     const unsigned int outBytes = fXCoder->transcodeTo
  515.     (
  516.         gQuoteRef
  517.         , XMLString::stringLen(gQuoteRef)
  518.         , fTmpBuf
  519.         , kTmpBufSize
  520.         , charsEaten
  521.         , XMLTranscoder::UnRep_Throw
  522.     );
  523.     fTmpBuf[outBytes] = 0; fTmpBuf[outBytes + 1] = 0;
  524.     fTmpBuf[outBytes + 2] = 0; fTmpBuf[outBytes + 3] = 0;
  525.     ((XMLFormatter*)this)->fQuoteRef = new XMLByte[outBytes + 4];
  526.     memcpy(fQuoteRef, fTmpBuf, outBytes + 4);
  527.     count = fQuoteLen = outBytes;
  528.     return fQuoteRef;
  529. }
  530. void XMLFormatter::specialFormat(const  XMLCh* const    toFormat
  531.                                 , const unsigned int    count
  532.                                 , const EscapeFlags     escapeFlags)
  533. {
  534.     //
  535.     //  We have to check each character and see if it could be represented.
  536.     //  As long as it can, we just keep up with where we started and how
  537.     //  many chars we've checked. When we hit an unrepresentable one, we
  538.     //  stop, transcode everything we've collected, then start handling
  539.     //  the unrepresentables via char refs. We repeat this until we get all
  540.     //  the chars done.
  541.     //
  542.     const XMLCh*    srcPtr = toFormat;
  543.     const XMLCh*    endPtr = toFormat + count;
  544.     // Set up the common part of the buffer that we build char refs into
  545.     XMLCh tmpBuf[32];
  546.     tmpBuf[0] = chAmpersand;
  547.     tmpBuf[1] = chPound;
  548.     tmpBuf[2] = chLatin_x;
  549.     while (srcPtr < endPtr)
  550.     {
  551.         const XMLCh* tmpPtr = srcPtr;
  552.         while (tmpPtr < endPtr)
  553.         {
  554.             if (fXCoder->canTranscodeTo(*tmpPtr))
  555.                 tmpPtr++;
  556.             else
  557.                 break;
  558.         }
  559.         if (tmpPtr > srcPtr)
  560.         {
  561.             // We got at least some chars that can be done normally
  562.             formatBuf
  563.             (
  564.                 srcPtr
  565.                 , tmpPtr - srcPtr
  566.                 , escapeFlags
  567.                 , XMLFormatter::UnRep_Fail
  568.             );
  569.             // Update the source pointer to our new spot
  570.             srcPtr = tmpPtr;
  571.         }
  572.          else
  573.         {
  574.             //
  575.             //  We hit something unrepresentable. So continue forward doing
  576.             //  char refs until we hit something representable again or the
  577.             //  end of input.
  578.             //
  579.             while (srcPtr < endPtr)
  580.             {
  581.                 // Build a char ref for the current char
  582.                 XMLString::binToText(*srcPtr, &tmpBuf[3], 8, 16);
  583.                 const unsigned int bufLen = XMLString::stringLen(tmpBuf);
  584.                 tmpBuf[bufLen] = chSemiColon;
  585.                 tmpBuf[bufLen+1] = chNull;
  586.                 // And now call recursively back to our caller to format this
  587.                 formatBuf
  588.                 (
  589.                     tmpBuf
  590.                     , bufLen + 1
  591.                     , XMLFormatter::NoEscapes
  592.                     , XMLFormatter::UnRep_Fail
  593.                 );
  594.                 // Move up the source pointer and break out if needed
  595.                 srcPtr++;
  596.                 if (fXCoder->canTranscodeTo(*srcPtr))
  597.                     break;
  598.             }
  599.         }
  600.     }
  601. }