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

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2001 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: XMLReader.cpp,v 1.30 2001/12/06 17:47:04 tng Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <util/BitOps.hpp>
  63. #include <util/BinInputStream.hpp>
  64. #include <util/PlatformUtils.hpp>
  65. #include <util/RuntimeException.hpp>
  66. #include <util/TranscodingException.hpp>
  67. #include <util/TransService.hpp>
  68. #include <util/UTFDataFormatException.hpp>
  69. #include <util/XMLEBCDICTranscoder.hpp>
  70. #include <util/XMLString.hpp>
  71. #include <util/XMLUni.hpp>
  72. #include <sax/InputSource.hpp>
  73. #include <framework/XMLBuffer.hpp>
  74. #include <internal/CharTypeTables.hpp>
  75. #include <internal/XMLReader.hpp>
  76. #include <internal/XMLScanner.hpp>
  77. #include <string.h>
  78. // ---------------------------------------------------------------------------
  79. //  XMLReader: static data initialization
  80. // ---------------------------------------------------------------------------
  81. bool XMLReader::fNEL = false;
  82. // ---------------------------------------------------------------------------
  83. //  XMLReader: Public, static methods
  84. // ---------------------------------------------------------------------------
  85. bool XMLReader::isFirstNameChar(const XMLCh toCheck)
  86. {
  87.     static const XMLByte ourMask = gBaseCharMask | gLetterCharMask;
  88.     if ((fgCharCharsTable[toCheck] & ourMask) != 0)
  89.         return true;
  90.     // Check the two special case name start chars
  91.     if ((toCheck == chUnderscore) || (toCheck == chColon))
  92.         return true;
  93.     return false;
  94. }
  95. //
  96. //  Checks whether all of the chars in the passed buffer are whitespace or
  97. //  not. Breaks out on the first non-whitespace.
  98. //
  99. bool XMLReader::isAllSpaces(const   XMLCh* const    toCheck
  100.                             , const unsigned int    count)
  101. {
  102.     const XMLCh* curCh = toCheck;
  103.     const XMLCh* endPtr = toCheck + count;
  104.     while (curCh < endPtr)
  105.     {
  106.         if (!(fgCharCharsTable[*curCh++] & gWhitespaceCharMask))
  107.             return false;
  108.     }
  109.     return true;
  110. }
  111. //
  112. //  Checks whether at least one of the chars in the passed buffer are whitespace or
  113. //  not.
  114. //
  115. bool XMLReader::containsWhiteSpace(const   XMLCh* const    toCheck
  116.                             , const unsigned int    count)
  117. {
  118.     const XMLCh* curCh = toCheck;
  119.     const XMLCh* endPtr = toCheck + count;
  120.     while (curCh < endPtr)
  121.     {
  122.         if (fgCharCharsTable[*curCh++] & gWhitespaceCharMask)
  123.             return true;
  124.     }
  125.     return false;
  126. }
  127. //
  128. //  This one is not called terribly often, so its done manually in order
  129. //  give up more bits in the character characteristics table for more often
  130. //  used characteristics.
  131. //
  132. bool XMLReader::isPublicIdChar(const XMLCh toCheck)
  133. {
  134.     return checkTable(gPublicIdChars, toCheck);
  135. }
  136. void XMLReader::enableNELWS() {
  137.     if (!fNEL) {
  138.         fNEL = true;
  139.         // When option is on, treat NEL same as LF
  140.         fgCharCharsTable[chNEL] = fgCharCharsTable[chLF];
  141.     }
  142. }
  143. // ---------------------------------------------------------------------------
  144. //  XMLReader: Constructors and Destructor
  145. // ---------------------------------------------------------------------------
  146. XMLReader::XMLReader(const  XMLCh* const                pubId
  147.                     , const XMLCh* const                sysId
  148.                     ,       BinInputStream* const       streamToAdopt
  149.                     , const RefFrom                     from
  150.                     , const Types                       type
  151.                     , const Sources                     source
  152.                     , const bool                        throwAtEnd) :
  153.     fCharIndex(0)
  154.     , fCharsAvail(0)
  155.     , fCurCol(1)
  156.     , fCurLine(1)
  157.     , fEncodingStr(0)
  158.     , fForcedEncoding(false)
  159.     , fNoMore(false)
  160.     , fPublicId(XMLString::replicate(pubId))
  161.     , fRawBufIndex(0)
  162.     , fRawBytesAvail(0)
  163.     , fReaderNum(0xFFFFFFFF)
  164.     , fRefFrom(from)
  165.     , fSentTrailingSpace(false)
  166.     , fSource(source)
  167.     , fSpareCh(0)
  168.     , fSrcOfsBase(0)
  169.     , fSrcOfsSupported(false)
  170.     , fStream(streamToAdopt)
  171.     , fSystemId(XMLString::replicate(sysId))
  172.     , fSwapped(false)
  173.     , fThrowAtEnd(throwAtEnd)
  174.     , fTranscoder(0)
  175.     , fType(type)
  176. {
  177.     // Do an initial load of raw bytes
  178.     refreshRawBuffer();
  179.     // Ask the transcoding service if it supports src offset info
  180.     fSrcOfsSupported = XMLPlatformUtils::fgTransService->supportsSrcOfs();
  181.     //
  182.     //  Use the recognizer class to get a basic sense of what family of
  183.     //  encodings this file is in. We'll start off with a reader of that
  184.     //  type, and update it later if needed when we read the XMLDecl line.
  185.     //
  186.     fEncoding = XMLRecognizer::basicEncodingProbe(fRawByteBuf, fRawBytesAvail);
  187.     #if defined(XERCES_DEBUG)
  188.     if ((fEncoding < XMLRecognizer::Encodings_Min)
  189.     ||  (fEncoding > XMLRecognizer::Encodings_Max))
  190.     {
  191.         ThrowXML(RuntimeException, XMLExcepts::Reader_BadAutoEncoding);
  192.     }
  193.     #endif
  194.     fEncodingStr = XMLString::replicate(XMLRecognizer::nameForEncoding(fEncoding));
  195.     // Check whether the fSwapped flag should be set or not
  196.     checkForSwapped();
  197.     //
  198.     //  This will check to see if the first line is an XMLDecl and, if
  199.     //  so, decode that first line manually one character at a time. This
  200.     //  leaves enough characters in the buffer that the high level code
  201.     //  can get through the Decl and call us back with the real encoding.
  202.     //
  203.     doInitDecode();
  204.     //
  205.     //  NOTE: We won't create a transcoder until we either get a call to
  206.     //  setEncoding() or we get a call to refreshCharBuffer() and no
  207.     //  transcoder has been set yet.
  208.     //
  209. }
  210. XMLReader::XMLReader(const  XMLCh* const            pubId
  211.                     , const XMLCh* const            sysId
  212.                     ,       BinInputStream* const   streamToAdopt
  213.                     , const XMLCh* const            encodingStr
  214.                     , const RefFrom                 from
  215.                     , const Types                   type
  216.                     , const Sources                 source
  217.                     , const bool                    throwAtEnd) :
  218.     fCharIndex(0)
  219.     , fCharsAvail(0)
  220.     , fCurCol(1)
  221.     , fCurLine(1)
  222.     , fEncoding(XMLRecognizer::UTF_8)
  223.     , fEncodingStr(0)
  224.     , fForcedEncoding(true)
  225.     , fNoMore(false)
  226.     , fPublicId(XMLString::replicate(pubId))
  227.     , fRawBufIndex(0)
  228.     , fRawBytesAvail(0)
  229.     , fReaderNum(0xFFFFFFFF)
  230.     , fRefFrom(from)
  231.     , fSentTrailingSpace(false)
  232.     , fSource(source)
  233.     , fSpareCh(0)
  234.     , fSrcOfsBase(0)
  235.     , fSrcOfsSupported(false)
  236.     , fStream(streamToAdopt)
  237.     , fSystemId(XMLString::replicate(sysId))
  238.     , fSwapped(false)
  239.     , fThrowAtEnd(throwAtEnd)
  240.     , fTranscoder(0)
  241.     , fType(type)
  242. {
  243.     // Do an initial load of raw bytes
  244.     refreshRawBuffer();
  245.     // Copy the encoding string to our member
  246.     fEncodingStr = XMLString::replicate(encodingStr);
  247.     // Ask the transcoding service if it supports src offset info
  248.     fSrcOfsSupported = XMLPlatformUtils::fgTransService->supportsSrcOfs();
  249.     //
  250.     //  Map the passed encoding name to one of our enums. If it does not
  251.     //  match one of the intrinsic encodings, it will come back 'other',
  252.     //  which tells us to create a transcoder based reader.
  253.     //
  254.     fEncoding = XMLRecognizer::encodingForName(fEncodingStr);
  255.     // Check whether the fSwapped flag should be set or not
  256.     checkForSwapped();
  257.     //
  258.     //  Create a transcoder for the encoding. Since the encoding has been
  259.     //  forced, this will be the one we will use, period.
  260.     //
  261.     XMLTransService::Codes failReason;
  262.     fTranscoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
  263.     (
  264.         fEncodingStr
  265.         , failReason
  266.         , kCharBufSize
  267.     );
  268.     if (!fTranscoder)
  269.     {
  270.         ThrowXML1
  271.         (
  272.             TranscodingException
  273.             , XMLExcepts::Trans_CantCreateCvtrFor
  274.             , fEncodingStr
  275.         );
  276.     }
  277.     //
  278.     //  Note that, unlike above, we do not do an initial decode of the
  279.     //  first line. We take the caller's word that the encoding is correct
  280.     //  and just assume that the first bulk decode (kicked off by the first
  281.     //  get of a character) will work.
  282.     //
  283.     //  So we do here the slipping in of the leading space if required.
  284.     //
  285.     if ((fType == Type_PE) && (fRefFrom == RefFrom_NonLiteral))
  286.     {
  287.         // This represents no data from the source
  288.         fCharSizeBuf[fCharsAvail] = 0;
  289.         fCharBuf[fCharsAvail++] = chSpace;
  290.     }
  291. }
  292. XMLReader::~XMLReader()
  293. {
  294.     delete [] fEncodingStr;
  295.     delete [] fPublicId;
  296.     delete [] fSystemId;
  297.     delete fStream;
  298.     delete fTranscoder;
  299. }
  300. // ---------------------------------------------------------------------------
  301. //  XMLReader: Character buffer management methods
  302. // ---------------------------------------------------------------------------
  303. unsigned int XMLReader::getSrcOffset() const
  304. {
  305.     if (!fSrcOfsSupported)
  306.         ThrowXML(RuntimeException, XMLExcepts::Reader_SrcOfsNotSupported);
  307.     //
  308.     //  Take the current source offset and add in the sizes that we've
  309.     //  eaten from the source so far.
  310.     //
  311.     unsigned int offset = fSrcOfsBase;
  312.     for (unsigned int index = 0; index < fCharIndex; index++)
  313.         offset += fCharSizeBuf[index];
  314.     return offset;
  315. }
  316. bool XMLReader::refreshCharBuffer()
  317. {
  318.     // If the no more flag is set, then don't both doing anything
  319.     if (fNoMore)
  320.         return false;
  321.     unsigned int startInd;
  322.     // See if we have any existing chars.
  323.     const unsigned int spareChars = fCharsAvail - fCharIndex;
  324.     // If we are full, then don't do anything.
  325.     if (spareChars == kCharBufSize)
  326.         return false;
  327.     //
  328.     //  If no transcoder has been created yet, then we never saw the
  329.     //  any encoding="" string and the encoding was not forced, so lets
  330.     //  create one now. We know that it won't change now.
  331.     //
  332.     //  However, note that if we autosensed EBCDIC, then we have to
  333.     //  consider it an error if we never got an encoding since we don't
  334.     //  know what variant of EBCDIC it is.
  335.     //
  336.     if (!fTranscoder)
  337.     {
  338.         if (fEncoding == XMLRecognizer::EBCDIC)
  339.             ThrowXML(RuntimeException, XMLExcepts::Reader_EncodingStrRequired);
  340.         // Ask the transcoding service to make use a transcoder
  341.         XMLTransService::Codes failReason;
  342.         fTranscoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
  343.         (
  344.             fEncodingStr
  345.             , failReason
  346.             , kCharBufSize
  347.         );
  348.         if (!fTranscoder)
  349.         {
  350.             ThrowXML1
  351.             (
  352.                 TranscodingException
  353.                 , XMLExcepts::Trans_CantCreateCvtrFor
  354.                 , fEncodingStr
  355.             );
  356.         }
  357.     }
  358.     //
  359.     //  Add the number of source bytes eaten so far to the base src
  360.     //  offset member.
  361.     //
  362.     for (startInd = 0; startInd < fCharIndex; startInd++)
  363.         fSrcOfsBase += fCharSizeBuf[startInd];
  364.     //
  365.     //  If there are spare chars, then move then down to the bottom. We
  366.     //  have to move the char sizes down also.
  367.     //
  368.     startInd = 0;
  369.     if (spareChars)
  370.     {
  371.         for (unsigned int index = fCharIndex; index < fCharsAvail; index++)
  372.         {
  373.             fCharBuf[startInd] = fCharBuf[index];
  374.             fCharSizeBuf[startInd] = fCharSizeBuf[index];
  375.             startInd++;
  376.         }
  377.     }
  378.     //
  379.     //  And then get more chars, starting after any spare chars that were
  380.     //  left over from the last time.
  381.     //
  382.     fCharsAvail = xcodeMoreChars
  383.     (
  384.         &fCharBuf[startInd]
  385.         , &fCharSizeBuf[startInd]
  386.         , kCharBufSize - spareChars
  387.     );
  388.     // Add back in the spare chars
  389.     fCharsAvail += spareChars;
  390.     // Reset the buffer index to zero, so we start from the 0th char again
  391.     fCharIndex = 0;
  392.     //
  393.     //  If no chars available, then we have to check for one last thing. If
  394.     //  this is reader for a PE and its not being expanded inside a literal,
  395.     //  then unget a trailing space. We use a boolean to avoid triggering
  396.     //  this more than once.
  397.     //
  398.     if (!fCharsAvail
  399.     &&  (fType == Type_PE)
  400.     &&  (fRefFrom == RefFrom_NonLiteral)
  401.     &&  !fSentTrailingSpace)
  402.     {
  403.         fCharBuf[0] = chSpace;
  404.         fCharsAvail = 1;
  405.         fSentTrailingSpace = true;
  406.     }
  407.     //
  408.     //  If we are on our first block of chars and the encoding is one of the
  409.     //  UTF-16 formats, then check the first char for the BOM and skip over
  410.     //  it manually.
  411.     //
  412.     if (fCharsAvail)
  413.     {
  414.         if ((fCurLine == 1) && (fCurCol == 1))
  415.         {
  416.             if (((fEncoding == XMLRecognizer::UTF_16L)
  417.             ||   (fEncoding == XMLRecognizer::UTF_16B))
  418.             &&  !startInd)
  419.             {
  420.                 if ((fCharBuf[startInd] == chUnicodeMarker)
  421.                 ||  (fCharBuf[startInd] == chSwappedUnicodeMarker))
  422.                 {
  423.                     XMLCh chTmp;
  424.                     getNextChar(chTmp);
  425.                 }
  426.             }
  427.         }
  428.     }
  429.     //
  430.     //  If we get here with no more chars, then set the fNoMore flag which
  431.     //  lets us optimize and know without checking that no more chars are
  432.     //  available.
  433.     //
  434.     if (!fCharsAvail)
  435.         fNoMore = true;
  436.     return (fCharsAvail != 0);
  437. }
  438. // ---------------------------------------------------------------------------
  439. //  XMLReader: Scanning methods
  440. // ---------------------------------------------------------------------------
  441. bool XMLReader::getName(XMLBuffer& toFill, const bool token)
  442. {
  443.     //
  444.     //  Ok, first lets see if we have chars in the buffer. If not, then lets
  445.     //  reload.
  446.     //
  447.     if (fCharIndex == fCharsAvail)
  448.     {
  449.         if (!refreshCharBuffer())
  450.             return false;
  451.     }
  452.     //
  453.     //  Lets check the first char for being a first name char. If not, then
  454.     //  what's the point in living mannnn? Just give up now. We only do this
  455.     //  if its a name and not a name token that they want.
  456.     //
  457.     if (!token)
  458.     {
  459.         if (!XMLReader::isFirstNameChar(fCharBuf[fCharIndex]))
  460.             return false;
  461.         // Looks ok, so lets eat it and put it in our buffer. Update column also!
  462.         toFill.append(fCharBuf[fCharIndex++]);
  463.         fCurCol++;
  464.     }
  465.     //
  466.     //  And now we loop until we run out of data in this reader or we hit
  467.     //  a non-name char.
  468.     //
  469.     do {
  470.         unsigned int curCol = fCurCol;
  471.         unsigned int charIndex = fCharIndex;
  472.         unsigned int charsAvail = fCharsAvail;
  473.         while (charIndex < charsAvail)
  474.         {
  475.             const XMLCh curCh = fCharBuf[charIndex];
  476.             //
  477.             //  Check the current char and take it if its a name char. Else
  478.             //  break out.
  479.             //
  480.             if (!XMLReader::isNameChar(curCh))
  481.             {
  482.                 fCharIndex  = charIndex;
  483.                 fCurCol = curCol;
  484.                 return !toFill.isEmpty();
  485.             }
  486.             toFill.append(curCh);
  487.             curCol++;
  488.             charIndex++;
  489.         }
  490.         fCharIndex  = charIndex;
  491.         fCurCol = curCol;
  492.     // If we don't get no more, then break out.
  493.     } while (refreshCharBuffer());
  494.     return !toFill.isEmpty();
  495. }
  496. bool XMLReader::getNextChar(XMLCh& chGotten)
  497. {
  498.     //
  499.     //  See if there is at least a char in the buffer. Else, do the buffer
  500.     //  reload logic.
  501.     //
  502.     if (fCharIndex >= fCharsAvail)
  503.     {
  504.         // If fNoMore is set, then we have nothing else to give
  505.         if (fNoMore)
  506.             return false;
  507.         // If the buffer is empty, then try to refresh
  508.         if (fCharIndex == fCharsAvail)
  509.         {
  510.             refreshCharBuffer();
  511.             // If still empty, then return false
  512.             if (fCharIndex == fCharsAvail)
  513.                 return false;
  514.         }
  515.     }
  516.     chGotten = fCharBuf[fCharIndex++];
  517.     // Handle end of line normalization and line/col member maintenance.
  518.     if (chGotten == chCR)
  519.     {
  520.         //
  521.         //  Do the normalization. We return chLF regardless of which was
  522.         //  found. We also eat a chCR followed by an chLF.
  523.         //
  524.         //  We only do this if the content being spooled is not already
  525.         //  internalized.
  526.         //
  527.         if (fSource == Source_External)
  528.         {
  529.             //
  530.             //  See if we have another char left. If not, don't bother.
  531.             //  Else, see if its an chLF to eat. If it is, bump the
  532.             //  index again.
  533.             //
  534.             if ((fCharIndex < fCharsAvail) || refreshCharBuffer())
  535.             {
  536.                 if (fCharBuf[fCharIndex] == chLF
  537.                     || ((fCharBuf[fCharIndex] == chNEL) && fNEL))
  538.                     fCharIndex++;
  539.             }
  540.             // And return just an chLF
  541.             chGotten = chLF;
  542.         }
  543.         // And handle the line/col stuff
  544.         fCurCol = 1;
  545.         fCurLine++;
  546.     }
  547.      else if (chGotten == chLF
  548.               || ((chGotten == chNEL) && fNEL))
  549.     {
  550.         chGotten = chLF;
  551.         fCurLine++;
  552.         fCurCol = 1;
  553.     }
  554.      else if (chGotten)
  555.     {
  556.         //
  557.         //  Only do this is not a null char. Null chars are not part of the
  558.         //  real content. They are just marker characters inserted into
  559.         //  the stream.
  560.         //
  561.         fCurCol++;
  562.     }
  563.     return true;
  564. }
  565. bool XMLReader::getSpaces(XMLBuffer& toFill)
  566. {
  567.     //
  568.     //  We just loop until we either hit a non-space or the end of this
  569.     //  entity. We return true if we returned because of a non-space and
  570.     //  false if because of end of entity.
  571.     //
  572.     //  NOTE:   We have to maintain line/col info here and we have to do
  573.     //          whitespace normalization if we are not already internalized.
  574.     //
  575.     while (true)
  576.     {
  577.         // Loop through the current chars in the buffer
  578.         while (fCharIndex < fCharsAvail)
  579.         {
  580.             // Get the current char out of the buffer
  581.             XMLCh curCh = fCharBuf[fCharIndex];
  582.             //
  583.             //  See if its a white space char. If so, then process it. Else
  584.             //  we've hit a non-space and need to return.
  585.             //
  586.             if (XMLReader::isWhitespace(curCh))
  587.             {
  588.                 // Eat this char
  589.                 fCharIndex++;
  590.                 //
  591.                 //  Ok, we've got some whitespace here. So we have to store
  592.                 //  it. But we have to normalize it and update the line and
  593.                 //  column info along the way.
  594.                 //
  595.                 if (curCh == chCR)
  596.                 {
  597.                     fCurCol = 1;
  598.                     fCurLine++;
  599.                     //
  600.                     //  If not already internalized, then convert it to an
  601.                     //  LF and eat any following LF.
  602.                     //
  603.                     if (fSource == Source_External)
  604.                     {
  605.                         if ((fCharIndex < fCharsAvail) || refreshCharBuffer())
  606.                         {
  607.                             if (fCharBuf[fCharIndex] == chLF
  608.                                 || ((fCharBuf[fCharIndex] == chNEL) && fNEL))
  609.                                 fCharIndex++;
  610.                         }
  611.                         curCh = chLF;
  612.                     }
  613.                 }
  614.                  else if (curCh == chLF
  615.                           || ((curCh == chNEL) && fNEL))
  616.                 {
  617.                     curCh = chLF;
  618.                     fCurCol = 1;
  619.                     fCurLine++;
  620.                 }
  621.                  else
  622.                 {
  623.                     fCurCol++;
  624.                 }
  625.                 // Ok we can add this guy to our buffer
  626.                 toFill.append(curCh);
  627.             }
  628.              else
  629.             {
  630.                 // Return true to indicate we broke out due to a whitespace
  631.                 return true;
  632.             }
  633.         }
  634.         //
  635.         //  We've eaten up the current buffer, so lets try to reload it. If
  636.         //  we don't get anything new, then break out. If we do, then we go
  637.         //  back to the top to keep getting spaces.
  638.         //
  639.         if (!refreshCharBuffer())
  640.             break;
  641.     }
  642.     return false;
  643. }
  644. bool XMLReader::getUpToCharOrWS(XMLBuffer& toFill, const XMLCh toCheck)
  645. {
  646.     while (true)
  647.     {
  648.         // Loop through the current chars in the buffer
  649.         while (fCharIndex < fCharsAvail)
  650.         {
  651.             // Get the current char out of the buffer
  652.             XMLCh curCh = fCharBuf[fCharIndex];
  653.             //
  654.             //  See if its not a white space or our target char, then process
  655.             //  it. Else, we need to return.
  656.             //
  657.             if (!XMLReader::isWhitespace(curCh) && (curCh != toCheck))
  658.             {
  659.                 // Eat this char
  660.                 fCharIndex++;
  661.                 //
  662.                 //  Ok, we've got some whitespace here. So we have to store
  663.                 //  it. But we have to normalize it and update the line and
  664.                 //  column info along the way.
  665.                 //
  666.                 if (curCh == chCR)
  667.                 {
  668.                     fCurCol = 1;
  669.                     fCurLine++;
  670.                     //
  671.                     //  If not already internalized, then convert it to an
  672.                     //  LF and eat any following LF.
  673.                     //
  674.                     if (fSource == Source_External)
  675.                     {
  676.                         if ((fCharIndex < fCharsAvail) || refreshCharBuffer())
  677.                         {
  678.                             if (fCharBuf[fCharIndex] == chLF
  679.                                 || ((fCharBuf[fCharIndex] == chNEL) && fNEL))
  680.                                 fCharIndex++;
  681.                         }
  682.                         curCh = chLF;
  683.                     }
  684.                 }
  685.                  else if (curCh == chLF
  686.                           || ((curCh == chNEL) && fNEL))
  687.                 {
  688.                     curCh = chLF;
  689.                     fCurCol = 1;
  690.                     fCurLine++;
  691.                 }
  692.                  else
  693.                 {
  694.                     fCurCol++;
  695.                 }
  696.                 // Add it to our buffer
  697.                 toFill.append(curCh);
  698.             }
  699.              else
  700.             {
  701.                 return true;
  702.             }
  703.         }
  704.         //
  705.         //  We've eaten up the current buffer, so lets try to reload it. If
  706.         //  we don't get anything new, then break out. If we do, then we go
  707.         //  back to the top to keep getting spaces.
  708.         //
  709.         if (!refreshCharBuffer())
  710.             break;
  711.     }
  712.     // We never hit any non-space and ate up the whole reader
  713.     return false;
  714. }
  715. bool XMLReader::peekNextChar(XMLCh& chGotten)
  716. {
  717.     //
  718.     //  If there is something still in the buffer, get it. Else do the reload
  719.     //  scenario.
  720.     //
  721.     if (fCharIndex >= fCharsAvail)
  722.     {
  723.         // Try to refresh the buffer
  724.         if (!refreshCharBuffer())
  725.         {
  726.             chGotten = chNull;
  727.             return false;
  728.         }
  729.     }
  730.     chGotten = fCharBuf[fCharIndex];
  731.     //
  732.     //  Even though we are only peeking, we have to act the same as the
  733.     //  normal char get method in regards to newline normalization, though
  734.     //  its not as complicated as the actual character getting method's.
  735.     //
  736.     if ((chGotten == chCR || ((chGotten == chNEL) && fNEL))
  737.         && (fSource == Source_External))
  738.         chGotten = chLF;
  739.     return true;
  740. }
  741. bool XMLReader::skipIfQuote(XMLCh& chGotten)
  742. {
  743.     if (fCharIndex == fCharsAvail)
  744.     {
  745.         if (!refreshCharBuffer())
  746.             return false;
  747.     }
  748.     const XMLCh curCh = fCharBuf[fCharIndex];
  749.     if ((curCh == chDoubleQuote) || (curCh == chSingleQuote))
  750.     {
  751.         chGotten = curCh;
  752.         fCharIndex++;
  753.         fCurCol++;
  754.         return true;
  755.     }
  756.     return false;
  757. }
  758. bool XMLReader::skipSpaces(bool& skippedSomething)
  759. {
  760.     // Remember the current line and column
  761.     unsigned int    orgLine = fCurLine;
  762.     unsigned int    orgCol  = fCurCol;
  763.     //
  764.     //  We enter a loop where we skip over spaces until we hit the end of
  765.     //  this reader or a non-space value. The return indicates whether we
  766.     //  hit the non-space (true) or the end (false).
  767.     //
  768.     while (true)
  769.     {
  770.         // Loop through the current chars in the buffer
  771.         while (fCharIndex < fCharsAvail)
  772.         {
  773.             // Get the current char out of the buffer
  774.             XMLCh curCh = fCharBuf[fCharIndex];
  775.             //
  776.             //  See if its a white space char. If so, then process it. Else
  777.             //  we've hit a non-space and need to return.
  778.             //
  779.             if (XMLReader::isWhitespace(curCh))
  780.             {
  781.                 // Eat this char
  782.                 fCharIndex++;
  783.                 //
  784.                 //  Ok, we've got some whitespace here. So we have to store
  785.                 //  it. But we have to normalize it and update the line and
  786.                 //  column info along the way.
  787.                 //
  788.                 if (curCh == chCR)
  789.                 {
  790.                     fCurCol = 1;
  791.                     fCurLine++;
  792.                     //
  793.                     //  If not already internalized, then convert it to an
  794.                     //  LF and eat any following LF.
  795.                     //
  796.                     if (fSource == Source_External)
  797.                     {
  798.                         if ((fCharIndex < fCharsAvail) || refreshCharBuffer())
  799.                         {
  800.                             if (fCharBuf[fCharIndex] == chLF
  801.                                 || ((fCharBuf[fCharIndex] == chNEL) && fNEL))
  802.                                 fCharIndex++;
  803.                         }
  804.                         curCh = chLF;
  805.                     }
  806.                 }
  807.                  else if (curCh == chLF
  808.                           || ((curCh == chNEL) && fNEL))
  809.                 {
  810.                     curCh = chLF;
  811.                     fCurCol = 1;
  812.                     fCurLine++;
  813.                 }
  814.                  else
  815.                 {
  816.                     fCurCol++;
  817.                 }
  818.             }
  819.              else
  820.             {
  821.                 skippedSomething = (orgLine != fCurLine) || (orgCol != fCurCol);
  822.                 return true;
  823.             }
  824.         }
  825.         //
  826.         //  We've eaten up the current buffer, so lets try to reload it. If
  827.         //  we don't get anything new, then break out. If we do, then we go
  828.         //  back to the top to keep getting spaces.
  829.         //
  830.         if (!refreshCharBuffer())
  831.             break;
  832.     }
  833.     // We never hit any non-space and ate up the whole reader
  834.     skippedSomething = (orgLine != fCurLine) || (orgCol != fCurCol);
  835.     return false;
  836. }
  837. bool XMLReader::skippedChar(const XMLCh toSkip)
  838. {
  839.     //
  840.     //  If the buffer is empty, then try to reload it. If we still get
  841.     //  nothing, then return false.
  842.     //
  843.     if (fCharIndex == fCharsAvail)
  844.     {
  845.         if (!refreshCharBuffer())
  846.             return false;
  847.     }
  848.     //
  849.     //  See if the current char is the one we want. If so, then we need
  850.     //  to eat it and return true.
  851.     //
  852.     if (fCharBuf[fCharIndex] == toSkip)
  853.     {
  854.         fCharIndex++;
  855.         fCurCol++;
  856.         return true;
  857.     }
  858.     return false;
  859. }
  860. bool XMLReader::skippedSpace()
  861. {
  862.     //
  863.     //  If the buffer is empty, then try to reload it. If we still get
  864.     //  nothing, then return false.
  865.     //
  866.     if (fCharIndex == fCharsAvail)
  867.     {
  868.         if (!refreshCharBuffer())
  869.             return false;
  870.     }
  871.     //
  872.     //  See if the current char is a whitespace. If so, then we need to eat
  873.     //  it and return true.
  874.     //
  875.     const XMLCh curCh = fCharBuf[fCharIndex];
  876.     if (XMLReader::isWhitespace(curCh))
  877.     {
  878.         // Eat the character
  879.         fCharIndex++;
  880.         if (curCh == chCR)
  881.         {
  882.             fCurLine++;
  883.             fCurCol = 1;
  884.             if (fSource == Source_External)
  885.             {
  886.                 if ((fCharIndex < fCharsAvail) || refreshCharBuffer())
  887.                 {
  888.                     if (fCharBuf[fCharIndex] == chLF
  889.                         || ((fCharBuf[fCharIndex] == chNEL) && fNEL))
  890.                         fCharIndex++;
  891.                 }
  892.             }
  893.         }
  894.          else if (curCh == chLF
  895.                   || ((curCh == chNEL) && fNEL))
  896.         {
  897.             fCurLine++;
  898.             fCurCol = 1;
  899.         }
  900.          else
  901.         {
  902.             fCurCol++;
  903.         }
  904.         return true;
  905.     }
  906.     return false;
  907. }
  908. bool XMLReader::skippedString(const XMLCh* const toSkip)
  909. {
  910.     // Get the length of the string to skip
  911.     const unsigned int srcLen = XMLString::stringLen(toSkip);
  912.     //
  913.     //  See if the current reader has enough chars to test against this
  914.     //  string. If not, then ask it to reload its buffer. If that does not
  915.     //  get us enough, then it cannot match.
  916.     //
  917.     //  NOTE: This works because strings never have to cross a reader! And
  918.     //  a string to skip will never have a new line in it, so we will never
  919.     //  miss adjusting the current line.
  920.     //
  921.     unsigned int charsLeft = charsLeftInBuffer();
  922.     while (charsLeft < srcLen)
  923.     {
  924.          refreshCharBuffer();
  925.          unsigned int t = charsLeftInBuffer();
  926.          if (t == charsLeft)   // if the refreshCharBuf() did not add anything new
  927.              return false;     //   give up and return.
  928.          charsLeft = t;
  929. }
  930.     //
  931.     //  Ok, now we now that the current reader has enough chars in its
  932.     //  buffer and that its index is back at zero. So we can do a quick and
  933.     //  dirty comparison straight to its buffer with no requirement to unget
  934.     //  if it fails.
  935.     //
  936.     if (XMLString::compareNString(&fCharBuf[fCharIndex], toSkip, srcLen))
  937.         return false;
  938.     // Add the source length to the current column to get it back right
  939.     fCurCol += srcLen;
  940.     //
  941.     //  And get the character buffer index back right by just adding the
  942.     //  source len to it.
  943.     //
  944.     fCharIndex += srcLen;
  945.     return true;
  946. }
  947. //
  948. // This is just to peek if the next coming buffer
  949. // matches the string toPeek.
  950. // Similar to skippedString, but just the fCharIndex and fCurCol are not updated
  951. //
  952. bool XMLReader::peekString(const XMLCh* const toPeek)
  953. {
  954.     // Get the length of the string to skip
  955.     const unsigned int srcLen = XMLString::stringLen(toPeek);
  956.     //
  957.     //  See if the current reader has enough chars to test against this
  958.     //  string. If not, then ask it to reload its buffer. If that does not
  959.     //  get us enough, then it cannot match.
  960.     //
  961.     //  NOTE: This works because strings never have to cross a reader! And
  962.     //  a string to skip will never have a new line in it, so we will never
  963.     //  miss adjusting the current line.
  964.     //
  965.     unsigned int charsLeft = charsLeftInBuffer();
  966.     while (charsLeft < srcLen)
  967.     {
  968.          refreshCharBuffer();
  969.          unsigned int t = charsLeftInBuffer();
  970.          if (t == charsLeft)   // if the refreshCharBuf() did not add anything new
  971.              return false;     //   give up and return.
  972.          charsLeft = t;
  973. }
  974.     //
  975.     //  Ok, now we now that the current reader has enough chars in its
  976.     //  buffer and that its index is back at zero. So we can do a quick and
  977.     //  dirty comparison straight to its buffer with no requirement to unget
  978.     //  if it fails.
  979.     //
  980.     if (XMLString::compareNString(&fCharBuf[fCharIndex], toPeek, srcLen))
  981.         return false;
  982.     return true;
  983. }
  984. // ---------------------------------------------------------------------------
  985. //  XMLReader: Setter methods (most are inlined)
  986. // ---------------------------------------------------------------------------
  987. bool XMLReader::setEncoding(const XMLCh* const newEncoding)
  988. {
  989.     //
  990.     //  If the encoding was forced, then we ignore the new value and just
  991.     //  return with success. If it was forced, then we are to use that
  992.     //  encoding without question. Note that, if we are forced, we created
  993.     //  a transcoder up front so there is no need to do one here in that
  994.     //  case.
  995.     //
  996.     if (fForcedEncoding)
  997.         return true;
  998.     // Clean up the old encoding string
  999. // Do not delete until we know we have a good encoding
  1000. // if (fEncodingStr)
  1001. // {
  1002. // delete [] fEncodingStr;
  1003. // fEncodingStr = 0;
  1004. // }
  1005.     //
  1006.     //  Try to map the string to one of our standard encodings. If its not
  1007.     //  one of them, then it has to be one of the non-intrinsic encodings,
  1008.     //  in which case we have to delete our intrinsic encoder and create a
  1009.     //  new one.
  1010.     //
  1011.     XMLRecognizer::Encodings newBaseEncoding = XMLRecognizer::encodingForName
  1012.     (
  1013.         newEncoding
  1014.     );
  1015.     //
  1016.     //  If it does not come back as one of the auto-sensed encodings, then we
  1017.     //  have to possibly replace it and at least check a few things.
  1018.     //
  1019.     if (newBaseEncoding == XMLRecognizer::OtherEncoding)
  1020.     {
  1021.         //
  1022.         //  Check for non-endian specific UTF-16 or UCS-4. If so, and if we
  1023.         //  are already in one of the endian versions of those encodings,
  1024.         //  then just keep it and go on. Otherwise, its not valid.
  1025.         //
  1026.         if (!XMLString::compareIString(newEncoding, XMLUni::fgUTF16EncodingString)
  1027.         ||  !XMLString::compareIString(newEncoding, XMLUni::fgUTF16EncodingString2)
  1028.         ||  !XMLString::compareIString(newEncoding, XMLUni::fgUTF16EncodingString3)
  1029.         ||  !XMLString::compareIString(newEncoding, XMLUni::fgUTF16EncodingString4))
  1030.         {
  1031.             if ((fEncoding != XMLRecognizer::UTF_16L)
  1032.             &&  (fEncoding != XMLRecognizer::UTF_16B))
  1033.             {
  1034.                 return false;
  1035.             }
  1036.             // Override with the original endian specific encoding
  1037.             newBaseEncoding = fEncoding;
  1038.             if (fEncoding == XMLRecognizer::UTF_16L) {
  1039. delete [] fEncodingStr;
  1040.                 fEncodingStr = XMLString::replicate(XMLUni::fgUTF16LEncodingString);
  1041. }
  1042.             else {
  1043. delete [] fEncodingStr;
  1044.                 fEncodingStr = XMLString::replicate(XMLUni::fgUTF16BEncodingString);
  1045. }
  1046.         }
  1047.          else if (!XMLString::compareIString(newEncoding, XMLUni::fgUCS4EncodingString)
  1048.               ||  !XMLString::compareIString(newEncoding, XMLUni::fgUCS4EncodingString2)
  1049.               ||  !XMLString::compareIString(newEncoding, XMLUni::fgUCS4EncodingString3))
  1050.         {
  1051.             if ((fEncoding != XMLRecognizer::UCS_4L)
  1052.             &&  (fEncoding != XMLRecognizer::UCS_4B))
  1053.             {
  1054.                 return false;
  1055.             }
  1056.             // Override with the original endian specific encoding
  1057.             newBaseEncoding = fEncoding;
  1058.             if (fEncoding == XMLRecognizer::UCS_4L) {
  1059.                 delete [] fEncodingStr;
  1060.                 fEncodingStr = XMLString::replicate(XMLUni::fgUCS4LEncodingString);
  1061. }
  1062.             else {
  1063.                 delete [] fEncodingStr;
  1064.                 fEncodingStr = XMLString::replicate(XMLUni::fgUCS4BEncodingString);
  1065. }
  1066.         }
  1067.          else
  1068.         {
  1069.             // None of those special cases, so just replicate the new name
  1070.             delete [] fEncodingStr;
  1071.             fEncodingStr = XMLString::replicate(newEncoding);
  1072.         }
  1073.     }
  1074.      else
  1075.     {
  1076.         // Store the new encoding string since it is just an intrinsic
  1077.         delete [] fEncodingStr;
  1078.         fEncodingStr = XMLString::replicate(newEncoding);
  1079.     }
  1080.     //
  1081.     //  Now we can create a transcoder using the transcoding service. We
  1082.     //  might get back a transcoder for an intrinsically supported encoding,
  1083.     //  or we might get one from the underlying transcoding service.
  1084.     //
  1085.     XMLTransService::Codes failReason;
  1086.     fTranscoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
  1087.     (
  1088.         fEncodingStr
  1089.         , failReason
  1090.         , kCharBufSize
  1091.     );
  1092.     if (!fTranscoder)
  1093.         ThrowXML1(TranscodingException, XMLExcepts::Trans_CantCreateCvtrFor, fEncodingStr);
  1094.     // Update the base encoding member with the new base encoding found
  1095.     fEncoding = newBaseEncoding;
  1096.     // Looks ok to us
  1097.     return true;
  1098. }
  1099. // ---------------------------------------------------------------------------
  1100. //  XMLReader: Private static init methods
  1101. // ---------------------------------------------------------------------------
  1102. bool XMLReader::checkTable( const   XMLCh* const    theTable
  1103.                             , const XMLCh           toCheck)
  1104. {
  1105.     const XMLCh* curTable = theTable;
  1106.     // Check the ranges
  1107.     while (*curTable)
  1108.     {
  1109.         //
  1110.         //  If the test char is less than the low range, then its never
  1111.         //  going to match any other range, so break out. But we have to
  1112.         //  run up to the range terminator first.
  1113.         //
  1114.         if (toCheck < *curTable++)
  1115.         {
  1116.             while (*curTable++)
  1117.             {
  1118.                 // Purposefully empty, we are just running up the pointer
  1119.             }
  1120.             break;
  1121.         }
  1122.         // If its less than or equal to the top of the range, then a match
  1123.         if (toCheck <= *curTable++)
  1124.             return true;
  1125.     }
  1126.     // And now test against singles
  1127.     while (*curTable)
  1128.     {
  1129.         if (toCheck == *curTable++)
  1130.             return true;
  1131.     }
  1132.     return false;
  1133. }
  1134. // ---------------------------------------------------------------------------
  1135. //  XMLReader: Private helper methods
  1136. // ---------------------------------------------------------------------------
  1137. //
  1138. //  This is called when the encoding flag is set and just sets the fSwapped
  1139. //  flag appropriately.
  1140. //
  1141. void XMLReader::checkForSwapped()
  1142. {
  1143.     // Assume not swapped
  1144.     fSwapped = false;
  1145.     #if defined(ENDIANMODE_LITTLE)
  1146.         if ((fEncoding == XMLRecognizer::UTF_16B)
  1147.         ||  (fEncoding == XMLRecognizer::UCS_4B))
  1148.         {
  1149.             fSwapped = true;
  1150.         }
  1151.     #elif defined(ENDIANMODE_BIG)
  1152.         if ((fEncoding == XMLRecognizer::UTF_16L)
  1153.         ||  (fEncoding == XMLRecognizer::UCS_4L))
  1154.         {
  1155.             fSwapped = true;
  1156.         }
  1157.     #endif
  1158. }
  1159. //
  1160. //  This is called from the constructor when the encoding is not forced.
  1161. //  We assume that the encoding has been auto-sensed at this point and that
  1162. //  fSwapped is set correctly.
  1163. //
  1164. //  In the case of UCS-4 and EBCDIC, we don't have to check for a decl.
  1165. //  The fact that we got here, means that there is one, because that's the
  1166. //  only way we can autosense those.
  1167. //
  1168. void XMLReader::doInitDecode()
  1169. {
  1170.     switch(fEncoding)
  1171.     {
  1172.         case XMLRecognizer::UCS_4B :
  1173.         case XMLRecognizer::UCS_4L :
  1174.         {
  1175.             // Look at the raw buffer as UCS4 chars
  1176.             const UCS4Ch* asUCS = (const UCS4Ch*)fRawByteBuf;
  1177.             while (fRawBufIndex < fRawBytesAvail)
  1178.             {
  1179.                 // Get out the current 4 byte value and inc our raw buf index
  1180.                 UCS4Ch curVal = *asUCS++;
  1181.                 fRawBufIndex += sizeof(UCS4Ch);
  1182.                 // Swap if that is required for this machine
  1183.                 if (fSwapped)
  1184.                     curVal = BitOps::swapBytes(curVal);
  1185.                 // Make sure its at least semi legal. If not, undo and throw
  1186.                 if (curVal > 0xFFFF)
  1187.                 {
  1188.                     fCharsAvail = 0;
  1189.                     fRawBufIndex = 0;
  1190.                     ThrowXML1
  1191.                     (
  1192.                         TranscodingException
  1193.                         , XMLExcepts::Reader_CouldNotDecodeFirstLine
  1194.                         , fSystemId
  1195.                     );
  1196.                 }
  1197.                 // Convert the value to an XML char and store it
  1198.                 fCharSizeBuf[fCharsAvail] = 4;
  1199.                 fCharBuf[fCharsAvail++] = XMLCh(curVal);
  1200.                 // Break out on the > character
  1201.                 if (curVal == chCloseAngle)
  1202.                     break;
  1203.             }
  1204.             break;
  1205.         }
  1206.         case XMLRecognizer::UTF_8 :
  1207.         {
  1208.             // If there's a utf-8 BOM  (0xEF 0xBB 0xBF), skip past it.
  1209.             //   Don't move to char buf - no one wants to see it.
  1210.             //   Note: this causes any encoding= declaration to override
  1211.             //         the BOM's attempt to say that the encoding is utf-8.
  1212.             // Look at the raw buffer as short chars
  1213.             const char* asChars = (const char*)fRawByteBuf;
  1214.             if (fRawBytesAvail > XMLRecognizer::fgUTF8BOMLen &&
  1215.                 XMLString::compareNString(  asChars
  1216.                                             , XMLRecognizer::fgUTF8BOM
  1217.                                             , XMLRecognizer::fgUTF8BOMLen) == 0)
  1218.             {
  1219.                 fRawBufIndex += XMLRecognizer::fgUTF8BOMLen;
  1220.                 asChars      += XMLRecognizer::fgUTF8BOMLen;
  1221.             }
  1222.             //
  1223.             //  First check that there are enough bytes to even see the
  1224.             //  decl indentifier. If not, get out now with no action since
  1225.             //  there is no decl.
  1226.             //
  1227.             if (fRawBytesAvail < XMLRecognizer::fgASCIIPreLen)
  1228.                 break;
  1229.             // Check for the opening sequence. If not, then no decl
  1230.             if (XMLString::compareNString(  asChars
  1231.                                             , XMLRecognizer::fgASCIIPre
  1232.                                             , XMLRecognizer::fgASCIIPreLen))
  1233.             {
  1234.                 break;
  1235.             }
  1236.             while (fRawBufIndex < fRawBytesAvail)
  1237.             {
  1238.                 const char curCh = *asChars++;
  1239.                 fRawBufIndex++;
  1240.                 // Looks ok, so store it
  1241.                 fCharSizeBuf[fCharsAvail] = 1;
  1242.                 fCharBuf[fCharsAvail++] = XMLCh(curCh);
  1243.                 // Break out on a > character
  1244.                 if (curCh == chCloseAngle)
  1245.                     break;
  1246.                 //
  1247.                 //  A char greater than 0x7F is not allowed in this case. If
  1248.                 //  so, undo and throw.
  1249.                 //
  1250.                 if (curCh & 0x80)
  1251.                 {
  1252.                     fCharsAvail = 0;
  1253.                     fRawBufIndex = 0;
  1254.                     ThrowXML1
  1255.                     (
  1256.                         TranscodingException
  1257.                         , XMLExcepts::Reader_CouldNotDecodeFirstLine
  1258.                         , fSystemId
  1259.                     );
  1260.                 }
  1261.             }
  1262.             break;
  1263.         }
  1264.         case XMLRecognizer::UTF_16B :
  1265.         case XMLRecognizer::UTF_16L :
  1266.         {
  1267.             //
  1268.             //  If there is a decl here, we just truncate back the characters
  1269.             //  as we go. No surrogate creation would be allowed here in legal
  1270.             //  XML, so we consider it a transoding error if we find one.
  1271.             //
  1272.             if (fRawBytesAvail < 2)
  1273.                 break;
  1274.             const UTF16Ch* asUTF16 = (const UTF16Ch*)&fRawByteBuf[fRawBufIndex];
  1275.             if ((*asUTF16 == chUnicodeMarker) || (*asUTF16 == chSwappedUnicodeMarker))
  1276.             {
  1277.                 fRawBufIndex += sizeof(UTF16Ch);
  1278.                 asUTF16++;
  1279.             }
  1280.             //  First check that there are enough raw bytes for there to even
  1281.             //  be a decl indentifier. If not, then nothing to do.
  1282.             //
  1283.             if (fRawBytesAvail - fRawBufIndex < XMLRecognizer::fgUTF16PreLen)
  1284.             {
  1285.                 fRawBufIndex = 0;
  1286.                 break;
  1287.             }
  1288.             //
  1289.             //  See we get a match on the prefix. If not, then reset and
  1290.             //  break out.
  1291.             //