src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/Decoder.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 384
8f2986ff0235
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  *
    25  * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC.
    26  */
    28 package com.sun.xml.internal.fastinfoset;
    30 import com.sun.xml.internal.fastinfoset.alphabet.BuiltInRestrictedAlphabets;
    31 import com.sun.xml.internal.fastinfoset.org.apache.xerces.util.XMLChar;
    32 import com.sun.xml.internal.fastinfoset.util.CharArray;
    33 import com.sun.xml.internal.fastinfoset.util.CharArrayArray;
    34 import com.sun.xml.internal.fastinfoset.util.CharArrayString;
    35 import com.sun.xml.internal.fastinfoset.util.ContiguousCharArrayArray;
    36 import com.sun.xml.internal.fastinfoset.util.DuplicateAttributeVerifier;
    37 import com.sun.xml.internal.fastinfoset.util.PrefixArray;
    38 import com.sun.xml.internal.fastinfoset.util.QualifiedNameArray;
    39 import com.sun.xml.internal.fastinfoset.util.StringArray;
    40 import com.sun.xml.internal.fastinfoset.vocab.ParserVocabulary;
    41 import java.io.EOFException;
    42 import java.io.IOException;
    43 import java.io.InputStream;
    44 import java.util.ArrayList;
    45 import java.util.HashMap;
    46 import java.util.List;
    47 import java.util.Map;
    48 import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetException;
    49 import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetParser;
    51 /**
    52  * Abstract decoder for developing concrete encoders.
    53  *
    54  * Concrete implementations extending Decoder will utilize methods on Decoder
    55  * to decode XML infoset according to the Fast Infoset standard. It is the
    56  * responsibility of the concrete implementation to ensure that methods are
    57  * invoked in the correct order to correctly decode a valid fast infoset
    58  * document.
    59  *
    60  * <p>
    61  * This class extends org.sax.xml.DefaultHandler so that concrete SAX
    62  * implementations can be used with javax.xml.parsers.SAXParser and the parse
    63  * methods that take org.sax.xml.DefaultHandler as a parameter.
    64  *
    65  * <p>
    66  * Buffering of octets that are read from an {@link java.io.InputStream} is
    67  * supported in a similar manner to a {@link java.io.BufferedInputStream}.
    68  * Combining buffering with decoding enables better performance.
    69  *
    70  * <p>
    71  * More than one fast infoset document may be decoded from the
    72  * {@link java.io.InputStream}.
    73  */
    74 public abstract class Decoder implements FastInfosetParser {
    76     private static final char[] XML_NAMESPACE_NAME_CHARS =
    77             EncodingConstants.XML_NAMESPACE_NAME.toCharArray();
    79     private static final char[] XMLNS_NAMESPACE_PREFIX_CHARS =
    80             EncodingConstants.XMLNS_NAMESPACE_PREFIX.toCharArray();
    82     private static final char[] XMLNS_NAMESPACE_NAME_CHARS =
    83             EncodingConstants.XMLNS_NAMESPACE_NAME.toCharArray();
    85     /**
    86      * String interning system property.
    87      */
    88     public static final String STRING_INTERNING_SYSTEM_PROPERTY =
    89             "com.sun.xml.internal.fastinfoset.parser.string-interning";
    91     /**
    92      * Internal buffer size interning system property.
    93      */
    94     public static final String BUFFER_SIZE_SYSTEM_PROPERTY =
    95             "com.sun.xml.internal.fastinfoset.parser.buffer-size";
    97     private static boolean _stringInterningSystemDefault = false;
    99     private static int _bufferSizeSystemDefault = 1024;
   101     static {
   102         String p = System.getProperty(STRING_INTERNING_SYSTEM_PROPERTY,
   103                 Boolean.toString(_stringInterningSystemDefault));
   104         _stringInterningSystemDefault = Boolean.valueOf(p).booleanValue();
   106         p = System.getProperty(BUFFER_SIZE_SYSTEM_PROPERTY,
   107                 Integer.toString(_bufferSizeSystemDefault));
   108         try {
   109             int i = Integer.valueOf(p).intValue();
   110             if (i > 0) {
   111                 _bufferSizeSystemDefault = i;
   112             }
   113         } catch (NumberFormatException e) {
   114         }
   115     }
   117     /**
   118      * True if string interning is performed by the decoder.
   119      */
   120     private boolean _stringInterning = _stringInterningSystemDefault;
   122     /**
   123      * The input stream from which the fast infoset document is being read.
   124      */
   125     private InputStream _s;
   127     /**
   128      * The map of URIs to referenced vocabularies.
   129      */
   130     private Map _externalVocabularies;
   132     /**
   133      * True if can parse fragments.
   134      */
   135     protected boolean _parseFragments;
   137     /**
   138      * True if needs to close underlying input stream.
   139      */
   140     protected boolean _needForceStreamClose;
   142     /**
   143      * True if the vocabulary is internally created by decoder.
   144      */
   145     private boolean _vIsInternal;
   147     /**
   148      * The list of Notation Information Items that are part of the
   149      * Document Information Item.
   150      */
   151     protected List _notations;
   153     /**
   154      * The list of Unparsed Entity Information Items that are part of the
   155      * Document Information Item.
   156      */
   157     protected List _unparsedEntities;
   159     /**
   160      * The map of URIs to registered encoding algorithms.
   161      */
   162     protected Map _registeredEncodingAlgorithms = new HashMap();
   164     /**
   165      * The vocabulary used for decoding.
   166      */
   167     protected ParserVocabulary _v;
   169     /**
   170      * The prefix table of the vocabulary.
   171      */
   172     protected PrefixArray _prefixTable;
   174     /**
   175      * The element name table of the vocabulary.
   176      */
   177     protected QualifiedNameArray _elementNameTable;
   179     /**
   180      * The attribute name table of the vocabulary.
   181      */
   182     protected QualifiedNameArray _attributeNameTable;
   184     /**
   185      * The character content chunk table of the vocabulary.
   186      */
   187     protected ContiguousCharArrayArray _characterContentChunkTable;
   189     /**
   190      * The attribute value table of the vocabulary.
   191      */
   192     protected StringArray _attributeValueTable;
   194     /**
   195      * The current octet that is being read
   196      */
   197     protected int _b;
   199     /**
   200      * True if an information item is terminated.
   201      */
   202     protected boolean _terminate;
   204     /**
   205      * True if two information item are terminated in direct sequence.
   206      */
   207     protected boolean _doubleTerminate;
   209     /**
   210      * True if an entry is required to be added to a table
   211      */
   212     protected boolean _addToTable;
   214     /**
   215      * The vocabulary table index to an indexed non identifying string.
   216      */
   217     protected int _integer;
   219     /**
   220      * The vocabulary table index of identifying string or the identifier of
   221      * an encoding algorithm or restricted alphabet.
   222      */
   223     protected int _identifier;
   225     /**
   226      * The size of the internal buffer.
   227      */
   228     protected int _bufferSize = _bufferSizeSystemDefault;
   230     /**
   231      * The internal buffer used for decoding.
   232      */
   233     protected byte[] _octetBuffer = new byte[_bufferSizeSystemDefault];
   235     /**
   236      * A mark into the internal buffer used for decoding encoded algorithm
   237      * or restricted alphabet data.
   238      */
   239     protected int _octetBufferStart;
   241     /**
   242      * The offset into the buffer to read the next byte.
   243      */
   244     protected int _octetBufferOffset;
   246     /**
   247      * The end of the buffer.
   248      */
   249     protected int _octetBufferEnd;
   251     /**
   252      * The length of some octets in the buffer that are to be read.
   253      */
   254     protected int _octetBufferLength;
   256     /**
   257      * The internal buffer of characters.
   258      */
   259     protected char[] _charBuffer = new char[512];
   261     /**
   262      * The length of characters in the buffer of characters.
   263      */
   264     protected int _charBufferLength;
   266     /**
   267      * Helper class that checks for duplicate attribute information items.
   268      */
   269     protected DuplicateAttributeVerifier _duplicateAttributeVerifier = new DuplicateAttributeVerifier();
   271     /**
   272      * Default constructor for the Decoder.
   273      */
   274     protected Decoder() {
   275         _v = new ParserVocabulary();
   276         _prefixTable = _v.prefix;
   277         _elementNameTable = _v.elementName;
   278         _attributeNameTable = _v.attributeName;
   279         _characterContentChunkTable = _v.characterContentChunk;
   280         _attributeValueTable = _v.attributeValue;
   281         _vIsInternal = true;
   282     }
   285     // FastInfosetParser interface
   287     /**
   288      * {@inheritDoc}
   289      */
   290     public void setStringInterning(boolean stringInterning) {
   291         _stringInterning = stringInterning;
   292     }
   294     /**
   295      * {@inheritDoc}
   296      */
   297     public boolean getStringInterning() {
   298         return _stringInterning;
   299     }
   301     /**
   302      * {@inheritDoc}
   303      */
   304     public void setBufferSize(int bufferSize) {
   305         if (_bufferSize > _octetBuffer.length) {
   306             _bufferSize = bufferSize;
   307         }
   308     }
   310     /**
   311      * {@inheritDoc}
   312      */
   313     public int getBufferSize() {
   314         return _bufferSize;
   315     }
   317     /**
   318      * {@inheritDoc}
   319      */
   320     public void setRegisteredEncodingAlgorithms(Map algorithms) {
   321         _registeredEncodingAlgorithms = algorithms;
   322         if (_registeredEncodingAlgorithms == null) {
   323             _registeredEncodingAlgorithms = new HashMap();
   324         }
   325     }
   327     /**
   328      * {@inheritDoc}
   329      */
   330     public Map getRegisteredEncodingAlgorithms() {
   331         return _registeredEncodingAlgorithms;
   332     }
   334     /**
   335      * {@inheritDoc}
   336      */
   337     public void setExternalVocabularies(Map referencedVocabualries) {
   338         if (referencedVocabualries != null) {
   339             // Clone the input map
   340             _externalVocabularies = new HashMap();
   341             _externalVocabularies.putAll(referencedVocabualries);
   342         } else {
   343             _externalVocabularies = null;
   344         }
   345     }
   347     /**
   348      * {@inheritDoc}
   349      */
   350     public Map getExternalVocabularies() {
   351         return _externalVocabularies;
   352     }
   354     /**
   355      * {@inheritDoc}
   356      */
   357     public void setParseFragments(boolean parseFragments) {
   358         _parseFragments = parseFragments;
   359     }
   361     /**
   362      * {@inheritDoc}
   363      */
   364     public boolean getParseFragments() {
   365         return _parseFragments;
   366     }
   368     /**
   369      * {@inheritDoc}
   370      */
   371     public void setForceStreamClose(boolean needForceStreamClose) {
   372         _needForceStreamClose = needForceStreamClose;
   373     }
   375     /**
   376      * {@inheritDoc}
   377      */
   378     public boolean getForceStreamClose() {
   379         return _needForceStreamClose;
   380     }
   382 // End FastInfosetParser interface
   384     /**
   385      * Reset the decoder for reuse decoding another XML infoset.
   386      */
   387     public void reset() {
   388         _terminate = _doubleTerminate = false;
   389     }
   391     /**
   392      * Set the ParserVocabulary to be used for decoding.
   393      *
   394      * @param v the vocabulary to be used for decoding.
   395      */
   396     public void setVocabulary(ParserVocabulary v) {
   397         _v = v;
   398         _prefixTable = _v.prefix;
   399         _elementNameTable = _v.elementName;
   400         _attributeNameTable = _v.attributeName;
   401         _characterContentChunkTable = _v.characterContentChunk;
   402         _attributeValueTable = _v.attributeValue;
   403         _vIsInternal = false;
   404     }
   406     /**
   407      * Set the InputStream to decode the fast infoset document.
   408      *
   409      * @param s the InputStream where the fast infoset document is decoded from.
   410      */
   411     public void setInputStream(InputStream s) {
   412         _s = s;
   413         _octetBufferOffset = 0;
   414         _octetBufferEnd = 0;
   415         if (_vIsInternal == true) {
   416             _v.clear();
   417         }
   418     }
   420     protected final void decodeDII() throws FastInfosetException, IOException {
   421         final int b = read();
   422         if (b == EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) {
   423             decodeInitialVocabulary();
   424         } else if (b != 0) {
   425             throw new IOException(CommonResourceBundle.getInstance().
   426                     getString("message.optinalValues"));
   427         }
   428     }
   430     protected final void decodeAdditionalData() throws FastInfosetException, IOException {
   431         final int noOfItems = decodeNumberOfItemsOfSequence();
   433         for (int i = 0; i < noOfItems; i++) {
   434             /*String URI = */decodeNonEmptyOctetStringOnSecondBitAsUtf8String();
   436             decodeNonEmptyOctetStringLengthOnSecondBit();
   437             ensureOctetBufferSize();
   438             _octetBufferStart = _octetBufferOffset;
   439             _octetBufferOffset += _octetBufferLength;
   440         }
   441     }
   443     protected final void decodeInitialVocabulary() throws FastInfosetException, IOException {
   444         // First 5 optionals of 13 bit optional field
   445         int b = read();
   446         // Next 8 optionals of 13 bit optional field
   447         int b2 = read();
   449         // Optimize for the most common case
   450         if (b == EncodingConstants.INITIAL_VOCABULARY_EXTERNAL_VOCABULARY_FLAG && b2 == 0) {
   451             decodeExternalVocabularyURI();
   452             return;
   453         }
   455         if ((b & EncodingConstants.INITIAL_VOCABULARY_EXTERNAL_VOCABULARY_FLAG) > 0) {
   456             decodeExternalVocabularyURI();
   457         }
   459         if ((b & EncodingConstants.INITIAL_VOCABULARY_RESTRICTED_ALPHABETS_FLAG) > 0) {
   460             decodeTableItems(_v.restrictedAlphabet);
   461         }
   463         if ((b & EncodingConstants.INITIAL_VOCABULARY_ENCODING_ALGORITHMS_FLAG) > 0) {
   464             decodeTableItems(_v.encodingAlgorithm);
   465         }
   467         if ((b & EncodingConstants.INITIAL_VOCABULARY_PREFIXES_FLAG) > 0) {
   468             decodeTableItems(_v.prefix);
   469         }
   471         if ((b & EncodingConstants.INITIAL_VOCABULARY_NAMESPACE_NAMES_FLAG) > 0) {
   472             decodeTableItems(_v.namespaceName);
   473         }
   475         if ((b2 & EncodingConstants.INITIAL_VOCABULARY_LOCAL_NAMES_FLAG) > 0) {
   476             decodeTableItems(_v.localName);
   477         }
   479         if ((b2 & EncodingConstants.INITIAL_VOCABULARY_OTHER_NCNAMES_FLAG) > 0) {
   480             decodeTableItems(_v.otherNCName);
   481         }
   483         if ((b2 & EncodingConstants.INITIAL_VOCABULARY_OTHER_URIS_FLAG) > 0) {
   484             decodeTableItems(_v.otherURI);
   485         }
   487         if ((b2 & EncodingConstants.INITIAL_VOCABULARY_ATTRIBUTE_VALUES_FLAG) > 0) {
   488             decodeTableItems(_v.attributeValue);
   489         }
   491         if ((b2 & EncodingConstants.INITIAL_VOCABULARY_CONTENT_CHARACTER_CHUNKS_FLAG) > 0) {
   492             decodeTableItems(_v.characterContentChunk);
   493         }
   495         if ((b2 & EncodingConstants.INITIAL_VOCABULARY_OTHER_STRINGS_FLAG) > 0) {
   496             decodeTableItems(_v.otherString);
   497         }
   499         if ((b2 & EncodingConstants.INITIAL_VOCABULARY_ELEMENT_NAME_SURROGATES_FLAG) > 0) {
   500             decodeTableItems(_v.elementName, false);
   501         }
   503         if ((b2 & EncodingConstants.INITIAL_VOCABULARY_ATTRIBUTE_NAME_SURROGATES_FLAG) > 0) {
   504             decodeTableItems(_v.attributeName, true);
   505         }
   506     }
   508     private void decodeExternalVocabularyURI() throws FastInfosetException, IOException {
   509         if (_externalVocabularies == null) {
   510             throw new IOException(CommonResourceBundle.
   511                     getInstance().getString("message.noExternalVocabularies"));
   512         }
   514         String externalVocabularyURI =
   515                 decodeNonEmptyOctetStringOnSecondBitAsUtf8String();
   517         Object o = _externalVocabularies.get(externalVocabularyURI);
   518         if (o instanceof ParserVocabulary) {
   519             _v.setReferencedVocabulary(externalVocabularyURI,
   520                     (ParserVocabulary)o, false);
   521         } else if (o instanceof com.sun.xml.internal.org.jvnet.fastinfoset.ExternalVocabulary) {
   522             com.sun.xml.internal.org.jvnet.fastinfoset.ExternalVocabulary v =
   523                     (com.sun.xml.internal.org.jvnet.fastinfoset.ExternalVocabulary)o;
   524             ParserVocabulary pv = new ParserVocabulary(v.vocabulary);
   526             _externalVocabularies.put(externalVocabularyURI, pv);
   527             _v.setReferencedVocabulary(externalVocabularyURI,
   528                     pv, false);
   529         } else {
   530             throw new FastInfosetException(CommonResourceBundle.getInstance().
   531                     getString("message.externalVocabularyNotRegistered",
   532                     new Object[]{externalVocabularyURI}));
   533         }
   534     }
   536     private void decodeTableItems(StringArray array) throws FastInfosetException, IOException {
   537         final int noOfItems = decodeNumberOfItemsOfSequence();
   539         for (int i = 0; i < noOfItems; i++) {
   540             array.add(decodeNonEmptyOctetStringOnSecondBitAsUtf8String());
   541         }
   542     }
   544     private void decodeTableItems(PrefixArray array) throws FastInfosetException, IOException {
   545         final int noOfItems = decodeNumberOfItemsOfSequence();
   547         for (int i = 0; i < noOfItems; i++) {
   548             array.add(decodeNonEmptyOctetStringOnSecondBitAsUtf8String());
   549         }
   550     }
   552     private void decodeTableItems(ContiguousCharArrayArray array) throws FastInfosetException, IOException {
   553         final int noOfItems = decodeNumberOfItemsOfSequence();
   555         for (int i = 0; i < noOfItems; i++) {
   556             switch(decodeNonIdentifyingStringOnFirstBit()) {
   557                 case NISTRING_STRING:
   558                     array.add(_charBuffer, _charBufferLength);
   559                     break;
   560                 default:
   561                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.illegalState"));
   562             }
   563         }
   564     }
   566     private void decodeTableItems(CharArrayArray array) throws FastInfosetException, IOException {
   567         final int noOfItems = decodeNumberOfItemsOfSequence();
   569         for (int i = 0; i < noOfItems; i++) {
   570             switch(decodeNonIdentifyingStringOnFirstBit()) {
   571                 case NISTRING_STRING:
   572                     array.add(new CharArray(_charBuffer, 0, _charBufferLength, true));
   573                     break;
   574                 default:
   575                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.illegalState"));
   576             }
   577         }
   578     }
   580     private void decodeTableItems(QualifiedNameArray array, boolean isAttribute) throws FastInfosetException, IOException {
   581         final int noOfItems = decodeNumberOfItemsOfSequence();
   583         for (int i = 0; i < noOfItems; i++) {
   584             final int b = read();
   586             String prefix = "";
   587             int prefixIndex = -1;
   588             if ((b & EncodingConstants.NAME_SURROGATE_PREFIX_FLAG) > 0) {
   589                 prefixIndex = decodeIntegerIndexOnSecondBit();
   590                 prefix = _v.prefix.get(prefixIndex);
   591             }
   593             String namespaceName = "";
   594             int namespaceNameIndex = -1;
   595             if ((b & EncodingConstants.NAME_SURROGATE_NAME_FLAG) > 0) {
   596                 namespaceNameIndex = decodeIntegerIndexOnSecondBit();
   597                 namespaceName = _v.namespaceName.get(namespaceNameIndex);
   598             }
   600             if (namespaceName == "" && prefix != "") {
   601                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.missingNamespace"));
   602             }
   604             final int localNameIndex = decodeIntegerIndexOnSecondBit();
   605             final String localName = _v.localName.get(localNameIndex);
   607             QualifiedName qualifiedName = new QualifiedName(prefix, namespaceName, localName,
   608                     prefixIndex, namespaceNameIndex, localNameIndex,
   609                     _charBuffer);
   610             if (isAttribute) {
   611                 qualifiedName.createAttributeValues(DuplicateAttributeVerifier.MAP_SIZE);
   612             }
   613             array.add(qualifiedName);
   614         }
   615     }
   617     private int decodeNumberOfItemsOfSequence() throws IOException {
   618         final int b = read();
   619         if (b < 128) {
   620             return b + 1;
   621         } else {
   622             return (((b & 0x0F) << 16) | (read() << 8) | read()) + 129;
   623         }
   624     }
   626     protected final void decodeNotations() throws FastInfosetException, IOException {
   627         if (_notations == null) {
   628             _notations = new ArrayList();
   629         } else {
   630             _notations.clear();
   631         }
   633         int b = read();
   634         while ((b & EncodingConstants.NOTATIONS_MASK) == EncodingConstants.NOTATIONS) {
   635             String name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
   637             String system_identifier = ((_b & EncodingConstants.NOTATIONS_SYSTEM_IDENTIFIER_FLAG) > 0)
   638             ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
   639             String public_identifier = ((_b & EncodingConstants.NOTATIONS_PUBLIC_IDENTIFIER_FLAG) > 0)
   640             ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
   642             Notation notation = new Notation(name, system_identifier, public_identifier);
   643             _notations.add(notation);
   645             b = read();
   646         }
   647         if (b != EncodingConstants.TERMINATOR) {
   648             throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IIsNotTerminatedCorrectly"));
   649         }
   650     }
   652     protected final void decodeUnparsedEntities() throws FastInfosetException, IOException {
   653         if (_unparsedEntities == null) {
   654             _unparsedEntities = new ArrayList();
   655         } else {
   656             _unparsedEntities.clear();
   657         }
   659         int b = read();
   660         while ((b & EncodingConstants.UNPARSED_ENTITIES_MASK) == EncodingConstants.UNPARSED_ENTITIES) {
   661             String name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
   662             String system_identifier = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI);
   664             String public_identifier = ((_b & EncodingConstants.UNPARSED_ENTITIES_PUBLIC_IDENTIFIER_FLAG) > 0)
   665             ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
   667             String notation_name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
   669             UnparsedEntity unparsedEntity = new UnparsedEntity(name, system_identifier, public_identifier, notation_name);
   670             _unparsedEntities.add(unparsedEntity);
   672             b = read();
   673         }
   674         if (b != EncodingConstants.TERMINATOR) {
   675             throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.unparsedEntities"));
   676         }
   677     }
   679     protected final String decodeCharacterEncodingScheme() throws FastInfosetException, IOException {
   680         return decodeNonEmptyOctetStringOnSecondBitAsUtf8String();
   681     }
   683     protected final String decodeVersion() throws FastInfosetException, IOException {
   684         switch(decodeNonIdentifyingStringOnFirstBit()) {
   685             case NISTRING_STRING:
   686                 final String data = new String(_charBuffer, 0, _charBufferLength);
   687                 if (_addToTable) {
   688                     _v.otherString.add(new CharArrayString(data));
   689                 }
   690                 return data;
   691             case NISTRING_ENCODING_ALGORITHM:
   692                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingNotSupported"));
   693             case NISTRING_INDEX:
   694                 return _v.otherString.get(_integer).toString();
   695             case NISTRING_EMPTY_STRING:
   696             default:
   697                 return "";
   698         }
   699     }
   701     protected final QualifiedName decodeEIIIndexMedium() throws FastInfosetException, IOException {
   702         final int i = (((_b & EncodingConstants.INTEGER_3RD_BIT_MEDIUM_MASK) << 8) | read())
   703         + EncodingConstants.INTEGER_3RD_BIT_SMALL_LIMIT;
   704         return _v.elementName._array[i];
   705     }
   707     protected final QualifiedName decodeEIIIndexLarge() throws FastInfosetException, IOException {
   708         int i;
   709         if ((_b & EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_FLAG) == 0x20) {
   710             // EII large index
   711             i = (((_b & EncodingConstants.INTEGER_3RD_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
   712             + EncodingConstants.INTEGER_3RD_BIT_MEDIUM_LIMIT;
   713         } else {
   714             // EII large large index
   715             i = (((read() & EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_MASK) << 16) | (read() << 8) | read())
   716             + EncodingConstants.INTEGER_3RD_BIT_LARGE_LIMIT;
   717         }
   718         return _v.elementName._array[i];
   719     }
   721     protected final QualifiedName decodeLiteralQualifiedName(int state, QualifiedName q)
   722     throws FastInfosetException, IOException {
   723         if (q == null) q = new QualifiedName();
   724         switch (state) {
   725             // no prefix, no namespace
   726             case 0:
   727                 return q.set(
   728                         "",
   729                         "",
   730                         decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
   731                         -1,
   732                         -1,
   733                         _identifier,
   734                         null);
   735                 // no prefix, namespace
   736             case 1:
   737                 return q.set(
   738                         "",
   739                         decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(false),
   740                         decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
   741                         -1,
   742                         _namespaceNameIndex,
   743                         _identifier,
   744                         null);
   745                 // prefix, no namespace
   746             case 2:
   747                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.qNameMissingNamespaceName"));
   748                 // prefix, namespace
   749             case 3:
   750                 return q.set(
   751                         decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(true),
   752                         decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(true),
   753                         decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
   754                         _prefixIndex,
   755                         _namespaceNameIndex,
   756                         _identifier,
   757                         _charBuffer);
   758             default:
   759                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingEII"));
   760         }
   761     }
   763     protected static final int NISTRING_STRING              = 0;
   764     protected static final int NISTRING_INDEX               = 1;
   765     protected static final int NISTRING_ENCODING_ALGORITHM  = 2;
   766     protected static final int NISTRING_EMPTY_STRING        = 3;
   768     /*
   769      * C.14
   770      * decodeNonIdentifyingStringOnFirstBit
   771      */
   772     protected final int decodeNonIdentifyingStringOnFirstBit() throws FastInfosetException, IOException {
   773         final int b = read();
   774         switch(DecoderStateTables.NISTRING(b)) {
   775             case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH:
   776                 _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
   777                 _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
   778                 decodeUtf8StringAsCharBuffer();
   779                 return NISTRING_STRING;
   780             case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH:
   781                 _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
   782                 _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
   783                 decodeUtf8StringAsCharBuffer();
   784                 return NISTRING_STRING;
   785             case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH:
   786             {
   787                 _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
   788                 final int length = (read() << 24) |
   789                         (read() << 16) |
   790                         (read() << 8) |
   791                         read();
   792                 _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
   793                 decodeUtf8StringAsCharBuffer();
   794                 return NISTRING_STRING;
   795             }
   796             case DecoderStateTables.NISTRING_UTF16_SMALL_LENGTH:
   797                 _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
   798                 _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
   799                 decodeUtf16StringAsCharBuffer();
   800                 return NISTRING_STRING;
   801             case DecoderStateTables.NISTRING_UTF16_MEDIUM_LENGTH:
   802                 _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
   803                 _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
   804                 decodeUtf16StringAsCharBuffer();
   805                 return NISTRING_STRING;
   806             case DecoderStateTables.NISTRING_UTF16_LARGE_LENGTH:
   807             {
   808                 _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
   809                 final int length = (read() << 24) |
   810                         (read() << 16) |
   811                         (read() << 8) |
   812                         read();
   813                 _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
   814                 decodeUtf16StringAsCharBuffer();
   815                 return NISTRING_STRING;
   816             }
   817             case DecoderStateTables.NISTRING_RA:
   818             {
   819                 _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
   820                 // Decode resitricted alphabet integer
   821                 _identifier = (b & 0x0F) << 4;
   822                 final int b2 = read();
   823                 _identifier |= (b2 & 0xF0) >> 4;
   825                 decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b2);
   827                 decodeRestrictedAlphabetAsCharBuffer();
   828                 return NISTRING_STRING;
   829             }
   830             case DecoderStateTables.NISTRING_EA:
   831             {
   832                 _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
   833                 // Decode encoding algorithm integer
   834                 _identifier = (b & 0x0F) << 4;
   835                 final int b2 = read();
   836                 _identifier |= (b2 & 0xF0) >> 4;
   838                 decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b2);
   839                 return NISTRING_ENCODING_ALGORITHM;
   840             }
   841             case DecoderStateTables.NISTRING_INDEX_SMALL:
   842                 _integer = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK;
   843                 return NISTRING_INDEX;
   844             case DecoderStateTables.NISTRING_INDEX_MEDIUM:
   845                 _integer = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
   846                 + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
   847                 return NISTRING_INDEX;
   848             case DecoderStateTables.NISTRING_INDEX_LARGE:
   849                 _integer = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
   850                 + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
   851                 return NISTRING_INDEX;
   852             case DecoderStateTables.NISTRING_EMPTY:
   853                 return NISTRING_EMPTY_STRING;
   854             default:
   855                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingNonIdentifyingString"));
   856         }
   857     }
   859     protected final void decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(int b) throws FastInfosetException, IOException {
   860         // Remove top 4 bits of restricted alphabet or encoding algorithm integer
   861         b &= 0x0F;
   862         // Reuse UTF8 length states
   863         switch(DecoderStateTables.NISTRING(b)) {
   864             case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH:
   865                 _octetBufferLength = b + 1;
   866                 break;
   867             case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH:
   868                 _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
   869                 break;
   870             case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH:
   871                 final int length = (read() << 24) |
   872                         (read() << 16) |
   873                         (read() << 8) |
   874                         read();
   875                 _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
   876                 break;
   877             default:
   878                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingOctets"));
   879         }
   880         ensureOctetBufferSize();
   881         _octetBufferStart = _octetBufferOffset;
   882         _octetBufferOffset += _octetBufferLength;
   883     }
   885     protected final void decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(int b) throws FastInfosetException, IOException {
   886         // Remove top 6 bits of restricted alphabet or encoding algorithm integer
   887         switch (b & 0x03) {
   888             // Small length
   889             case 0:
   890                 _octetBufferLength = 1;
   891                 break;
   892                 // Small length
   893             case 1:
   894                 _octetBufferLength = 2;
   895                 break;
   896                 // Medium length
   897             case 2:
   898                 _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
   899                 break;
   900                 // Large length
   901             case 3:
   902                 _octetBufferLength = (read() << 24) |
   903                         (read() << 16) |
   904                         (read() << 8) |
   905                         read();
   906                 _octetBufferLength += EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
   907                 break;
   908         }
   910         ensureOctetBufferSize();
   911         _octetBufferStart = _octetBufferOffset;
   912         _octetBufferOffset += _octetBufferLength;
   913     }
   915     /*
   916      * C.13
   917      */
   918     protected final String decodeIdentifyingNonEmptyStringOnFirstBit(StringArray table) throws FastInfosetException, IOException {
   919         final int b = read();
   920         switch(DecoderStateTables.ISTRING(b)) {
   921             case DecoderStateTables.ISTRING_SMALL_LENGTH:
   922             {
   923                 _octetBufferLength = b + 1;
   924                 final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString();
   925                 _identifier = table.add(s) - 1;
   926                 return s;
   927             }
   928             case DecoderStateTables.ISTRING_MEDIUM_LENGTH:
   929             {
   930                 _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT;
   931                 final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString();
   932                 _identifier = table.add(s) - 1;
   933                 return s;
   934             }
   935             case DecoderStateTables.ISTRING_LARGE_LENGTH:
   936             {
   937                 final int length = (read() << 24) |
   938                         (read() << 16) |
   939                         (read() << 8) |
   940                         read();
   941                 _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT;
   942                 final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString();
   943                 _identifier = table.add(s) - 1;
   944                 return s;
   945             }
   946             case DecoderStateTables.ISTRING_INDEX_SMALL:
   947                 _identifier = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK;
   948                 return table._array[_identifier];
   949             case DecoderStateTables.ISTRING_INDEX_MEDIUM:
   950                 _identifier = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
   951                 + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
   952                 return table._array[_identifier];
   953             case DecoderStateTables.ISTRING_INDEX_LARGE:
   954                 _identifier = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
   955                 + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
   956                 return table._array[_identifier];
   957             default:
   958                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingIdentifyingString"));
   959         }
   960     }
   962     protected int _prefixIndex;
   964     /*
   965      * C.13
   966      */
   967     protected final String decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(boolean namespaceNamePresent) throws FastInfosetException, IOException {
   968         final int b = read();
   969         switch(DecoderStateTables.ISTRING_PREFIX_NAMESPACE(b)) {
   970             case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_3:
   971             {
   972                 _octetBufferLength = EncodingConstants.XML_NAMESPACE_PREFIX_LENGTH;
   973                 decodeUtf8StringAsCharBuffer();
   975                 if (_charBuffer[0] == 'x' &&
   976                         _charBuffer[1] == 'm' &&
   977                         _charBuffer[2] == 'l') {
   978                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.prefixIllegal"));
   979                 }
   981                 final String s = (_stringInterning) ? new String(_charBuffer, 0, _charBufferLength).intern() :
   982                     new String(_charBuffer, 0, _charBufferLength);
   983                 _prefixIndex = _v.prefix.add(s);
   984                 return s;
   985             }
   986             case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_5:
   987             {
   988                 _octetBufferLength = EncodingConstants.XMLNS_NAMESPACE_PREFIX_LENGTH;
   989                 decodeUtf8StringAsCharBuffer();
   991                 if (_charBuffer[0] == 'x' &&
   992                         _charBuffer[1] == 'm' &&
   993                         _charBuffer[2] == 'l' &&
   994                         _charBuffer[3] == 'n' &&
   995                         _charBuffer[4] == 's') {
   996                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.xmlns"));
   997                 }
   999                 final String s = (_stringInterning) ? new String(_charBuffer, 0, _charBufferLength).intern() :
  1000                     new String(_charBuffer, 0, _charBufferLength);
  1001                 _prefixIndex = _v.prefix.add(s);
  1002                 return s;
  1004             case DecoderStateTables.ISTRING_SMALL_LENGTH:
  1005             case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_29:
  1006             case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_36:
  1008                 _octetBufferLength = b + 1;
  1009                 final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString();
  1010                 _prefixIndex = _v.prefix.add(s);
  1011                 return s;
  1013             case DecoderStateTables.ISTRING_MEDIUM_LENGTH:
  1015                 _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT;
  1016                 final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString();
  1017                 _prefixIndex = _v.prefix.add(s);
  1018                 return s;
  1020             case DecoderStateTables.ISTRING_LARGE_LENGTH:
  1022                 final int length = (read() << 24) |
  1023                         (read() << 16) |
  1024                         (read() << 8) |
  1025                         read();
  1026                 _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT;
  1027                 final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString();
  1028                 _prefixIndex = _v.prefix.add(s);
  1029                 return s;
  1031             case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO:
  1032                 if (namespaceNamePresent) {
  1033                     _prefixIndex = 0;
  1034                     // Peak at next byte and check the index of the XML namespace name
  1035                     if (DecoderStateTables.ISTRING_PREFIX_NAMESPACE(peek())
  1036                             != DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO) {
  1037                         throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.wrongNamespaceName"));
  1039                     return EncodingConstants.XML_NAMESPACE_PREFIX;
  1040                 } else {
  1041                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.missingNamespaceName"));
  1043             case DecoderStateTables.ISTRING_INDEX_SMALL:
  1044                 _prefixIndex = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK;
  1045                 return _v.prefix._array[_prefixIndex - 1];
  1046             case DecoderStateTables.ISTRING_INDEX_MEDIUM:
  1047                 _prefixIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
  1048                 + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
  1049                 return _v.prefix._array[_prefixIndex - 1];
  1050             case DecoderStateTables.ISTRING_INDEX_LARGE:
  1051                 _prefixIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
  1052                 + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
  1053                 return _v.prefix._array[_prefixIndex - 1];
  1054             default:
  1055                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingIdentifyingStringForPrefix"));
  1059     /*
  1060      * C.13
  1061      */
  1062     protected final String decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(boolean namespaceNamePresent) throws FastInfosetException, IOException {
  1063         final int b = read();
  1064         switch(DecoderStateTables.ISTRING_PREFIX_NAMESPACE(b)) {
  1065             case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO:
  1066                 if (namespaceNamePresent) {
  1067                     _prefixIndex = 0;
  1068                     // Peak at next byte and check the index of the XML namespace name
  1069                     if (DecoderStateTables.ISTRING_PREFIX_NAMESPACE(peek())
  1070                             != DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO) {
  1071                         throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.wrongNamespaceName"));
  1073                     return EncodingConstants.XML_NAMESPACE_PREFIX;
  1074                 } else {
  1075                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.missingNamespaceName"));
  1077             case DecoderStateTables.ISTRING_INDEX_SMALL:
  1078                 _prefixIndex = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK;
  1079                 return _v.prefix._array[_prefixIndex - 1];
  1080             case DecoderStateTables.ISTRING_INDEX_MEDIUM:
  1081                 _prefixIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
  1082                 + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
  1083                 return _v.prefix._array[_prefixIndex - 1];
  1084             case DecoderStateTables.ISTRING_INDEX_LARGE:
  1085                 _prefixIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
  1086                 + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
  1087                 return _v.prefix._array[_prefixIndex - 1];
  1088             default:
  1089                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingIdentifyingStringForPrefix"));
  1093     protected int _namespaceNameIndex;
  1095     /*
  1096      * C.13
  1097      */
  1098     protected final String decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(boolean prefixPresent) throws FastInfosetException, IOException {
  1099         final int b = read();
  1100         switch(DecoderStateTables.ISTRING_PREFIX_NAMESPACE(b)) {
  1101             case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_3:
  1102             case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_5:
  1103             case DecoderStateTables.ISTRING_SMALL_LENGTH:
  1105                 _octetBufferLength = b + 1;
  1106                 final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString();
  1107                 _namespaceNameIndex = _v.namespaceName.add(s);
  1108                 return s;
  1110             case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_29:
  1112                 _octetBufferLength = EncodingConstants.XMLNS_NAMESPACE_NAME_LENGTH;
  1113                 decodeUtf8StringAsCharBuffer();
  1115                 if (compareCharsWithCharBufferFromEndToStart(XMLNS_NAMESPACE_NAME_CHARS)) {
  1116                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.xmlnsConnotBeBoundToPrefix"));
  1119                 final String s = (_stringInterning) ? new String(_charBuffer, 0, _charBufferLength).intern() :
  1120                     new String(_charBuffer, 0, _charBufferLength);
  1121                 _namespaceNameIndex = _v.namespaceName.add(s);
  1122                 return s;
  1124             case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_36:
  1126                 _octetBufferLength = EncodingConstants.XML_NAMESPACE_NAME_LENGTH;
  1127                 decodeUtf8StringAsCharBuffer();
  1129                 if (compareCharsWithCharBufferFromEndToStart(XML_NAMESPACE_NAME_CHARS)) {
  1130                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.illegalNamespaceName"));
  1133                 final String s = (_stringInterning) ? new String(_charBuffer, 0, _charBufferLength).intern() :
  1134                     new String(_charBuffer, 0, _charBufferLength);
  1135                 _namespaceNameIndex = _v.namespaceName.add(s);
  1136                 return s;
  1138             case DecoderStateTables.ISTRING_MEDIUM_LENGTH:
  1140                 _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT;
  1141                 final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString();
  1142                 _namespaceNameIndex = _v.namespaceName.add(s);
  1143                 return s;
  1145             case DecoderStateTables.ISTRING_LARGE_LENGTH:
  1147                 final int length = (read() << 24) |
  1148                         (read() << 16) |
  1149                         (read() << 8) |
  1150                         read();
  1151                 _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT;
  1152                 final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString();
  1153                 _namespaceNameIndex = _v.namespaceName.add(s);
  1154                 return s;
  1156             case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO:
  1157                 if (prefixPresent) {
  1158                     _namespaceNameIndex = 0;
  1159                     return EncodingConstants.XML_NAMESPACE_NAME;
  1160                 } else {
  1161                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.namespaceWithoutPrefix"));
  1163             case DecoderStateTables.ISTRING_INDEX_SMALL:
  1164                 _namespaceNameIndex = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK;
  1165                 return _v.namespaceName._array[_namespaceNameIndex - 1];
  1166             case DecoderStateTables.ISTRING_INDEX_MEDIUM:
  1167                 _namespaceNameIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
  1168                 + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
  1169                 return _v.namespaceName._array[_namespaceNameIndex - 1];
  1170             case DecoderStateTables.ISTRING_INDEX_LARGE:
  1171                 _namespaceNameIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
  1172                 + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
  1173                 return _v.namespaceName._array[_namespaceNameIndex - 1];
  1174             default:
  1175                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingForNamespaceName"));
  1179     /*
  1180      * C.13
  1181      */
  1182     protected final String decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(boolean prefixPresent) throws FastInfosetException, IOException {
  1183         final int b = read();
  1184         switch(DecoderStateTables.ISTRING_PREFIX_NAMESPACE(b)) {
  1185             case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO:
  1186                 if (prefixPresent) {
  1187                     _namespaceNameIndex = 0;
  1188                     return EncodingConstants.XML_NAMESPACE_NAME;
  1189                 } else {
  1190                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.namespaceWithoutPrefix"));
  1192             case DecoderStateTables.ISTRING_INDEX_SMALL:
  1193                 _namespaceNameIndex = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK;
  1194                 return _v.namespaceName._array[_namespaceNameIndex - 1];
  1195             case DecoderStateTables.ISTRING_INDEX_MEDIUM:
  1196                 _namespaceNameIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
  1197                 + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
  1198                 return _v.namespaceName._array[_namespaceNameIndex - 1];
  1199             case DecoderStateTables.ISTRING_INDEX_LARGE:
  1200                 _namespaceNameIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
  1201                 + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
  1202                 return _v.namespaceName._array[_namespaceNameIndex - 1];
  1203             default:
  1204                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingForNamespaceName"));
  1208     private boolean compareCharsWithCharBufferFromEndToStart(char[] c) {
  1209         int i = _charBufferLength ;
  1210         while (--i >= 0) {
  1211             if (c[i] != _charBuffer[i]) {
  1212                 return false;
  1215         return true;
  1218     /*
  1219      * C.22
  1220      */
  1221     protected final String decodeNonEmptyOctetStringOnSecondBitAsUtf8String() throws FastInfosetException, IOException {
  1222         decodeNonEmptyOctetStringOnSecondBitAsUtf8CharArray();
  1223         return new String(_charBuffer, 0, _charBufferLength);
  1226     /*
  1227      * C.22
  1228      */
  1229     protected final void decodeNonEmptyOctetStringOnSecondBitAsUtf8CharArray() throws FastInfosetException, IOException {
  1230         decodeNonEmptyOctetStringLengthOnSecondBit();
  1231         decodeUtf8StringAsCharBuffer();
  1234     /*
  1235      * C.22
  1236      */
  1237     protected final void decodeNonEmptyOctetStringLengthOnSecondBit() throws FastInfosetException, IOException {
  1238         final int b = read();
  1239         switch(DecoderStateTables.ISTRING(b)) {
  1240             case DecoderStateTables.ISTRING_SMALL_LENGTH:
  1241                 _octetBufferLength = b + 1;
  1242                 break;
  1243             case DecoderStateTables.ISTRING_MEDIUM_LENGTH:
  1244                 _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT;
  1245                 break;
  1246             case DecoderStateTables.ISTRING_LARGE_LENGTH:
  1248                 final int length = (read() << 24) |
  1249                         (read() << 16) |
  1250                         (read() << 8) |
  1251                         read();
  1252                 _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT;
  1253                 break;
  1255             case DecoderStateTables.ISTRING_INDEX_SMALL:
  1256             case DecoderStateTables.ISTRING_INDEX_MEDIUM:
  1257             case DecoderStateTables.ISTRING_INDEX_LARGE:
  1258             default:
  1259                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingNonEmptyOctet"));
  1263     /*
  1264      * C.25
  1265      */
  1266     protected final int decodeIntegerIndexOnSecondBit() throws FastInfosetException, IOException {
  1267         final int b = read() | 0x80;
  1268         switch(DecoderStateTables.ISTRING(b)) {
  1269             case DecoderStateTables.ISTRING_INDEX_SMALL:
  1270                 return b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK;
  1271             case DecoderStateTables.ISTRING_INDEX_MEDIUM:
  1272                 return (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
  1273                 + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
  1274             case DecoderStateTables.ISTRING_INDEX_LARGE:
  1275                 return (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
  1276                 + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
  1277             case DecoderStateTables.ISTRING_SMALL_LENGTH:
  1278             case DecoderStateTables.ISTRING_MEDIUM_LENGTH:
  1279             case DecoderStateTables.ISTRING_LARGE_LENGTH:
  1280             default:
  1281                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingIndexOnSecondBit"));
  1285     protected final void decodeHeader() throws FastInfosetException, IOException {
  1286         if (!_isFastInfosetDocument()) {
  1287             throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.notFIDocument"));
  1291     protected final void decodeRestrictedAlphabetAsCharBuffer() throws FastInfosetException, IOException {
  1292         if (_identifier <= EncodingConstants.RESTRICTED_ALPHABET_BUILTIN_END) {
  1293             decodeFourBitAlphabetOctetsAsCharBuffer(BuiltInRestrictedAlphabets.table[_identifier]);
  1294             // decodeAlphabetOctetsAsCharBuffer(BuiltInRestrictedAlphabets.table[_identifier]);
  1295         } else if (_identifier >= EncodingConstants.RESTRICTED_ALPHABET_APPLICATION_START) {
  1296             CharArray ca = _v.restrictedAlphabet.get(_identifier - EncodingConstants.RESTRICTED_ALPHABET_APPLICATION_START);
  1297             if (ca == null) {
  1298                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.alphabetNotPresent", new Object[]{Integer.valueOf(_identifier)}));
  1300             decodeAlphabetOctetsAsCharBuffer(ca.ch);
  1301         } else {
  1302             // Reserved built-in algorithms for future use
  1303             // TODO should use sax property to decide if event will be
  1304             // reported, allows for support through handler if required.
  1305             throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.alphabetIdentifiersReserved"));
  1309     protected final String decodeRestrictedAlphabetAsString() throws FastInfosetException, IOException {
  1310         decodeRestrictedAlphabetAsCharBuffer();
  1311         return new String(_charBuffer, 0, _charBufferLength);
  1314     protected final String decodeRAOctetsAsString(char[] restrictedAlphabet) throws FastInfosetException, IOException {
  1315         decodeAlphabetOctetsAsCharBuffer(restrictedAlphabet);
  1316         return new String(_charBuffer, 0, _charBufferLength);
  1319     protected final void decodeFourBitAlphabetOctetsAsCharBuffer(char[] restrictedAlphabet) throws FastInfosetException, IOException {
  1320         _charBufferLength = 0;
  1321         final int characters = _octetBufferLength * 2;
  1322         if (_charBuffer.length < characters) {
  1323             _charBuffer = new char[characters];
  1326         int v = 0;
  1327         for (int i = 0; i < _octetBufferLength - 1; i++) {
  1328             v = _octetBuffer[_octetBufferStart++] & 0xFF;
  1329             _charBuffer[_charBufferLength++] = restrictedAlphabet[v >> 4];
  1330             _charBuffer[_charBufferLength++] = restrictedAlphabet[v & 0x0F];
  1332         v = _octetBuffer[_octetBufferStart++] & 0xFF;
  1333         _charBuffer[_charBufferLength++] = restrictedAlphabet[v >> 4];
  1334         v &= 0x0F;
  1335         if (v != 0x0F) {
  1336             _charBuffer[_charBufferLength++] = restrictedAlphabet[v & 0x0F];
  1340     protected final void decodeAlphabetOctetsAsCharBuffer(char[] restrictedAlphabet) throws FastInfosetException, IOException {
  1341         if (restrictedAlphabet.length < 2) {
  1342             throw new IllegalArgumentException(CommonResourceBundle.getInstance().getString("message.alphabetMustContain2orMoreChars"));
  1345         int bitsPerCharacter = 1;
  1346         while ((1 << bitsPerCharacter) <= restrictedAlphabet.length) {
  1347             bitsPerCharacter++;
  1349         final int terminatingValue = (1 << bitsPerCharacter) - 1;
  1351         int characters = (_octetBufferLength << 3) / bitsPerCharacter;
  1352         if (characters == 0) {
  1353             throw new IOException("");
  1356         _charBufferLength = 0;
  1357         if (_charBuffer.length < characters) {
  1358             _charBuffer = new char[characters];
  1361         resetBits();
  1362         for (int i = 0; i < characters; i++) {
  1363             int value = readBits(bitsPerCharacter);
  1364             if (bitsPerCharacter < 8 && value == terminatingValue) {
  1365                 int octetPosition = (i * bitsPerCharacter) >>> 3;
  1366                 if (octetPosition != _octetBufferLength - 1) {
  1367                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.alphabetIncorrectlyTerminated"));
  1369                 break;
  1371             _charBuffer[_charBufferLength++] = restrictedAlphabet[value];
  1375     private int _bitsLeftInOctet;
  1377     private void resetBits() {
  1378         _bitsLeftInOctet = 0;
  1381     private int readBits(int bits) throws IOException {
  1382         int value = 0;
  1383         while (bits > 0) {
  1384             if (_bitsLeftInOctet == 0) {
  1385                 _b = _octetBuffer[_octetBufferStart++] & 0xFF;
  1386                 _bitsLeftInOctet = 8;
  1388             int bit = ((_b & (1 << --_bitsLeftInOctet)) > 0) ? 1 : 0;
  1389             value |= (bit << --bits);
  1392         return value;
  1395     protected final void decodeUtf8StringAsCharBuffer() throws IOException {
  1396         ensureOctetBufferSize();
  1397         decodeUtf8StringIntoCharBuffer();
  1400     protected final void decodeUtf8StringAsCharBuffer(char[] ch, int offset) throws IOException {
  1401         ensureOctetBufferSize();
  1402         decodeUtf8StringIntoCharBuffer(ch, offset);
  1405     protected final String decodeUtf8StringAsString() throws IOException {
  1406         decodeUtf8StringAsCharBuffer();
  1407         return new String(_charBuffer, 0, _charBufferLength);
  1410     protected final void decodeUtf16StringAsCharBuffer() throws IOException {
  1411         ensureOctetBufferSize();
  1412         decodeUtf16StringIntoCharBuffer();
  1415     protected final String decodeUtf16StringAsString() throws IOException {
  1416         decodeUtf16StringAsCharBuffer();
  1417         return new String(_charBuffer, 0, _charBufferLength);
  1420     private void ensureOctetBufferSize() throws IOException {
  1421         if (_octetBufferEnd < (_octetBufferOffset + _octetBufferLength)) {
  1422             final int octetsInBuffer = _octetBufferEnd - _octetBufferOffset;
  1424             if (_octetBuffer.length < _octetBufferLength) {
  1425                 // Length to read is too large, resize the buffer
  1426                 byte[] newOctetBuffer = new byte[_octetBufferLength];
  1427                 // Move partially read octets to the start of the buffer
  1428                 System.arraycopy(_octetBuffer, _octetBufferOffset, newOctetBuffer, 0, octetsInBuffer);
  1429                 _octetBuffer = newOctetBuffer;
  1430             } else {
  1431                 // Move partially read octets to the start of the buffer
  1432                 System.arraycopy(_octetBuffer, _octetBufferOffset, _octetBuffer, 0, octetsInBuffer);
  1434             _octetBufferOffset = 0;
  1436             // Read as many octets as possible to fill the buffer
  1437             final int octetsRead = _s.read(_octetBuffer, octetsInBuffer, _octetBuffer.length - octetsInBuffer);
  1438             if (octetsRead < 0) {
  1439                 throw new EOFException("Unexpeceted EOF");
  1441             _octetBufferEnd = octetsInBuffer + octetsRead;
  1443             // Check if the number of octets that have been read is not enough
  1444             // This can happen when underlying non-blocking is used to read
  1445             if (_octetBufferEnd < _octetBufferLength) {
  1446                 repeatedRead();
  1451     private void repeatedRead() throws IOException {
  1452         // Check if the number of octets that have been read is not enough
  1453         while (_octetBufferEnd < _octetBufferLength) {
  1454             // Read as many octets as possible to fill the buffer
  1455             final int octetsRead = _s.read(_octetBuffer, _octetBufferEnd, _octetBuffer.length - _octetBufferEnd);
  1456             if (octetsRead < 0) {
  1457                 throw new EOFException("Unexpeceted EOF");
  1459             _octetBufferEnd += octetsRead;
  1463     protected final void decodeUtf8StringIntoCharBuffer() throws IOException {
  1464         if (_charBuffer.length < _octetBufferLength) {
  1465             _charBuffer = new char[_octetBufferLength];
  1468         _charBufferLength = 0;
  1469         final int end = _octetBufferLength + _octetBufferOffset;
  1470         int b1;
  1471         while (end != _octetBufferOffset) {
  1472             b1 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1473             if (DecoderStateTables.UTF8(b1) == DecoderStateTables.UTF8_ONE_BYTE) {
  1474                 _charBuffer[_charBufferLength++] = (char) b1;
  1475             } else {
  1476                 decodeTwoToFourByteUtf8Character(b1, end);
  1481     protected final void decodeUtf8StringIntoCharBuffer(char[] ch, int offset) throws IOException {
  1482         _charBufferLength = offset;
  1483         final int end = _octetBufferLength + _octetBufferOffset;
  1484         int b1;
  1485         while (end != _octetBufferOffset) {
  1486             b1 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1487             if (DecoderStateTables.UTF8(b1) == DecoderStateTables.UTF8_ONE_BYTE) {
  1488                 ch[_charBufferLength++] = (char) b1;
  1489             } else {
  1490                 decodeTwoToFourByteUtf8Character(ch, b1, end);
  1493         _charBufferLength -= offset;
  1496     private void decodeTwoToFourByteUtf8Character(int b1, int end) throws IOException {
  1497         switch(DecoderStateTables.UTF8(b1)) {
  1498             case DecoderStateTables.UTF8_TWO_BYTES:
  1500                 // Decode byte 2
  1501                 if (end == _octetBufferOffset) {
  1502                     decodeUtf8StringLengthTooSmall();
  1504                 final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1505                 if ((b2 & 0xC0) != 0x80) {
  1506                     decodeUtf8StringIllegalState();
  1509                 // Character guaranteed to be in [0x20, 0xD7FF] range
  1510                 // since a character encoded in two bytes will be in the
  1511                 // range [0x80, 0x1FFF]
  1512                 _charBuffer[_charBufferLength++] = (char) (
  1513                         ((b1 & 0x1F) << 6)
  1514                         | (b2 & 0x3F));
  1515                 break;
  1517             case DecoderStateTables.UTF8_THREE_BYTES:
  1518                 final char c = decodeUtf8ThreeByteChar(end, b1);
  1519                 if (XMLChar.isContent(c)) {
  1520                     _charBuffer[_charBufferLength++] = c;
  1521                 } else {
  1522                     decodeUtf8StringIllegalState();
  1524                 break;
  1525             case DecoderStateTables.UTF8_FOUR_BYTES:
  1527                 final int supplemental = decodeUtf8FourByteChar(end, b1);
  1528                 if (XMLChar.isContent(supplemental)) {
  1529                     _charBuffer[_charBufferLength++] = _utf8_highSurrogate;
  1530                     _charBuffer[_charBufferLength++] = _utf8_lowSurrogate;
  1531                 } else {
  1532                     decodeUtf8StringIllegalState();
  1534                 break;
  1536             default:
  1537                 decodeUtf8StringIllegalState();
  1541     private void decodeTwoToFourByteUtf8Character(char ch[], int b1, int end) throws IOException {
  1542         switch(DecoderStateTables.UTF8(b1)) {
  1543             case DecoderStateTables.UTF8_TWO_BYTES:
  1545                 // Decode byte 2
  1546                 if (end == _octetBufferOffset) {
  1547                     decodeUtf8StringLengthTooSmall();
  1549                 final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1550                 if ((b2 & 0xC0) != 0x80) {
  1551                     decodeUtf8StringIllegalState();
  1554                 // Character guaranteed to be in [0x20, 0xD7FF] range
  1555                 // since a character encoded in two bytes will be in the
  1556                 // range [0x80, 0x1FFF]
  1557                 ch[_charBufferLength++] = (char) (
  1558                         ((b1 & 0x1F) << 6)
  1559                         | (b2 & 0x3F));
  1560                 break;
  1562             case DecoderStateTables.UTF8_THREE_BYTES:
  1563                 final char c = decodeUtf8ThreeByteChar(end, b1);
  1564                 if (XMLChar.isContent(c)) {
  1565                     ch[_charBufferLength++] = c;
  1566                 } else {
  1567                     decodeUtf8StringIllegalState();
  1569                 break;
  1570             case DecoderStateTables.UTF8_FOUR_BYTES:
  1572                 final int supplemental = decodeUtf8FourByteChar(end, b1);
  1573                 if (XMLChar.isContent(supplemental)) {
  1574                     ch[_charBufferLength++] = _utf8_highSurrogate;
  1575                     ch[_charBufferLength++] = _utf8_lowSurrogate;
  1576                 } else {
  1577                     decodeUtf8StringIllegalState();
  1579                 break;
  1581             default:
  1582                 decodeUtf8StringIllegalState();
  1586     protected final void decodeUtf8NCNameIntoCharBuffer() throws IOException {
  1587         _charBufferLength = 0;
  1588         if (_charBuffer.length < _octetBufferLength) {
  1589             _charBuffer = new char[_octetBufferLength];
  1592         final int end = _octetBufferLength + _octetBufferOffset;
  1594         int b1 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1595         if (DecoderStateTables.UTF8_NCNAME(b1) == DecoderStateTables.UTF8_NCNAME_NCNAME) {
  1596             _charBuffer[_charBufferLength++] = (char) b1;
  1597         } else {
  1598             decodeUtf8NCNameStartTwoToFourByteCharacters(b1, end);
  1601         while (end != _octetBufferOffset) {
  1602             b1 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1603             if (DecoderStateTables.UTF8_NCNAME(b1) < DecoderStateTables.UTF8_TWO_BYTES) {
  1604                 _charBuffer[_charBufferLength++] = (char) b1;
  1605             } else {
  1606                 decodeUtf8NCNameTwoToFourByteCharacters(b1, end);
  1611     private void decodeUtf8NCNameStartTwoToFourByteCharacters(int b1, int end) throws IOException {
  1612         switch(DecoderStateTables.UTF8_NCNAME(b1)) {
  1613             case DecoderStateTables.UTF8_TWO_BYTES:
  1615                 // Decode byte 2
  1616                 if (end == _octetBufferOffset) {
  1617                     decodeUtf8StringLengthTooSmall();
  1619                 final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1620                 if ((b2 & 0xC0) != 0x80) {
  1621                     decodeUtf8StringIllegalState();
  1624                 final char c = (char) (
  1625                         ((b1 & 0x1F) << 6)
  1626                         | (b2 & 0x3F));
  1627                 if (XMLChar.isNCNameStart(c)) {
  1628                     _charBuffer[_charBufferLength++] = c;
  1629                 } else {
  1630                     decodeUtf8NCNameIllegalState();
  1632                 break;
  1634             case DecoderStateTables.UTF8_THREE_BYTES:
  1635                 final char c = decodeUtf8ThreeByteChar(end, b1);
  1636                 if (XMLChar.isNCNameStart(c)) {
  1637                     _charBuffer[_charBufferLength++] = c;
  1638                 } else {
  1639                     decodeUtf8NCNameIllegalState();
  1641                 break;
  1642             case DecoderStateTables.UTF8_FOUR_BYTES:
  1644                 final int supplemental = decodeUtf8FourByteChar(end, b1);
  1645                 if (XMLChar.isNCNameStart(supplemental)) {
  1646                     _charBuffer[_charBufferLength++] = _utf8_highSurrogate;
  1647                     _charBuffer[_charBufferLength++] = _utf8_lowSurrogate;
  1648                 } else {
  1649                     decodeUtf8NCNameIllegalState();
  1651                 break;
  1653             case DecoderStateTables.UTF8_NCNAME_NCNAME_CHAR:
  1654             default:
  1655                 decodeUtf8NCNameIllegalState();
  1660     private void decodeUtf8NCNameTwoToFourByteCharacters(int b1, int end) throws IOException {
  1661         switch(DecoderStateTables.UTF8_NCNAME(b1)) {
  1662             case DecoderStateTables.UTF8_TWO_BYTES:
  1664                 // Decode byte 2
  1665                 if (end == _octetBufferOffset) {
  1666                     decodeUtf8StringLengthTooSmall();
  1668                 final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1669                 if ((b2 & 0xC0) != 0x80) {
  1670                     decodeUtf8StringIllegalState();
  1673                 final char c = (char) (
  1674                         ((b1 & 0x1F) << 6)
  1675                         | (b2 & 0x3F));
  1676                 if (XMLChar.isNCName(c)) {
  1677                     _charBuffer[_charBufferLength++] = c;
  1678                 } else {
  1679                     decodeUtf8NCNameIllegalState();
  1681                 break;
  1683             case DecoderStateTables.UTF8_THREE_BYTES:
  1684                 final char c = decodeUtf8ThreeByteChar(end, b1);
  1685                 if (XMLChar.isNCName(c)) {
  1686                     _charBuffer[_charBufferLength++] = c;
  1687                 } else {
  1688                     decodeUtf8NCNameIllegalState();
  1690                 break;
  1691             case DecoderStateTables.UTF8_FOUR_BYTES:
  1693                 final int supplemental = decodeUtf8FourByteChar(end, b1);
  1694                 if (XMLChar.isNCName(supplemental)) {
  1695                     _charBuffer[_charBufferLength++] = _utf8_highSurrogate;
  1696                     _charBuffer[_charBufferLength++] = _utf8_lowSurrogate;
  1697                 } else {
  1698                     decodeUtf8NCNameIllegalState();
  1700                 break;
  1702             default:
  1703                 decodeUtf8NCNameIllegalState();
  1707     private char decodeUtf8ThreeByteChar(int end, int b1) throws IOException {
  1708         // Decode byte 2
  1709         if (end == _octetBufferOffset) {
  1710             decodeUtf8StringLengthTooSmall();
  1712         final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1713         if ((b2 & 0xC0) != 0x80
  1714                 || (b1 == 0xED && b2 >= 0xA0)
  1715                 || ((b1 & 0x0F) == 0 && (b2 & 0x20) == 0)) {
  1716             decodeUtf8StringIllegalState();
  1719         // Decode byte 3
  1720         if (end == _octetBufferOffset) {
  1721             decodeUtf8StringLengthTooSmall();
  1723         final int b3 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1724         if ((b3 & 0xC0) != 0x80) {
  1725             decodeUtf8StringIllegalState();
  1728         return (char) (
  1729                 (b1 & 0x0F) << 12
  1730                 | (b2 & 0x3F) << 6
  1731                 | (b3 & 0x3F));
  1734     private char _utf8_highSurrogate;
  1735     private char _utf8_lowSurrogate;
  1737     private int decodeUtf8FourByteChar(int end, int b1) throws IOException {
  1738         // Decode byte 2
  1739         if (end == _octetBufferOffset) {
  1740             decodeUtf8StringLengthTooSmall();
  1742         final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1743         if ((b2 & 0xC0) != 0x80
  1744                 || ((b2 & 0x30) == 0 && (b1 & 0x07) == 0)) {
  1745             decodeUtf8StringIllegalState();
  1748         // Decode byte 3
  1749         if (end == _octetBufferOffset) {
  1750             decodeUtf8StringLengthTooSmall();
  1752         final int b3 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1753         if ((b3 & 0xC0) != 0x80) {
  1754             decodeUtf8StringIllegalState();
  1757         // Decode byte 4
  1758         if (end == _octetBufferOffset) {
  1759             decodeUtf8StringLengthTooSmall();
  1761         final int b4 = _octetBuffer[_octetBufferOffset++] & 0xFF;
  1762         if ((b4 & 0xC0) != 0x80) {
  1763             decodeUtf8StringIllegalState();
  1766         final int uuuuu = ((b1 << 2) & 0x001C) | ((b2 >> 4) & 0x0003);
  1767         if (uuuuu > 0x10) {
  1768             decodeUtf8StringIllegalState();
  1770         final int wwww = uuuuu - 1;
  1772         _utf8_highSurrogate = (char) (0xD800 |
  1773                 ((wwww << 6) & 0x03C0) | ((b2 << 2) & 0x003C) |
  1774                 ((b3 >> 4) & 0x0003));
  1775         _utf8_lowSurrogate = (char) (0xDC00 | ((b3 << 6) & 0x03C0) | (b4 & 0x003F));
  1777         return XMLChar.supplemental(_utf8_highSurrogate, _utf8_lowSurrogate);
  1780     private void decodeUtf8StringLengthTooSmall() throws IOException {
  1781         throw new IOException(CommonResourceBundle.getInstance().getString("message.deliminatorTooSmall"));
  1784     private void decodeUtf8StringIllegalState() throws IOException {
  1785         throw new IOException(CommonResourceBundle.getInstance().getString("message.UTF8Encoded"));
  1788     private void decodeUtf8NCNameIllegalState() throws IOException {
  1789         throw new IOException(CommonResourceBundle.getInstance().getString("message.UTF8EncodedNCName"));
  1792     private void decodeUtf16StringIntoCharBuffer() throws IOException {
  1793         _charBufferLength = _octetBufferLength / 2;
  1794         if (_charBuffer.length < _charBufferLength) {
  1795             _charBuffer = new char[_charBufferLength];
  1798         for (int i = 0; i < _charBufferLength; i++) {
  1799             final char c = (char)((read() << 8) | read());
  1800             // TODO check c is a valid Char character
  1801             _charBuffer[i] = c;
  1806     protected String createQualifiedNameString(String second) {
  1807         return createQualifiedNameString(XMLNS_NAMESPACE_PREFIX_CHARS, second);
  1810     protected String createQualifiedNameString(char[] first, String second) {
  1811         final int l1 = first.length;
  1812         final int l2 = second.length();
  1813         final int total = l1 + l2 + 1;
  1814         if (total < _charBuffer.length) {
  1815             System.arraycopy(first, 0, _charBuffer, 0, l1);
  1816             _charBuffer[l1] = ':';
  1817             second.getChars(0, l2, _charBuffer, l1 + 1);
  1818             return new String(_charBuffer, 0, total);
  1819         } else {
  1820             StringBuilder b = new StringBuilder(new String(first));
  1821             b.append(':');
  1822             b.append(second);
  1823             return b.toString();
  1827     protected final int read() throws IOException {
  1828         if (_octetBufferOffset < _octetBufferEnd) {
  1829             return _octetBuffer[_octetBufferOffset++] & 0xFF;
  1830         } else {
  1831             _octetBufferEnd = _s.read(_octetBuffer);
  1832             if (_octetBufferEnd < 0) {
  1833                 throw new EOFException(CommonResourceBundle.getInstance().getString("message.EOF"));
  1836             _octetBufferOffset = 1;
  1837             return _octetBuffer[0] & 0xFF;
  1841     protected final void closeIfRequired() throws IOException {
  1842         if (_s != null && _needForceStreamClose) {
  1843             _s.close();
  1847     protected final int peek() throws IOException {
  1848         return peek(null);
  1851     protected final int peek(OctetBufferListener octetBufferListener) throws IOException {
  1852         if (_octetBufferOffset < _octetBufferEnd) {
  1853             return _octetBuffer[_octetBufferOffset] & 0xFF;
  1854         } else {
  1855             if (octetBufferListener != null) {
  1856                 octetBufferListener.onBeforeOctetBufferOverwrite();
  1859             _octetBufferEnd = _s.read(_octetBuffer);
  1860             if (_octetBufferEnd < 0) {
  1861                 throw new EOFException(CommonResourceBundle.getInstance().getString("message.EOF"));
  1864             _octetBufferOffset = 0;
  1865             return _octetBuffer[0] & 0xFF;
  1869     protected final int peek2(OctetBufferListener octetBufferListener) throws IOException {
  1870         if (_octetBufferOffset + 1 < _octetBufferEnd) {
  1871             return _octetBuffer[_octetBufferOffset + 1] & 0xFF;
  1872         } else {
  1873             if (octetBufferListener != null) {
  1874                 octetBufferListener.onBeforeOctetBufferOverwrite();
  1877             int offset = 0;
  1878             if (_octetBufferOffset < _octetBufferEnd) {
  1879                 _octetBuffer[0] = _octetBuffer[_octetBufferOffset];
  1880                 offset = 1;
  1882             _octetBufferEnd = _s.read(_octetBuffer, offset, _octetBuffer.length - offset);
  1884             if (_octetBufferEnd < 0) {
  1885                 throw new EOFException(CommonResourceBundle.getInstance().getString("message.EOF"));
  1888             _octetBufferOffset = 0;
  1889             return _octetBuffer[1] & 0xFF;
  1893     protected class EncodingAlgorithmInputStream extends InputStream {
  1895         public int read() throws IOException {
  1896             if (_octetBufferStart < _octetBufferOffset) {
  1897                 return (_octetBuffer[_octetBufferStart++] & 0xFF);
  1898             } else {
  1899                 return -1;
  1903         @Override
  1904         public int read(byte b[]) throws IOException {
  1905             return read(b, 0, b.length);
  1908         @Override
  1909         public int read(byte b[], int off, int len) throws IOException {
  1910             if (b == null) {
  1911                 throw new NullPointerException();
  1912             } else if ((off < 0) || (off > b.length) || (len < 0) ||
  1913                     ((off + len) > b.length) || ((off + len) < 0)) {
  1914                 throw new IndexOutOfBoundsException();
  1915             } else if (len == 0) {
  1916                 return 0;
  1919             final int newOctetBufferStart = _octetBufferStart + len;
  1920             if (newOctetBufferStart < _octetBufferOffset) {
  1921                 System.arraycopy(_octetBuffer, _octetBufferStart, b, off, len);
  1922                 _octetBufferStart = newOctetBufferStart;
  1923                 return len;
  1924             } else if (_octetBufferStart < _octetBufferOffset) {
  1925                 final int bytesToRead = _octetBufferOffset - _octetBufferStart;
  1926                 System.arraycopy(_octetBuffer, _octetBufferStart, b, off, bytesToRead);
  1927                 _octetBufferStart += bytesToRead;
  1928                 return bytesToRead;
  1929             } else {
  1930                 return -1;
  1935     protected final boolean _isFastInfosetDocument() throws IOException {
  1936         // Fill up the octet buffer
  1937         peek();
  1939         _octetBufferLength = EncodingConstants.BINARY_HEADER.length;
  1940         ensureOctetBufferSize();
  1941         _octetBufferOffset += _octetBufferLength;
  1943         // Check for binary header
  1944         if (_octetBuffer[0] != EncodingConstants.BINARY_HEADER[0] ||
  1945                 _octetBuffer[1] != EncodingConstants.BINARY_HEADER[1] ||
  1946                 _octetBuffer[2] != EncodingConstants.BINARY_HEADER[2] ||
  1947                 _octetBuffer[3] != EncodingConstants.BINARY_HEADER[3]) {
  1949             // Check for each form of XML declaration
  1950             for (int i = 0; i < EncodingConstants.XML_DECLARATION_VALUES.length; i++) {
  1951                 _octetBufferLength = EncodingConstants.XML_DECLARATION_VALUES[i].length - _octetBufferOffset;
  1952                 ensureOctetBufferSize();
  1953                 _octetBufferOffset += _octetBufferLength;
  1955                 // Check XML declaration
  1956                 if (arrayEquals(_octetBuffer, 0,
  1957                         EncodingConstants.XML_DECLARATION_VALUES[i],
  1958                         EncodingConstants.XML_DECLARATION_VALUES[i].length)) {
  1959                     _octetBufferLength = EncodingConstants.BINARY_HEADER.length;
  1960                     ensureOctetBufferSize();
  1962                     // Check for binary header
  1963                     if (_octetBuffer[_octetBufferOffset++] != EncodingConstants.BINARY_HEADER[0] ||
  1964                             _octetBuffer[_octetBufferOffset++] != EncodingConstants.BINARY_HEADER[1] ||
  1965                             _octetBuffer[_octetBufferOffset++] != EncodingConstants.BINARY_HEADER[2] ||
  1966                             _octetBuffer[_octetBufferOffset++] != EncodingConstants.BINARY_HEADER[3]) {
  1967                         return false;
  1968                     } else {
  1969                         // Fast Infoset document with XML declaration and binary header
  1970                         return true;
  1975             return false;
  1978         // Fast Infoset document with binary header
  1979         return true;
  1982     private boolean arrayEquals(byte[] b1, int offset, byte[] b2, int length) {
  1983         for (int i = 0; i < length; i++) {
  1984             if (b1[offset + i] != b2[i]) {
  1985                 return false;
  1989         return true;
  1992     static public boolean isFastInfosetDocument(InputStream s) throws IOException {
  1993         // TODO
  1994         // Check for <?xml declaration with 'finf' encoding
  1995         final int headerSize = 4;
  1997         final byte[] header = new byte[headerSize];
  1998         final int readBytesCount = s.read(header);
  1999         if (readBytesCount < headerSize ||
  2000                 header[0] != EncodingConstants.BINARY_HEADER[0] ||
  2001                 header[1] != EncodingConstants.BINARY_HEADER[1] ||
  2002                 header[2] != EncodingConstants.BINARY_HEADER[2] ||
  2003                 header[3] != EncodingConstants.BINARY_HEADER[3]) {
  2004             return false;
  2007         // TODO
  2008         return true;

mercurial