| /* |
| * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| * |
| * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC. |
| */ |
| |
| /* |
| * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| * |
| * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC. |
| * |
| */ |
| package com.sun.xml.internal.fastinfoset; |
| |
| import com.sun.xml.internal.fastinfoset.alphabet.BuiltInRestrictedAlphabets; |
| import com.sun.xml.internal.fastinfoset.org.apache.xerces.util.XMLChar; |
| import com.sun.xml.internal.fastinfoset.util.CharArray; |
| import com.sun.xml.internal.fastinfoset.util.CharArrayArray; |
| import com.sun.xml.internal.fastinfoset.util.CharArrayString; |
| import com.sun.xml.internal.fastinfoset.util.ContiguousCharArrayArray; |
| import com.sun.xml.internal.fastinfoset.util.DuplicateAttributeVerifier; |
| import com.sun.xml.internal.fastinfoset.util.PrefixArray; |
| import com.sun.xml.internal.fastinfoset.util.QualifiedNameArray; |
| import com.sun.xml.internal.fastinfoset.util.StringArray; |
| import com.sun.xml.internal.fastinfoset.vocab.ParserVocabulary; |
| import java.io.EOFException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetException; |
| import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetParser; |
| |
| /** |
| * Abstract decoder for developing concrete encoders. |
| * |
| * Concrete implementations extending Decoder will utilize methods on Decoder |
| * to decode XML infoset according to the Fast Infoset standard. It is the |
| * responsibility of the concrete implementation to ensure that methods are |
| * invoked in the correct order to correctly decode a valid fast infoset |
| * document. |
| * |
| * <p> |
| * This class extends org.sax.xml.DefaultHandler so that concrete SAX |
| * implementations can be used with javax.xml.parsers.SAXParser and the parse |
| * methods that take org.sax.xml.DefaultHandler as a parameter. |
| * |
| * <p> |
| * Buffering of octets that are read from an {@link java.io.InputStream} is |
| * supported in a similar manner to a {@link java.io.BufferedInputStream}. |
| * Combining buffering with decoding enables better performance. |
| * |
| * <p> |
| * More than one fast infoset document may be decoded from the |
| * {@link java.io.InputStream}. |
| */ |
| public abstract class Decoder implements FastInfosetParser { |
| |
| /** |
| * String interning system property. |
| */ |
| public static final String STRING_INTERNING_SYSTEM_PROPERTY = |
| "com.sun.xml.internal.fastinfoset.parser.string-interning"; |
| |
| /** |
| * Internal buffer size interning system property. |
| */ |
| public static final String BUFFER_SIZE_SYSTEM_PROPERTY = |
| "com.sun.xml.internal.fastinfoset.parser.buffer-size"; |
| |
| private static boolean _stringInterningSystemDefault = false; |
| |
| private static int _bufferSizeSystemDefault = 1024; |
| |
| static { |
| String p = System.getProperty(STRING_INTERNING_SYSTEM_PROPERTY, |
| Boolean.toString(_stringInterningSystemDefault)); |
| _stringInterningSystemDefault = Boolean.valueOf(p).booleanValue(); |
| |
| p = System.getProperty(BUFFER_SIZE_SYSTEM_PROPERTY, |
| Integer.toString(_bufferSizeSystemDefault)); |
| try { |
| int i = Integer.valueOf(p).intValue(); |
| if (i > 0) { |
| _bufferSizeSystemDefault = i; |
| } |
| } catch (NumberFormatException e) { |
| } |
| } |
| |
| /** |
| * True if string interning is performed by the decoder. |
| */ |
| private boolean _stringInterning = _stringInterningSystemDefault; |
| |
| /** |
| * The input stream from which the fast infoset document is being read. |
| */ |
| private InputStream _s; |
| |
| /** |
| * The map of URIs to referenced vocabularies. |
| */ |
| private Map _externalVocabularies; |
| |
| /** |
| * True if the vocabulary is internally created by decoder. |
| */ |
| private boolean _vIsInternal; |
| |
| /** |
| * The list of Notation Information Items that are part of the |
| * Document Information Item. |
| */ |
| protected List _notations; |
| |
| /** |
| * The list of Unparsed Entity Information Items that are part of the |
| * Document Information Item. |
| */ |
| protected List _unparsedEntities; |
| |
| /** |
| * The map of URIs to registered encoding algorithms. |
| */ |
| protected Map _registeredEncodingAlgorithms = new HashMap(); |
| |
| /** |
| * The vocabulary used for decoding. |
| */ |
| protected ParserVocabulary _v; |
| |
| /** |
| * The prefix table of the vocabulary. |
| */ |
| protected PrefixArray _prefixTable; |
| |
| /** |
| * The element name table of the vocabulary. |
| */ |
| protected QualifiedNameArray _elementNameTable; |
| |
| /** |
| * The attribute name table of the vocabulary. |
| */ |
| protected QualifiedNameArray _attributeNameTable; |
| |
| /** |
| * The character content chunk table of the vocabulary. |
| */ |
| protected ContiguousCharArrayArray _characterContentChunkTable; |
| |
| /** |
| * The attribute value table of the vocabulary. |
| */ |
| protected StringArray _attributeValueTable; |
| |
| /** |
| * The current octet that is being read |
| */ |
| protected int _b; |
| |
| /** |
| * True if an information item is terminated. |
| */ |
| protected boolean _terminate; |
| |
| /** |
| * True if two information item are terminated in direct sequence. |
| */ |
| protected boolean _doubleTerminate; |
| |
| /** |
| * True if an entry is required to be added to a table |
| */ |
| protected boolean _addToTable; |
| |
| /** |
| * The vocabulary table index to an indexed non identifying string. |
| */ |
| protected int _integer; |
| |
| /** |
| * The vocabulary table index of identifying string or the identifier of |
| * an encoding algorithm or restricted alphabet. |
| */ |
| protected int _identifier; |
| |
| /** |
| * The size of the internal buffer. |
| */ |
| protected int _bufferSize = _bufferSizeSystemDefault; |
| |
| /** |
| * The internal buffer used for decoding. |
| */ |
| protected byte[] _octetBuffer = new byte[_bufferSizeSystemDefault]; |
| |
| /** |
| * A mark into the internal buffer used for decoding encoded algorithm |
| * or restricted alphabet data. |
| */ |
| protected int _octetBufferStart; |
| |
| /** |
| * The offset into the buffer to read the next byte. |
| */ |
| protected int _octetBufferOffset; |
| |
| /** |
| * The end of the buffer. |
| */ |
| protected int _octetBufferEnd; |
| |
| /** |
| * The length of some octets in the buffer that are to be read. |
| */ |
| protected int _octetBufferLength; |
| |
| /** |
| * The internal buffer of characters. |
| */ |
| protected char[] _charBuffer = new char[512]; |
| |
| /** |
| * The length of characters in the buffer of characters. |
| */ |
| protected int _charBufferLength; |
| |
| /** |
| * Helper class that checks for duplicate attribute information items. |
| */ |
| protected DuplicateAttributeVerifier _duplicateAttributeVerifier = new DuplicateAttributeVerifier(); |
| |
| /** |
| * Default constructor for the Decoder. |
| */ |
| protected Decoder() { |
| _v = new ParserVocabulary(); |
| _prefixTable = _v.prefix; |
| _elementNameTable = _v.elementName; |
| _attributeNameTable = _v.attributeName; |
| _characterContentChunkTable = _v.characterContentChunk; |
| _attributeValueTable = _v.attributeValue; |
| _vIsInternal = true; |
| } |
| |
| |
| // FastInfosetParser interface |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void setStringInterning(boolean stringInterning) { |
| _stringInterning = stringInterning; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public boolean getStringInterning() { |
| return _stringInterning; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void setBufferSize(int bufferSize) { |
| if (_bufferSize > _octetBuffer.length) { |
| _bufferSize = bufferSize; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public int getBufferSize() { |
| return _bufferSize; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void setRegisteredEncodingAlgorithms(Map algorithms) { |
| _registeredEncodingAlgorithms = algorithms; |
| if (_registeredEncodingAlgorithms == null) { |
| _registeredEncodingAlgorithms = new HashMap(); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public Map getRegisteredEncodingAlgorithms() { |
| return _registeredEncodingAlgorithms; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void setExternalVocabularies(Map referencedVocabualries) { |
| if (referencedVocabualries != null) { |
| // Clone the input map |
| _externalVocabularies = new HashMap(); |
| _externalVocabularies.putAll(referencedVocabualries); |
| } else { |
| _externalVocabularies = null; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public Map getExternalVocabularies() { |
| return _externalVocabularies; |
| } |
| |
| // End FastInfosetParser interface |
| |
| |
| /** |
| * Reset the decoder for reuse decoding another XML infoset. |
| */ |
| public void reset() { |
| _terminate = _doubleTerminate = false; |
| } |
| |
| /** |
| * Set the ParserVocabulary to be used for decoding. |
| * |
| * @param v the vocabulary to be used for decoding. |
| */ |
| public void setVocabulary(ParserVocabulary v) { |
| _v = v; |
| _prefixTable = _v.prefix; |
| _elementNameTable = _v.elementName; |
| _attributeNameTable = _v.attributeName; |
| _characterContentChunkTable = _v.characterContentChunk; |
| _attributeValueTable = _v.attributeValue; |
| _vIsInternal = false; |
| } |
| |
| /** |
| * Set the InputStream to decode the fast infoset document. |
| * |
| * @param s the InputStream where the fast infoset document is decoded from. |
| */ |
| public void setInputStream(InputStream s) { |
| _s = s; |
| _octetBufferOffset = 0; |
| _octetBufferEnd = 0; |
| if (_vIsInternal == true) { |
| _v.clear(); |
| } |
| } |
| |
| protected final void decodeDII() throws FastInfosetException, IOException { |
| final int b = read(); |
| if (b == EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) { |
| decodeInitialVocabulary(); |
| } else if (b != 0) { |
| throw new IOException(CommonResourceBundle.getInstance(). |
| getString("message.optinalValues")); |
| } |
| } |
| |
| protected final void decodeAdditionalData() throws FastInfosetException, IOException { |
| for (int i = 0; i < decodeNumberOfItemsOfSequence(); i++) { |
| String URI = decodeNonEmptyOctetStringOnSecondBitAsUtf8String(); |
| |
| decodeNonEmptyOctetStringLengthOnSecondBit(); |
| ensureOctetBufferSize(); |
| _octetBufferStart = _octetBufferOffset; |
| _octetBufferOffset += _octetBufferLength; |
| } |
| } |
| |
| protected final void decodeInitialVocabulary() throws FastInfosetException, IOException { |
| // First 5 optionals of 13 bit optional field |
| int b = read(); |
| // Next 8 optionals of 13 bit optional field |
| int b2 = read(); |
| |
| // Optimize for the most common case |
| if (b == EncodingConstants.INITIAL_VOCABULARY_EXTERNAL_VOCABULARY_FLAG && b2 == 0) { |
| decodeExternalVocabularyURI(); |
| return; |
| } |
| |
| if ((b & EncodingConstants.INITIAL_VOCABULARY_EXTERNAL_VOCABULARY_FLAG) > 0) { |
| decodeExternalVocabularyURI(); |
| } |
| |
| if ((b & EncodingConstants.INITIAL_VOCABULARY_RESTRICTED_ALPHABETS_FLAG) > 0) { |
| decodeTableItems(_v.restrictedAlphabet); |
| } |
| |
| if ((b & EncodingConstants.INITIAL_VOCABULARY_ENCODING_ALGORITHMS_FLAG) > 0) { |
| decodeTableItems(_v.encodingAlgorithm); |
| } |
| |
| if ((b & EncodingConstants.INITIAL_VOCABULARY_PREFIXES_FLAG) > 0) { |
| decodeTableItems(_v.prefix); |
| } |
| |
| if ((b & EncodingConstants.INITIAL_VOCABULARY_NAMESPACE_NAMES_FLAG) > 0) { |
| decodeTableItems(_v.namespaceName); |
| } |
| |
| if ((b2 & EncodingConstants.INITIAL_VOCABULARY_LOCAL_NAMES_FLAG) > 0) { |
| decodeTableItems(_v.localName); |
| } |
| |
| if ((b2 & EncodingConstants.INITIAL_VOCABULARY_OTHER_NCNAMES_FLAG) > 0) { |
| decodeTableItems(_v.otherNCName); |
| } |
| |
| if ((b2 & EncodingConstants.INITIAL_VOCABULARY_OTHER_URIS_FLAG) > 0) { |
| decodeTableItems(_v.otherURI); |
| } |
| |
| if ((b2 & EncodingConstants.INITIAL_VOCABULARY_ATTRIBUTE_VALUES_FLAG) > 0) { |
| decodeTableItems(_v.attributeValue); |
| } |
| |
| if ((b2 & EncodingConstants.INITIAL_VOCABULARY_CONTENT_CHARACTER_CHUNKS_FLAG) > 0) { |
| decodeTableItems(_v.characterContentChunk); |
| } |
| |
| if ((b2 & EncodingConstants.INITIAL_VOCABULARY_OTHER_STRINGS_FLAG) > 0) { |
| decodeTableItems(_v.otherString); |
| } |
| |
| if ((b2 & EncodingConstants.INITIAL_VOCABULARY_ELEMENT_NAME_SURROGATES_FLAG) > 0) { |
| decodeTableItems(_v.elementName, false); |
| } |
| |
| if ((b2 & EncodingConstants.INITIAL_VOCABULARY_ATTRIBUTE_NAME_SURROGATES_FLAG) > 0) { |
| decodeTableItems(_v.attributeName, true); |
| } |
| } |
| |
| private void decodeExternalVocabularyURI() throws FastInfosetException, IOException { |
| if (_externalVocabularies == null) { |
| throw new IOException(CommonResourceBundle. |
| getInstance().getString("message.noExternalVocabularies")); |
| } |
| |
| String externalVocabularyURI = |
| decodeNonEmptyOctetStringOnSecondBitAsUtf8String(); |
| |
| Object o = _externalVocabularies.get(externalVocabularyURI); |
| if (o instanceof ParserVocabulary) { |
| _v.setReferencedVocabulary(externalVocabularyURI, |
| (ParserVocabulary)o, false); |
| } else if (o instanceof com.sun.xml.internal.org.jvnet.fastinfoset.ExternalVocabulary) { |
| com.sun.xml.internal.org.jvnet.fastinfoset.ExternalVocabulary v = |
| (com.sun.xml.internal.org.jvnet.fastinfoset.ExternalVocabulary)o; |
| ParserVocabulary pv = new ParserVocabulary(v.vocabulary); |
| |
| _externalVocabularies.put(externalVocabularyURI, pv); |
| _v.setReferencedVocabulary(externalVocabularyURI, |
| pv, false); |
| } else { |
| throw new FastInfosetException(CommonResourceBundle.getInstance(). |
| getString("message.externalVocabularyNotRegistered", |
| new Object[]{externalVocabularyURI})); |
| } |
| } |
| |
| private void decodeTableItems(StringArray array) throws FastInfosetException, IOException { |
| for (int i = 0; i < decodeNumberOfItemsOfSequence(); i++) { |
| array.add(decodeNonEmptyOctetStringOnSecondBitAsUtf8String()); |
| } |
| } |
| |
| private void decodeTableItems(PrefixArray array) throws FastInfosetException, IOException { |
| for (int i = 0; i < decodeNumberOfItemsOfSequence(); i++) { |
| array.add(decodeNonEmptyOctetStringOnSecondBitAsUtf8String()); |
| } |
| } |
| |
| private void decodeTableItems(ContiguousCharArrayArray array) throws FastInfosetException, IOException { |
| for (int i = 0; i < decodeNumberOfItemsOfSequence(); i++) { |
| switch(decodeNonIdentifyingStringOnFirstBit()) { |
| case NISTRING_STRING: |
| array.add(_charBuffer, _charBufferLength); |
| break; |
| default: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.illegalState")); |
| } |
| } |
| } |
| |
| private void decodeTableItems(CharArrayArray array) throws FastInfosetException, IOException { |
| for (int i = 0; i < decodeNumberOfItemsOfSequence(); i++) { |
| switch(decodeNonIdentifyingStringOnFirstBit()) { |
| case NISTRING_STRING: |
| array.add(new CharArray(_charBuffer, 0, _charBufferLength, true)); |
| break; |
| default: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.illegalState")); |
| } |
| } |
| } |
| |
| private void decodeTableItems(QualifiedNameArray array, boolean isAttribute) throws FastInfosetException, IOException { |
| for (int i = 0; i < decodeNumberOfItemsOfSequence(); i++) { |
| final int b = read(); |
| |
| String prefix = ""; |
| int prefixIndex = -1; |
| if ((b & EncodingConstants.NAME_SURROGATE_PREFIX_FLAG) > 0) { |
| prefixIndex = decodeIntegerIndexOnSecondBit(); |
| prefix = _v.prefix.get(prefixIndex); |
| } |
| |
| String namespaceName = ""; |
| int namespaceNameIndex = -1; |
| if ((b & EncodingConstants.NAME_SURROGATE_NAME_FLAG) > 0) { |
| namespaceNameIndex = decodeIntegerIndexOnSecondBit(); |
| namespaceName = _v.prefix.get(prefixIndex); |
| } |
| |
| if (namespaceName == "" && prefix != "") { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.missingNamespace")); |
| } |
| |
| final int localNameIndex = decodeIntegerIndexOnSecondBit(); |
| final String localName = _v.localName.get(localNameIndex); |
| |
| QualifiedName qualifiedName = new QualifiedName(prefix, namespaceName, localName, |
| prefixIndex, namespaceNameIndex, localNameIndex, |
| _charBuffer); |
| if (isAttribute) { |
| qualifiedName.createAttributeValues(_duplicateAttributeVerifier.MAP_SIZE); |
| } |
| array.add(qualifiedName); |
| } |
| } |
| |
| private int decodeNumberOfItemsOfSequence() throws IOException { |
| final int b = read(); |
| if (b < 128) { |
| return b; |
| } else { |
| return ((b & 0x0F) << 16) | (read() << 8) | read(); |
| } |
| } |
| |
| protected final void decodeNotations() throws FastInfosetException, IOException { |
| if (_notations == null) { |
| _notations = new ArrayList(); |
| } else { |
| _notations.clear(); |
| } |
| |
| int b = read(); |
| while ((b & EncodingConstants.NOTATIONS_MASK) == EncodingConstants.NOTATIONS) { |
| String name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName); |
| |
| String system_identifier = ((_b & EncodingConstants.NOTATIONS_SYSTEM_IDENTIFIER_FLAG) > 0) |
| ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : ""; |
| String public_identifier = ((_b & EncodingConstants.NOTATIONS_PUBLIC_IDENTIFIER_FLAG) > 0) |
| ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : ""; |
| |
| Notation notation = new Notation(name, system_identifier, public_identifier); |
| _notations.add(notation); |
| |
| b = read(); |
| } |
| if (b != EncodingConstants.TERMINATOR) { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IIsNotTerminatedCorrectly")); |
| } |
| } |
| |
| protected final void decodeUnparsedEntities() throws FastInfosetException, IOException { |
| if (_unparsedEntities == null) { |
| _unparsedEntities = new ArrayList(); |
| } else { |
| _unparsedEntities.clear(); |
| } |
| |
| int b = read(); |
| while ((b & EncodingConstants.UNPARSED_ENTITIES_MASK) == EncodingConstants.UNPARSED_ENTITIES) { |
| String name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName); |
| String system_identifier = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI); |
| |
| String public_identifier = ((_b & EncodingConstants.UNPARSED_ENTITIES_PUBLIC_IDENTIFIER_FLAG) > 0) |
| ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : ""; |
| |
| String notation_name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName); |
| |
| UnparsedEntity unparsedEntity = new UnparsedEntity(name, system_identifier, public_identifier, notation_name); |
| _unparsedEntities.add(unparsedEntity); |
| |
| b = read(); |
| } |
| if (b != EncodingConstants.TERMINATOR) { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.unparsedEntities")); |
| } |
| } |
| |
| protected final String decodeCharacterEncodingScheme() throws FastInfosetException, IOException { |
| return decodeNonEmptyOctetStringOnSecondBitAsUtf8String(); |
| } |
| |
| protected final String decodeVersion() throws FastInfosetException, IOException { |
| switch(decodeNonIdentifyingStringOnFirstBit()) { |
| case NISTRING_STRING: |
| final String data = new String(_charBuffer, 0, _charBufferLength); |
| if (_addToTable) { |
| _v.otherString.add(new CharArrayString(data)); |
| } |
| return data; |
| case NISTRING_ENCODING_ALGORITHM: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingNotSupported")); |
| case NISTRING_INDEX: |
| return _v.otherString.get(_integer).toString(); |
| case NISTRING_EMPTY_STRING: |
| default: |
| return ""; |
| } |
| } |
| |
| protected final QualifiedName decodeEIIIndexMedium() throws FastInfosetException, IOException { |
| final int i = (((_b & EncodingConstants.INTEGER_3RD_BIT_MEDIUM_MASK) << 8) | read()) |
| + EncodingConstants.INTEGER_3RD_BIT_SMALL_LIMIT; |
| return _v.elementName._array[i]; |
| } |
| |
| protected final QualifiedName decodeEIIIndexLarge() throws FastInfosetException, IOException { |
| int i; |
| if ((_b & EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_FLAG) == 0x20) { |
| // EII large index |
| i = (((_b & EncodingConstants.INTEGER_3RD_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) |
| + EncodingConstants.INTEGER_3RD_BIT_MEDIUM_LIMIT; |
| } else { |
| // EII large large index |
| i = (((read() & EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_MASK) << 16) | (read() << 8) | read()) |
| + EncodingConstants.INTEGER_3RD_BIT_LARGE_LIMIT; |
| } |
| return _v.elementName._array[i]; |
| } |
| |
| protected final QualifiedName decodeLiteralQualifiedName(int state) throws FastInfosetException, IOException { |
| switch (state) { |
| // no prefix, no namespace |
| case 0: |
| return new QualifiedName( |
| "", |
| "", |
| decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName), |
| -1, |
| -1, |
| _identifier, |
| null); |
| // no prefix, namespace |
| case 1: |
| return new QualifiedName( |
| "", |
| decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(false), |
| decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName), |
| -1, |
| _namespaceNameIndex, |
| _identifier, |
| null); |
| // prefix, no namespace |
| case 2: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.qNameMissingNamespaceName")); |
| // prefix, namespace |
| case 3: |
| return new QualifiedName( |
| decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(true), |
| decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(true), |
| decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName), |
| _prefixIndex, |
| _namespaceNameIndex, |
| _identifier, |
| _charBuffer); |
| default: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingEII")); |
| } |
| } |
| |
| protected static final int NISTRING_STRING = 0; |
| protected static final int NISTRING_INDEX = 1; |
| protected static final int NISTRING_ENCODING_ALGORITHM = 2; |
| protected static final int NISTRING_EMPTY_STRING = 3; |
| |
| /* |
| * C.14 |
| * decodeNonIdentifyingStringOnFirstBit |
| */ |
| protected final int decodeNonIdentifyingStringOnFirstBit() throws FastInfosetException, IOException { |
| final int b = read(); |
| switch(DecoderStateTables.NISTRING[b]) { |
| case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH: |
| _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; |
| _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1; |
| decodeUtf8StringAsCharBuffer(); |
| return NISTRING_STRING; |
| case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH: |
| _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; |
| _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT; |
| decodeUtf8StringAsCharBuffer(); |
| return NISTRING_STRING; |
| case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH: |
| { |
| _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; |
| final int length = (read() << 24) | |
| (read() << 16) | |
| (read() << 8) | |
| read(); |
| _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT; |
| decodeUtf8StringAsCharBuffer(); |
| return NISTRING_STRING; |
| } |
| case DecoderStateTables.NISTRING_UTF16_SMALL_LENGTH: |
| _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; |
| _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1; |
| decodeUtf16StringAsCharBuffer(); |
| return NISTRING_STRING; |
| case DecoderStateTables.NISTRING_UTF16_MEDIUM_LENGTH: |
| _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; |
| _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT; |
| decodeUtf16StringAsCharBuffer(); |
| return NISTRING_STRING; |
| case DecoderStateTables.NISTRING_UTF16_LARGE_LENGTH: |
| { |
| _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; |
| final int length = (read() << 24) | |
| (read() << 16) | |
| (read() << 8) | |
| read(); |
| _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT; |
| decodeUtf16StringAsCharBuffer(); |
| return NISTRING_STRING; |
| } |
| case DecoderStateTables.NISTRING_RA: |
| { |
| _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; |
| // Decode resitricted alphabet integer |
| _identifier = (b & 0x0F) << 4; |
| final int b2 = read(); |
| _identifier |= (b2 & 0xF0) >> 4; |
| |
| decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b2); |
| |
| decodeRestrictedAlphabetAsCharBuffer(); |
| return NISTRING_STRING; |
| } |
| case DecoderStateTables.NISTRING_EA: |
| { |
| _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; |
| // Decode encoding algorithm integer |
| _identifier = (b & 0x0F) << 4; |
| final int b2 = read(); |
| _identifier |= (b2 & 0xF0) >> 4; |
| |
| decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b2); |
| return NISTRING_ENCODING_ALGORITHM; |
| } |
| case DecoderStateTables.NISTRING_INDEX_SMALL: |
| _integer = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; |
| return NISTRING_INDEX; |
| case DecoderStateTables.NISTRING_INDEX_MEDIUM: |
| _integer = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; |
| return NISTRING_INDEX; |
| case DecoderStateTables.NISTRING_INDEX_LARGE: |
| _integer = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; |
| return NISTRING_INDEX; |
| case DecoderStateTables.NISTRING_EMPTY: |
| return NISTRING_EMPTY_STRING; |
| default: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingNonIdentifyingString")); |
| } |
| } |
| |
| protected final void decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(int b) throws FastInfosetException, IOException { |
| // Remove top 4 bits of restricted alphabet or encoding algorithm integer |
| b &= 0x0F; |
| // Reuse UTF8 length states |
| switch(DecoderStateTables.NISTRING[b]) { |
| case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH: |
| _octetBufferLength = b + 1; |
| break; |
| case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH: |
| _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT; |
| break; |
| case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH: |
| final int length = (read() << 24) | |
| (read() << 16) | |
| (read() << 8) | |
| read(); |
| _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT; |
| break; |
| default: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingOctets")); |
| } |
| ensureOctetBufferSize(); |
| _octetBufferStart = _octetBufferOffset; |
| _octetBufferOffset += _octetBufferLength; |
| } |
| |
| protected final void decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(int b) throws FastInfosetException, IOException { |
| // Remove top 6 bits of restricted alphabet or encoding algorithm integer |
| switch (b & 0x03) { |
| // Small length |
| case 0: |
| _octetBufferLength = 1; |
| break; |
| // Small length |
| case 1: |
| _octetBufferLength = 2; |
| break; |
| // Medium length |
| case 2: |
| _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT; |
| break; |
| // Large length |
| case 3: |
| _octetBufferLength = (read() << 24) | |
| (read() << 16) | |
| (read() << 8) | |
| read(); |
| _octetBufferLength += EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT; |
| break; |
| } |
| |
| ensureOctetBufferSize(); |
| _octetBufferStart = _octetBufferOffset; |
| _octetBufferOffset += _octetBufferLength; |
| } |
| |
| /* |
| * C.13 |
| */ |
| protected final String decodeIdentifyingNonEmptyStringOnFirstBit(StringArray table) throws FastInfosetException, IOException { |
| final int b = read(); |
| switch(DecoderStateTables.ISTRING[b]) { |
| case DecoderStateTables.ISTRING_SMALL_LENGTH: |
| { |
| _octetBufferLength = b + 1; |
| final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); |
| _identifier = table.add(s) - 1; |
| return s; |
| } |
| case DecoderStateTables.ISTRING_MEDIUM_LENGTH: |
| { |
| _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT; |
| final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); |
| _identifier = table.add(s) - 1; |
| return s; |
| } |
| case DecoderStateTables.ISTRING_LARGE_LENGTH: |
| { |
| final int length = (read() << 24) | |
| (read() << 16) | |
| (read() << 8) | |
| read(); |
| _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT; |
| final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); |
| _identifier = table.add(s) - 1; |
| return s; |
| } |
| case DecoderStateTables.ISTRING_INDEX_SMALL: |
| _identifier = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; |
| return table._array[_identifier]; |
| case DecoderStateTables.ISTRING_INDEX_MEDIUM: |
| _identifier = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; |
| return table._array[_identifier]; |
| case DecoderStateTables.ISTRING_INDEX_LARGE: |
| _identifier = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; |
| return table._array[_identifier]; |
| default: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingIdentifyingString")); |
| } |
| } |
| |
| protected int _prefixIndex; |
| |
| /* |
| * C.13 |
| */ |
| protected final String decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(boolean namespaceNamePresent) throws FastInfosetException, IOException { |
| final int b = read(); |
| switch(DecoderStateTables.ISTRING_PREFIX_NAMESPACE[b]) { |
| case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_3: |
| { |
| _octetBufferLength = EncodingConstants.XML_NAMESPACE_PREFIX_LENGTH; |
| decodeUtf8StringAsCharBuffer(); |
| |
| if (_charBuffer[0] == 'x' && |
| _charBuffer[1] == 'm' && |
| _charBuffer[2] == 'l') { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.prefixIllegal")); |
| } |
| |
| final String s = (_stringInterning) ? new String(_charBuffer, 0, _charBufferLength).intern() : |
| new String(_charBuffer, 0, _charBufferLength); |
| _prefixIndex = _v.prefix.add(s); |
| return s; |
| } |
| case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_5: |
| { |
| _octetBufferLength = EncodingConstants.XMLNS_NAMESPACE_PREFIX_LENGTH; |
| decodeUtf8StringAsCharBuffer(); |
| |
| if (_charBuffer[0] == 'x' && |
| _charBuffer[1] == 'm' && |
| _charBuffer[2] == 'l' && |
| _charBuffer[3] == 'n' && |
| _charBuffer[4] == 's') { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.xmlns")); |
| } |
| |
| final String s = (_stringInterning) ? new String(_charBuffer, 0, _charBufferLength).intern() : |
| new String(_charBuffer, 0, _charBufferLength); |
| _prefixIndex = _v.prefix.add(s); |
| return s; |
| } |
| case DecoderStateTables.ISTRING_SMALL_LENGTH: |
| case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_29: |
| case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_36: |
| { |
| _octetBufferLength = b + 1; |
| final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); |
| _prefixIndex = _v.prefix.add(s); |
| return s; |
| } |
| case DecoderStateTables.ISTRING_MEDIUM_LENGTH: |
| { |
| _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT; |
| final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); |
| _prefixIndex = _v.prefix.add(s); |
| return s; |
| } |
| case DecoderStateTables.ISTRING_LARGE_LENGTH: |
| { |
| final int length = (read() << 24) | |
| (read() << 16) | |
| (read() << 8) | |
| read(); |
| _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT; |
| final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); |
| _prefixIndex = _v.prefix.add(s); |
| return s; |
| } |
| case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO: |
| if (namespaceNamePresent) { |
| _prefixIndex = 0; |
| // Peak at next byte and check the index of the XML namespace name |
| if (DecoderStateTables.ISTRING_PREFIX_NAMESPACE[peak()] |
| != DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO) { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.wrongNamespaceName")); |
| } |
| return EncodingConstants.XML_NAMESPACE_PREFIX; |
| } else { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.missingNamespaceName")); |
| } |
| case DecoderStateTables.ISTRING_INDEX_SMALL: |
| _prefixIndex = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; |
| return _v.prefix._array[_prefixIndex - 1]; |
| case DecoderStateTables.ISTRING_INDEX_MEDIUM: |
| _prefixIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; |
| return _v.prefix._array[_prefixIndex - 1]; |
| case DecoderStateTables.ISTRING_INDEX_LARGE: |
| _prefixIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; |
| return _v.prefix._array[_prefixIndex - 1]; |
| default: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingIdentifyingStringForPrefix")); |
| } |
| } |
| |
| /* |
| * C.13 |
| */ |
| protected final String decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(boolean namespaceNamePresent) throws FastInfosetException, IOException { |
| final int b = read(); |
| switch(DecoderStateTables.ISTRING_PREFIX_NAMESPACE[b]) { |
| case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO: |
| if (namespaceNamePresent) { |
| _prefixIndex = 0; |
| // Peak at next byte and check the index of the XML namespace name |
| if (DecoderStateTables.ISTRING_PREFIX_NAMESPACE[peak()] |
| != DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO) { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.wrongNamespaceName")); |
| } |
| return EncodingConstants.XML_NAMESPACE_PREFIX; |
| } else { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.missingNamespaceName")); |
| } |
| case DecoderStateTables.ISTRING_INDEX_SMALL: |
| _prefixIndex = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; |
| return _v.prefix._array[_prefixIndex - 1]; |
| case DecoderStateTables.ISTRING_INDEX_MEDIUM: |
| _prefixIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; |
| return _v.prefix._array[_prefixIndex - 1]; |
| case DecoderStateTables.ISTRING_INDEX_LARGE: |
| _prefixIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; |
| return _v.prefix._array[_prefixIndex - 1]; |
| default: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingIdentifyingStringForPrefix")); |
| } |
| } |
| |
| protected int _namespaceNameIndex; |
| |
| /* |
| * C.13 |
| */ |
| protected final String decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(boolean prefixPresent) throws FastInfosetException, IOException { |
| final int b = read(); |
| switch(DecoderStateTables.ISTRING_PREFIX_NAMESPACE[b]) { |
| case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_3: |
| case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_5: |
| case DecoderStateTables.ISTRING_SMALL_LENGTH: |
| { |
| _octetBufferLength = b + 1; |
| final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); |
| _namespaceNameIndex = _v.namespaceName.add(s); |
| return s; |
| } |
| case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_29: |
| { |
| _octetBufferLength = EncodingConstants.XMLNS_NAMESPACE_NAME_LENGTH; |
| decodeUtf8StringAsCharBuffer(); |
| |
| if (compareCharsWithCharBufferFromEndToStart(EncodingConstants.XMLNS_NAMESPACE_NAME_CHARS)) { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.xmlnsConnotBeBoundToPrefix")); |
| } |
| |
| final String s = (_stringInterning) ? new String(_charBuffer, 0, _charBufferLength).intern() : |
| new String(_charBuffer, 0, _charBufferLength); |
| _namespaceNameIndex = _v.namespaceName.add(s); |
| return s; |
| } |
| case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_36: |
| { |
| _octetBufferLength = EncodingConstants.XML_NAMESPACE_NAME_LENGTH; |
| decodeUtf8StringAsCharBuffer(); |
| |
| if (compareCharsWithCharBufferFromEndToStart(EncodingConstants.XML_NAMESPACE_NAME_CHARS)) { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.illegalNamespaceName")); |
| } |
| |
| final String s = (_stringInterning) ? new String(_charBuffer, 0, _charBufferLength).intern() : |
| new String(_charBuffer, 0, _charBufferLength); |
| _namespaceNameIndex = _v.namespaceName.add(s); |
| return s; |
| } |
| case DecoderStateTables.ISTRING_MEDIUM_LENGTH: |
| { |
| _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT; |
| final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); |
| _namespaceNameIndex = _v.namespaceName.add(s); |
| return s; |
| } |
| case DecoderStateTables.ISTRING_LARGE_LENGTH: |
| { |
| final int length = (read() << 24) | |
| (read() << 16) | |
| (read() << 8) | |
| read(); |
| _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT; |
| final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); |
| _namespaceNameIndex = _v.namespaceName.add(s); |
| return s; |
| } |
| case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO: |
| if (prefixPresent) { |
| _namespaceNameIndex = 0; |
| return EncodingConstants.XML_NAMESPACE_NAME; |
| } else { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.namespaceWithoutPrefix")); |
| } |
| case DecoderStateTables.ISTRING_INDEX_SMALL: |
| _namespaceNameIndex = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; |
| return _v.namespaceName._array[_namespaceNameIndex - 1]; |
| case DecoderStateTables.ISTRING_INDEX_MEDIUM: |
| _namespaceNameIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; |
| return _v.namespaceName._array[_namespaceNameIndex - 1]; |
| case DecoderStateTables.ISTRING_INDEX_LARGE: |
| _namespaceNameIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; |
| return _v.namespaceName._array[_namespaceNameIndex - 1]; |
| default: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingForNamespaceName")); |
| } |
| } |
| |
| /* |
| * C.13 |
| */ |
| protected final String decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(boolean prefixPresent) throws FastInfosetException, IOException { |
| final int b = read(); |
| switch(DecoderStateTables.ISTRING_PREFIX_NAMESPACE[b]) { |
| case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO: |
| if (prefixPresent) { |
| _namespaceNameIndex = 0; |
| return EncodingConstants.XML_NAMESPACE_NAME; |
| } else { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.namespaceWithoutPrefix")); |
| } |
| case DecoderStateTables.ISTRING_INDEX_SMALL: |
| _namespaceNameIndex = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; |
| return _v.namespaceName._array[_namespaceNameIndex - 1]; |
| case DecoderStateTables.ISTRING_INDEX_MEDIUM: |
| _namespaceNameIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; |
| return _v.namespaceName._array[_namespaceNameIndex - 1]; |
| case DecoderStateTables.ISTRING_INDEX_LARGE: |
| _namespaceNameIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; |
| return _v.namespaceName._array[_namespaceNameIndex - 1]; |
| default: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingForNamespaceName")); |
| } |
| } |
| |
| private boolean compareCharsWithCharBufferFromEndToStart(char[] c) { |
| int i = _charBufferLength ; |
| while (--i >= 0) { |
| if (c[i] != _charBuffer[i]) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /* |
| * C.22 |
| */ |
| protected final String decodeNonEmptyOctetStringOnSecondBitAsUtf8String() throws FastInfosetException, IOException { |
| decodeNonEmptyOctetStringOnSecondBitAsUtf8CharArray(); |
| return new String(_charBuffer, 0, _charBufferLength); |
| } |
| |
| /* |
| * C.22 |
| */ |
| protected final void decodeNonEmptyOctetStringOnSecondBitAsUtf8CharArray() throws FastInfosetException, IOException { |
| decodeNonEmptyOctetStringLengthOnSecondBit(); |
| decodeUtf8StringAsCharBuffer(); |
| } |
| |
| /* |
| * C.22 |
| */ |
| protected final void decodeNonEmptyOctetStringLengthOnSecondBit() throws FastInfosetException, IOException { |
| final int b = read(); |
| switch(DecoderStateTables.ISTRING[b]) { |
| case DecoderStateTables.ISTRING_SMALL_LENGTH: |
| _octetBufferLength = b + 1; |
| break; |
| case DecoderStateTables.ISTRING_MEDIUM_LENGTH: |
| _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT; |
| break; |
| case DecoderStateTables.ISTRING_LARGE_LENGTH: |
| { |
| final int length = (read() << 24) | |
| (read() << 16) | |
| (read() << 8) | |
| read(); |
| _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT; |
| break; |
| } |
| case DecoderStateTables.ISTRING_INDEX_SMALL: |
| case DecoderStateTables.ISTRING_INDEX_MEDIUM: |
| case DecoderStateTables.ISTRING_INDEX_LARGE: |
| default: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingNonEmptyOctet")); |
| } |
| } |
| |
| /* |
| * C.25 |
| */ |
| protected final int decodeIntegerIndexOnSecondBit() throws FastInfosetException, IOException { |
| final int b = read(); |
| switch(DecoderStateTables.ISTRING[b]) { |
| case DecoderStateTables.ISTRING_INDEX_SMALL: |
| return b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; |
| case DecoderStateTables.ISTRING_INDEX_MEDIUM: |
| return (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; |
| case DecoderStateTables.ISTRING_INDEX_LARGE: |
| return (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) |
| + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; |
| case DecoderStateTables.ISTRING_SMALL_LENGTH: |
| case DecoderStateTables.ISTRING_MEDIUM_LENGTH: |
| case DecoderStateTables.ISTRING_LARGE_LENGTH: |
| default: |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingIndexOnSecondBit")); |
| } |
| } |
| |
| protected final void decodeHeader() throws FastInfosetException, IOException { |
| if (!_isFastInfosetDocument()) { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.notFIDocument")); |
| } |
| } |
| |
| protected final void decodeRestrictedAlphabetAsCharBuffer() throws FastInfosetException, IOException { |
| if (_identifier <= EncodingConstants.RESTRICTED_ALPHABET_BUILTIN_END) { |
| decodeFourBitAlphabetOctetsAsCharBuffer(BuiltInRestrictedAlphabets.table[_identifier]); |
| // decodeAlphabetOctetsAsCharBuffer(BuiltInRestrictedAlphabets.table[_identifier]); |
| } else if (_identifier >= EncodingConstants.RESTRICTED_ALPHABET_APPLICATION_START) { |
| CharArray ca = _v.restrictedAlphabet.get(_identifier - EncodingConstants.RESTRICTED_ALPHABET_APPLICATION_START); |
| if (ca == null) { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.alphabetNotPresent", new Object[]{new Integer(_identifier)})); |
| } |
| decodeAlphabetOctetsAsCharBuffer(ca.ch); |
| } else { |
| // Reserved built-in algorithms for future use |
| // TODO should use sax property to decide if event will be |
| // reported, allows for support through handler if required. |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.alphabetIdentifiersReserved")); |
| } |
| } |
| |
| protected final String decodeRestrictedAlphabetAsString() throws FastInfosetException, IOException { |
| decodeRestrictedAlphabetAsCharBuffer(); |
| return new String(_charBuffer, 0, _charBufferLength); |
| } |
| |
| protected final String decodeRAOctetsAsString(char[] restrictedAlphabet) throws FastInfosetException, IOException { |
| decodeAlphabetOctetsAsCharBuffer(null); |
| return new String(_charBuffer, 0, _charBufferLength); |
| } |
| |
| protected final void decodeFourBitAlphabetOctetsAsCharBuffer(char[] restrictedAlphabet) throws FastInfosetException, IOException { |
| _charBufferLength = 0; |
| final int characters = _octetBufferLength / 2; |
| if (_charBuffer.length < characters) { |
| _charBuffer = new char[characters]; |
| } |
| |
| int v = 0; |
| for (int i = 0; i < _octetBufferLength - 1; i++) { |
| v = _octetBuffer[_octetBufferStart++] & 0xFF; |
| _charBuffer[_charBufferLength++] = restrictedAlphabet[v >> 4]; |
| _charBuffer[_charBufferLength++] = restrictedAlphabet[v & 0x0F]; |
| } |
| v = _octetBuffer[_octetBufferStart++] & 0xFF; |
| _charBuffer[_charBufferLength++] = restrictedAlphabet[v >> 4]; |
| v &= 0x0F; |
| if (v != 0x0F) { |
| _charBuffer[_charBufferLength++] = restrictedAlphabet[v & 0x0F]; |
| } |
| } |
| |
| protected final void decodeAlphabetOctetsAsCharBuffer(char[] restrictedAlphabet) throws FastInfosetException, IOException { |
| if (restrictedAlphabet.length < 2) { |
| throw new IllegalArgumentException(CommonResourceBundle.getInstance().getString("message.alphabetMustContain2orMoreChars")); |
| } |
| |
| int bitsPerCharacter = 1; |
| while ((1 << bitsPerCharacter) <= restrictedAlphabet.length) { |
| bitsPerCharacter++; |
| } |
| final int terminatingValue = (1 << bitsPerCharacter) - 1; |
| |
| int characters = (_octetBufferLength << 3) / bitsPerCharacter; |
| if (characters == 0) { |
| throw new IOException(""); |
| } |
| |
| _charBufferLength = 0; |
| if (_charBuffer.length < characters) { |
| _charBuffer = new char[characters]; |
| } |
| |
| resetBits(); |
| for (int i = 0; i < characters; i++) { |
| int value = readBits(bitsPerCharacter); |
| if (bitsPerCharacter < 8 && value == terminatingValue) { |
| int octetPosition = (i * bitsPerCharacter) >>> 3; |
| if (octetPosition != _octetBufferLength - 1) { |
| throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.alphabetIncorrectlyTerminated")); |
| } |
| break; |
| } |
| _charBuffer[_charBufferLength++] = restrictedAlphabet[value]; |
| } |
| } |
| |
| private int _bitsLeftInOctet; |
| |
| private void resetBits() { |
| _bitsLeftInOctet = 0; |
| } |
| |
| private int readBits(int bits) throws IOException { |
| int value = 0; |
| while (bits > 0) { |
| if (_bitsLeftInOctet == 0) { |
| _b = _octetBuffer[_octetBufferStart++] & 0xFF; |
| _bitsLeftInOctet = 8; |
| } |
| int bit = ((_b & (1 << --_bitsLeftInOctet)) > 0) ? 1 : 0; |
| value |= (bit << --bits); |
| } |
| |
| return value; |
| } |
| |
| protected final void decodeUtf8StringAsCharBuffer() throws IOException { |
| ensureOctetBufferSize(); |
| decodeUtf8StringIntoCharBuffer(); |
| } |
| |
| protected final String decodeUtf8StringAsString() throws IOException { |
| decodeUtf8StringAsCharBuffer(); |
| return new String(_charBuffer, 0, _charBufferLength); |
| } |
| |
| protected final void decodeUtf16StringAsCharBuffer() throws IOException { |
| ensureOctetBufferSize(); |
| decodeUtf16StringIntoCharBuffer(); |
| } |
| |
| protected final String decodeUtf16StringAsString() throws IOException { |
| decodeUtf16StringAsCharBuffer(); |
| return new String(_charBuffer, 0, _charBufferLength); |
| } |
| |
| private void ensureOctetBufferSize() throws IOException { |
| if (_octetBufferEnd < (_octetBufferOffset + _octetBufferLength)) { |
| final int octetsInBuffer = _octetBufferEnd - _octetBufferOffset; |
| |
| if (_octetBuffer.length < _octetBufferLength) { |
| // Length to read is too large, resize the buffer |
| byte[] newOctetBuffer = new byte[_octetBufferLength]; |
| // Move partially read octets to the start of the buffer |
| System.arraycopy(_octetBuffer, _octetBufferOffset, newOctetBuffer, 0, octetsInBuffer); |
| _octetBuffer = newOctetBuffer; |
| } else { |
| // Move partially read octets to the start of the buffer |
| System.arraycopy(_octetBuffer, _octetBufferOffset, _octetBuffer, 0, octetsInBuffer); |
| } |
| _octetBufferOffset = 0; |
| |
| // Read as many octets as possible to fill the buffer |
| final int octetsRead = _s.read(_octetBuffer, octetsInBuffer, _octetBuffer.length - octetsInBuffer); |
| if (octetsRead < 0) { |
| throw new EOFException("Unexpeceted EOF"); |
| } |
| _octetBufferEnd = octetsInBuffer + octetsRead; |
| |
| // Check if the number of octets that have been read is not enough |
| // This can happen when underlying non-blocking is used to read |
| if (_octetBufferEnd < _octetBufferLength) { |
| repeatedRead(); |
| } |
| } |
| } |
| |
| private void repeatedRead() throws IOException { |
| // Check if the number of octets that have been read is not enough |
| while (_octetBufferEnd < _octetBufferLength) { |
| // Read as many octets as possible to fill the buffer |
| final int octetsRead = _s.read(_octetBuffer, _octetBufferEnd, _octetBuffer.length - _octetBufferEnd); |
| if (octetsRead < 0) { |
| throw new EOFException("Unexpeceted EOF"); |
| } |
| _octetBufferEnd += octetsRead; |
| } |
| } |
| |
| protected final void decodeUtf8StringIntoCharBuffer() throws IOException { |
| if (_charBuffer.length < _octetBufferLength) { |
| _charBuffer = new char[_octetBufferLength]; |
| } |
| |
| _charBufferLength = 0; |
| final int end = _octetBufferLength + _octetBufferOffset; |
| int b1; |
| while (end != _octetBufferOffset) { |
| b1 = _octetBuffer[_octetBufferOffset++] & 0xFF; |
| if (DecoderStateTables.UTF8[b1] == DecoderStateTables.UTF8_ONE_BYTE) { |
| _charBuffer[_charBufferLength++] = (char) b1; |
| } else { |
| decodeTwoToFourByteUtf8Character(b1, end); |
| } |
| } |
| } |
| |
| private void decodeTwoToFourByteUtf8Character(int b1, int end) throws IOException { |
| switch(DecoderStateTables.UTF8[b1]) { |
| case DecoderStateTables.UTF8_TWO_BYTES: |
| { |
| // Decode byte 2 |
| if (end == _octetBufferOffset) { |
| decodeUtf8StringLengthTooSmall(); |
| } |
| final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF; |
| if ((b2 & 0xC0) != 0x80) { |
| decodeUtf8StringIllegalState(); |
| } |
| |
| // Character guaranteed to be in [0x20, 0xD7FF] range |
| // since a character encoded in two bytes will be in the |
| // range [0x80, 0x1FFF] |
| _charBuffer[_charBufferLength++] = (char) ( |
| ((b1 & 0x1F) << 6) |
| | (b2 & 0x3F)); |
| break; |
| } |
| case DecoderStateTables.UTF8_THREE_BYTES: |
| final char c = decodeUtf8ThreeByteChar(end, b1); |
| if (XMLChar.isContent(c)) { |
| _charBuffer[_charBufferLength++] = c; |
| break; |
| } else { |
| decodeUtf8StringIllegalState(); |
| } |
| case DecoderStateTables.UTF8_FOUR_BYTES: |
| { |
| final int supplemental = decodeUtf8FourByteChar(end, b1); |
| if (XMLChar.isContent(supplemental)) { |
| _charBuffer[_charBufferLength++] = _utf8_highSurrogate; |
| _charBuffer[_charBufferLength++] = _utf8_lowSurrogate; |
| } else { |
| decodeUtf8StringIllegalState(); |
| } |
| break; |
| } |
| default: |
| decodeUtf8StringIllegalState(); |
| } |
| } |
| |
| protected final void decodeUtf8NCNameIntoCharBuffer() throws IOException { |
| _charBufferLength = 0; |
| if (_charBuffer.length < _octetBufferLength) { |
| _charBuffer = new char[_octetBufferLength]; |
| } |
| |
| final int end = _octetBufferLength + _octetBufferOffset; |
| |
| int b1 = _octetBuffer[_octetBufferOffset++] & 0xFF; |
| if (DecoderStateTables.UTF8_NCNAME[b1] == DecoderStateTables.UTF8_NCNAME_NCNAME) { |
| _charBuffer[_charBufferLength++] = (char) b1; |
| } else { |
| decodeUtf8NCNameStartTwoToFourByteCharacters(b1, end); |
| } |
| |
| while (end != _octetBufferOffset) { |
| b1 = _octetBuffer[_octetBufferOffset++] & 0xFF; |
| if (DecoderStateTables.UTF8_NCNAME[b1] < DecoderStateTables.UTF8_TWO_BYTES) { |
| _charBuffer[_charBufferLength++] = (char) b1; |
| } else { |
| decodeUtf8NCNameTwoToFourByteCharacters(b1, end); |
| } |
| } |
| } |
| |
| private void decodeUtf8NCNameStartTwoToFourByteCharacters(int b1, int end) throws IOException { |
| switch(DecoderStateTables.UTF8_NCNAME[b1]) { |
| case DecoderStateTables.UTF8_TWO_BYTES: |
| { |
| // Decode byte 2 |
| if (end == _octetBufferOffset) { |
| decodeUtf8StringLengthTooSmall(); |
| } |
| final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF; |
| if ((b2 & 0xC0) != 0x80) { |
| decodeUtf8StringIllegalState(); |
| } |
| |
| final char c = (char) ( |
| ((b1 & 0x1F) << 6) |
| | (b2 & 0x3F)); |
| if (XMLChar.isNCNameStart(c)) { |
| _charBuffer[_charBufferLength++] = c; |
| break; |
| } else { |
| decodeUtf8NCNameIllegalState(); |
| } |
| } |
| case DecoderStateTables.UTF8_THREE_BYTES: |
| final char c = decodeUtf8ThreeByteChar(end, b1); |
| if (XMLChar.isNCNameStart(c)) { |
| _charBuffer[_charBufferLength++] = c; |
| break; |
| } else { |
| decodeUtf8NCNameIllegalState(); |
| } |
| break; |
| case DecoderStateTables.UTF8_FOUR_BYTES: |
| { |
| final int supplemental = decodeUtf8FourByteChar(end, b1); |
| if (XMLChar.isNCNameStart(supplemental)) { |
| _charBuffer[_charBufferLength++] = _utf8_highSurrogate; |
| _charBuffer[_charBufferLength++] = _utf8_lowSurrogate; |
| } else { |
| decodeUtf8NCNameIllegalState(); |
| } |
| break; |
| } |
| case DecoderStateTables.UTF8_NCNAME_NCNAME_CHAR: |
| default: |
| decodeUtf8NCNameIllegalState(); |
| } |
| |
| } |
| |
| private void decodeUtf8NCNameTwoToFourByteCharacters(int b1, int end) throws IOException { |
| switch(DecoderStateTables.UTF8_NCNAME[b1]) { |
| case DecoderStateTables.UTF8_TWO_BYTES: |
| { |
| // Decode byte 2 |
| if (end == _octetBufferOffset) { |
| decodeUtf8StringLengthTooSmall(); |
| } |
| final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF; |
| if ((b2 & 0xC0) != 0x80) { |
| decodeUtf8StringIllegalState(); |
| } |
| |
| final char c = (char) ( |
| ((b1 & 0x1F) << 6) |
| | (b2 & 0x3F)); |
| if (XMLChar.isNCName(c)) { |
| _charBuffer[_charBufferLength++] = c; |
| break; |
| } else { |
| decodeUtf8NCNameIllegalState(); |
| } |
| } |
| case DecoderStateTables.UTF8_THREE_BYTES: |
| final char c = decodeUtf8ThreeByteChar(end, b1); |
| if (XMLChar.isNCName(c)) { |
| _charBuffer[_charBufferLength++] = c; |
| break; |
| } else { |
| decodeUtf8NCNameIllegalState(); |
| } |
| break; |
| case DecoderStateTables.UTF8_FOUR_BYTES: |
| { |
| final int supplemental = decodeUtf8FourByteChar(end, b1); |
| if (XMLChar.isNCName(supplemental)) { |
| _charBuffer[_charBufferLength++] = _utf8_highSurrogate; |
| _charBuffer[_charBufferLength++] = _utf8_lowSurrogate; |
| } else { |
| decodeUtf8NCNameIllegalState(); |
| } |
| break; |
| } |
| default: |
| decodeUtf8NCNameIllegalState(); |
| } |
| } |
| |
| private char decodeUtf8ThreeByteChar(int end, int b1) throws IOException { |
| // Decode byte 2 |
| if (end == _octetBufferOffset) { |
| decodeUtf8StringLengthTooSmall(); |
| } |
| final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF; |
| if ((b2 & 0xC0) != 0x80 |
| || (b1 == 0xED && b2 >= 0xA0) |
| || ((b1 & 0x0F) == 0 && (b2 & 0x20) == 0)) { |
| decodeUtf8StringIllegalState(); |
| } |
| |
| // Decode byte 3 |
| if (end == _octetBufferOffset) { |
| decodeUtf8StringLengthTooSmall(); |
| } |
| final int b3 = _octetBuffer[_octetBufferOffset++] & 0xFF; |
| if ((b3 & 0xC0) != 0x80) { |
| decodeUtf8StringIllegalState(); |
| } |
| |
| return (char) ( |
| (b1 & 0x0F) << 12 |
| | (b2 & 0x3F) << 6 |
| | (b3 & 0x3F)); |
| } |
| |
| private char _utf8_highSurrogate; |
| private char _utf8_lowSurrogate; |
| |
| private int decodeUtf8FourByteChar(int end, int b1) throws IOException { |
| // Decode byte 2 |
| if (end == _octetBufferOffset) { |
| decodeUtf8StringLengthTooSmall(); |
| } |
| final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF; |
| if ((b2 & 0xC0) != 0x80 |
| || ((b2 & 0x30) == 0 && (b1 & 0x07) == 0)) { |
| decodeUtf8StringIllegalState(); |
| } |
| |
| // Decode byte 3 |
| if (end == _octetBufferOffset) { |
| decodeUtf8StringLengthTooSmall(); |
| } |
| final int b3 = _octetBuffer[_octetBufferOffset++] & 0xFF; |
| if ((b3 & 0xC0) != 0x80) { |
| decodeUtf8StringIllegalState(); |
| } |
| |
| // Decode byte 4 |
| if (end == _octetBufferOffset) { |
| decodeUtf8StringLengthTooSmall(); |
| } |
| final int b4 = _octetBuffer[_octetBufferOffset++] & 0xFF; |
| if ((b4 & 0xC0) != 0x80) { |
| decodeUtf8StringIllegalState(); |
| } |
| |
| final int uuuuu = ((b1 << 2) & 0x001C) | ((b2 >> 4) & 0x0003); |
| if (uuuuu > 0x10) { |
| decodeUtf8StringIllegalState(); |
| } |
| final int wwww = uuuuu - 1; |
| |
| _utf8_highSurrogate = (char) (0xD800 | |
| ((wwww << 6) & 0x03C0) | ((b2 << 2) & 0x003C) | |
| ((b3 >> 4) & 0x0003)); |
| _utf8_lowSurrogate = (char) (0xDC00 | ((b3 << 6) & 0x03C0) | (b4 & 0x003F)); |
| |
| return XMLChar.supplemental(_utf8_highSurrogate, _utf8_lowSurrogate); |
| } |
| |
| private void decodeUtf8StringLengthTooSmall() throws IOException { |
| throw new IOException(CommonResourceBundle.getInstance().getString("message.deliminatorTooSmall")); |
| } |
| |
| private void decodeUtf8StringIllegalState() throws IOException { |
| throw new IOException(CommonResourceBundle.getInstance().getString("message.UTF8Encoded")); |
| } |
| |
| private void decodeUtf8NCNameIllegalState() throws IOException { |
| throw new IOException(CommonResourceBundle.getInstance().getString("message.UTF8EncodedNCName")); |
| } |
| |
| private void decodeUtf16StringIntoCharBuffer() throws IOException { |
| _charBufferLength = _octetBufferLength / 2; |
| if (_charBuffer.length < _charBufferLength) { |
| _charBuffer = new char[_charBufferLength]; |
| } |
| |
| for (int i = 0; i < _charBufferLength; i++) { |
| final char c = (char)((read() << 8) | read()); |
| // TODO check c is a valid Char character |
| _charBuffer[i] = c; |
| } |
| |
| } |
| |
| protected String createQualifiedNameString(char[] first, String second) { |
| final int l1 = first.length; |
| final int l2 = second.length(); |
| final int total = l1 + l2 + 1; |
| if (total < _charBuffer.length) { |
| System.arraycopy(first, 0, _charBuffer, 0, l1); |
| _charBuffer[l1] = ':'; |
| second.getChars(0, l2, _charBuffer, l1 + 1); |
| return new String(_charBuffer, 0, total); |
| } else { |
| StringBuffer b = new StringBuffer(new String(first)); |
| b.append(':'); |
| b.append(second); |
| return b.toString(); |
| } |
| } |
| |
| protected final int read() throws IOException { |
| if (_octetBufferOffset < _octetBufferEnd) { |
| return _octetBuffer[_octetBufferOffset++] & 0xFF; |
| } else { |
| _octetBufferEnd = _s.read(_octetBuffer); |
| if (_octetBufferEnd < 0) { |
| throw new EOFException(CommonResourceBundle.getInstance().getString("message.EOF")); |
| } |
| |
| _octetBufferOffset = 1; |
| return _octetBuffer[0] & 0xFF; |
| } |
| } |
| |
| protected final int peak() throws IOException { |
| if (_octetBufferOffset < _octetBufferEnd) { |
| return _octetBuffer[_octetBufferOffset] & 0xFF; |
| } else { |
| _octetBufferEnd = _s.read(_octetBuffer); |
| if (_octetBufferEnd < 0) { |
| throw new EOFException(CommonResourceBundle.getInstance().getString("message.EOF")); |
| } |
| |
| _octetBufferOffset = 0; |
| return _octetBuffer[0] & 0xFF; |
| } |
| } |
| |
| protected class EncodingAlgorithmInputStream extends InputStream { |
| |
| public int read() throws IOException { |
| if (_octetBufferStart < _octetBufferOffset) { |
| return (_octetBuffer[_octetBufferStart++] & 0xFF); |
| } else { |
| return -1; |
| } |
| } |
| |
| public int read(byte b[]) throws IOException { |
| return read(b, 0, b.length); |
| } |
| |
| public int read(byte b[], int off, int len) throws IOException { |
| if (b == null) { |
| throw new NullPointerException(); |
| } else if ((off < 0) || (off > b.length) || (len < 0) || |
| ((off + len) > b.length) || ((off + len) < 0)) { |
| throw new IndexOutOfBoundsException(); |
| } else if (len == 0) { |
| return 0; |
| } |
| |
| final int newOctetBufferStart = _octetBufferStart + len; |
| if (newOctetBufferStart < _octetBufferOffset) { |
| System.arraycopy(_octetBuffer, _octetBufferStart, b, off, len); |
| _octetBufferStart = newOctetBufferStart; |
| return len; |
| } else if (_octetBufferStart < _octetBufferOffset) { |
| final int bytesToRead = _octetBufferOffset - _octetBufferStart; |
| System.arraycopy(_octetBuffer, _octetBufferStart, b, off, bytesToRead); |
| _octetBufferStart += bytesToRead; |
| return bytesToRead; |
| } else { |
| return -1; |
| } |
| } |
| } |
| |
| protected final boolean _isFastInfosetDocument() throws IOException { |
| // Fill up the octet buffer |
| peak(); |
| |
| _octetBufferLength = EncodingConstants.BINARY_HEADER.length; |
| ensureOctetBufferSize(); |
| _octetBufferOffset += _octetBufferLength; |
| |
| // Check for binary header |
| if (_octetBuffer[0] != EncodingConstants.BINARY_HEADER[0] || |
| _octetBuffer[1] != EncodingConstants.BINARY_HEADER[1] || |
| _octetBuffer[2] != EncodingConstants.BINARY_HEADER[2] || |
| _octetBuffer[3] != EncodingConstants.BINARY_HEADER[3]) { |
| |
| // Check for each form of XML declaration |
| for (int i = 0; i < EncodingConstants.XML_DECLARATION_VALUES.length; i++) { |
| _octetBufferLength = EncodingConstants.XML_DECLARATION_VALUES[i].length - _octetBufferOffset; |
| ensureOctetBufferSize(); |
| _octetBufferOffset += _octetBufferLength; |
| |
| // Check XML declaration |
| if (arrayEquals(_octetBuffer, 0, |
| EncodingConstants.XML_DECLARATION_VALUES[i], |
| EncodingConstants.XML_DECLARATION_VALUES[i].length)) { |
| _octetBufferLength = EncodingConstants.BINARY_HEADER.length; |
| ensureOctetBufferSize(); |
| |
| // Check for binary header |
| if (_octetBuffer[_octetBufferOffset++] != EncodingConstants.BINARY_HEADER[0] || |
| _octetBuffer[_octetBufferOffset++] != EncodingConstants.BINARY_HEADER[1] || |
| _octetBuffer[_octetBufferOffset++] != EncodingConstants.BINARY_HEADER[2] || |
| _octetBuffer[_octetBufferOffset++] != EncodingConstants.BINARY_HEADER[3]) { |
| return false; |
| } else { |
| // Fast Infoset document with XML declaration and binary header |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| // Fast Infoset document with binary header |
| return true; |
| } |
| |
| private boolean arrayEquals(byte[] b1, int offset, byte[] b2, int length) { |
| for (int i = 0; i < length; i++) { |
| if (b1[offset + i] != b2[i]) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| static public boolean isFastInfosetDocument(InputStream s) throws IOException { |
| // TODO |
| // Check for <?xml declaration with 'finf' encoding |
| |
| final byte[] header = new byte[4]; |
| s.read(header); |
| if (header[0] != EncodingConstants.BINARY_HEADER[0] || |
| header[1] != EncodingConstants.BINARY_HEADER[1] || |
| header[2] != EncodingConstants.BINARY_HEADER[2] || |
| header[3] != EncodingConstants.BINARY_HEADER[3]) { |
| return false; |
| } |
| |
| // TODO |
| return true; |
| } |
| } |