Thu, 31 Aug 2017 15:18:52 +0800
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;
1003 }
1004 case DecoderStateTables.ISTRING_SMALL_LENGTH:
1005 case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_29:
1006 case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_36:
1007 {
1008 _octetBufferLength = b + 1;
1009 final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString();
1010 _prefixIndex = _v.prefix.add(s);
1011 return s;
1012 }
1013 case DecoderStateTables.ISTRING_MEDIUM_LENGTH:
1014 {
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;
1019 }
1020 case DecoderStateTables.ISTRING_LARGE_LENGTH:
1021 {
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;
1030 }
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"));
1038 }
1039 return EncodingConstants.XML_NAMESPACE_PREFIX;
1040 } else {
1041 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.missingNamespaceName"));
1042 }
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"));
1056 }
1057 }
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"));
1072 }
1073 return EncodingConstants.XML_NAMESPACE_PREFIX;
1074 } else {
1075 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.missingNamespaceName"));
1076 }
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"));
1090 }
1091 }
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:
1104 {
1105 _octetBufferLength = b + 1;
1106 final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString();
1107 _namespaceNameIndex = _v.namespaceName.add(s);
1108 return s;
1109 }
1110 case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_29:
1111 {
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"));
1117 }
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;
1123 }
1124 case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_36:
1125 {
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"));
1131 }
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;
1137 }
1138 case DecoderStateTables.ISTRING_MEDIUM_LENGTH:
1139 {
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;
1144 }
1145 case DecoderStateTables.ISTRING_LARGE_LENGTH:
1146 {
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;
1155 }
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"));
1162 }
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"));
1176 }
1177 }
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"));
1191 }
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"));
1205 }
1206 }
1208 private boolean compareCharsWithCharBufferFromEndToStart(char[] c) {
1209 int i = _charBufferLength ;
1210 while (--i >= 0) {
1211 if (c[i] != _charBuffer[i]) {
1212 return false;
1213 }
1214 }
1215 return true;
1216 }
1218 /*
1219 * C.22
1220 */
1221 protected final String decodeNonEmptyOctetStringOnSecondBitAsUtf8String() throws FastInfosetException, IOException {
1222 decodeNonEmptyOctetStringOnSecondBitAsUtf8CharArray();
1223 return new String(_charBuffer, 0, _charBufferLength);
1224 }
1226 /*
1227 * C.22
1228 */
1229 protected final void decodeNonEmptyOctetStringOnSecondBitAsUtf8CharArray() throws FastInfosetException, IOException {
1230 decodeNonEmptyOctetStringLengthOnSecondBit();
1231 decodeUtf8StringAsCharBuffer();
1232 }
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:
1247 {
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;
1254 }
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"));
1260 }
1261 }
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"));
1282 }
1283 }
1285 protected final void decodeHeader() throws FastInfosetException, IOException {
1286 if (!_isFastInfosetDocument()) {
1287 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.notFIDocument"));
1288 }
1289 }
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)}));
1299 }
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"));
1306 }
1307 }
1309 protected final String decodeRestrictedAlphabetAsString() throws FastInfosetException, IOException {
1310 decodeRestrictedAlphabetAsCharBuffer();
1311 return new String(_charBuffer, 0, _charBufferLength);
1312 }
1314 protected final String decodeRAOctetsAsString(char[] restrictedAlphabet) throws FastInfosetException, IOException {
1315 decodeAlphabetOctetsAsCharBuffer(restrictedAlphabet);
1316 return new String(_charBuffer, 0, _charBufferLength);
1317 }
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];
1324 }
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];
1331 }
1332 v = _octetBuffer[_octetBufferStart++] & 0xFF;
1333 _charBuffer[_charBufferLength++] = restrictedAlphabet[v >> 4];
1334 v &= 0x0F;
1335 if (v != 0x0F) {
1336 _charBuffer[_charBufferLength++] = restrictedAlphabet[v & 0x0F];
1337 }
1338 }
1340 protected final void decodeAlphabetOctetsAsCharBuffer(char[] restrictedAlphabet) throws FastInfosetException, IOException {
1341 if (restrictedAlphabet.length < 2) {
1342 throw new IllegalArgumentException(CommonResourceBundle.getInstance().getString("message.alphabetMustContain2orMoreChars"));
1343 }
1345 int bitsPerCharacter = 1;
1346 while ((1 << bitsPerCharacter) <= restrictedAlphabet.length) {
1347 bitsPerCharacter++;
1348 }
1349 final int terminatingValue = (1 << bitsPerCharacter) - 1;
1351 int characters = (_octetBufferLength << 3) / bitsPerCharacter;
1352 if (characters == 0) {
1353 throw new IOException("");
1354 }
1356 _charBufferLength = 0;
1357 if (_charBuffer.length < characters) {
1358 _charBuffer = new char[characters];
1359 }
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"));
1368 }
1369 break;
1370 }
1371 _charBuffer[_charBufferLength++] = restrictedAlphabet[value];
1372 }
1373 }
1375 private int _bitsLeftInOctet;
1377 private void resetBits() {
1378 _bitsLeftInOctet = 0;
1379 }
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;
1387 }
1388 int bit = ((_b & (1 << --_bitsLeftInOctet)) > 0) ? 1 : 0;
1389 value |= (bit << --bits);
1390 }
1392 return value;
1393 }
1395 protected final void decodeUtf8StringAsCharBuffer() throws IOException {
1396 ensureOctetBufferSize();
1397 decodeUtf8StringIntoCharBuffer();
1398 }
1400 protected final void decodeUtf8StringAsCharBuffer(char[] ch, int offset) throws IOException {
1401 ensureOctetBufferSize();
1402 decodeUtf8StringIntoCharBuffer(ch, offset);
1403 }
1405 protected final String decodeUtf8StringAsString() throws IOException {
1406 decodeUtf8StringAsCharBuffer();
1407 return new String(_charBuffer, 0, _charBufferLength);
1408 }
1410 protected final void decodeUtf16StringAsCharBuffer() throws IOException {
1411 ensureOctetBufferSize();
1412 decodeUtf16StringIntoCharBuffer();
1413 }
1415 protected final String decodeUtf16StringAsString() throws IOException {
1416 decodeUtf16StringAsCharBuffer();
1417 return new String(_charBuffer, 0, _charBufferLength);
1418 }
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);
1433 }
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");
1440 }
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();
1447 }
1448 }
1449 }
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");
1458 }
1459 _octetBufferEnd += octetsRead;
1460 }
1461 }
1463 protected final void decodeUtf8StringIntoCharBuffer() throws IOException {
1464 if (_charBuffer.length < _octetBufferLength) {
1465 _charBuffer = new char[_octetBufferLength];
1466 }
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);
1477 }
1478 }
1479 }
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);
1491 }
1492 }
1493 _charBufferLength -= offset;
1494 }
1496 private void decodeTwoToFourByteUtf8Character(int b1, int end) throws IOException {
1497 switch(DecoderStateTables.UTF8(b1)) {
1498 case DecoderStateTables.UTF8_TWO_BYTES:
1499 {
1500 // Decode byte 2
1501 if (end == _octetBufferOffset) {
1502 decodeUtf8StringLengthTooSmall();
1503 }
1504 final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF;
1505 if ((b2 & 0xC0) != 0x80) {
1506 decodeUtf8StringIllegalState();
1507 }
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;
1516 }
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();
1523 }
1524 break;
1525 case DecoderStateTables.UTF8_FOUR_BYTES:
1526 {
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();
1533 }
1534 break;
1535 }
1536 default:
1537 decodeUtf8StringIllegalState();
1538 }
1539 }
1541 private void decodeTwoToFourByteUtf8Character(char ch[], int b1, int end) throws IOException {
1542 switch(DecoderStateTables.UTF8(b1)) {
1543 case DecoderStateTables.UTF8_TWO_BYTES:
1544 {
1545 // Decode byte 2
1546 if (end == _octetBufferOffset) {
1547 decodeUtf8StringLengthTooSmall();
1548 }
1549 final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF;
1550 if ((b2 & 0xC0) != 0x80) {
1551 decodeUtf8StringIllegalState();
1552 }
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;
1561 }
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();
1568 }
1569 break;
1570 case DecoderStateTables.UTF8_FOUR_BYTES:
1571 {
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();
1578 }
1579 break;
1580 }
1581 default:
1582 decodeUtf8StringIllegalState();
1583 }
1584 }
1586 protected final void decodeUtf8NCNameIntoCharBuffer() throws IOException {
1587 _charBufferLength = 0;
1588 if (_charBuffer.length < _octetBufferLength) {
1589 _charBuffer = new char[_octetBufferLength];
1590 }
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);
1599 }
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);
1607 }
1608 }
1609 }
1611 private void decodeUtf8NCNameStartTwoToFourByteCharacters(int b1, int end) throws IOException {
1612 switch(DecoderStateTables.UTF8_NCNAME(b1)) {
1613 case DecoderStateTables.UTF8_TWO_BYTES:
1614 {
1615 // Decode byte 2
1616 if (end == _octetBufferOffset) {
1617 decodeUtf8StringLengthTooSmall();
1618 }
1619 final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF;
1620 if ((b2 & 0xC0) != 0x80) {
1621 decodeUtf8StringIllegalState();
1622 }
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();
1631 }
1632 break;
1633 }
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();
1640 }
1641 break;
1642 case DecoderStateTables.UTF8_FOUR_BYTES:
1643 {
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();
1650 }
1651 break;
1652 }
1653 case DecoderStateTables.UTF8_NCNAME_NCNAME_CHAR:
1654 default:
1655 decodeUtf8NCNameIllegalState();
1656 }
1658 }
1660 private void decodeUtf8NCNameTwoToFourByteCharacters(int b1, int end) throws IOException {
1661 switch(DecoderStateTables.UTF8_NCNAME(b1)) {
1662 case DecoderStateTables.UTF8_TWO_BYTES:
1663 {
1664 // Decode byte 2
1665 if (end == _octetBufferOffset) {
1666 decodeUtf8StringLengthTooSmall();
1667 }
1668 final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF;
1669 if ((b2 & 0xC0) != 0x80) {
1670 decodeUtf8StringIllegalState();
1671 }
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();
1680 }
1681 break;
1682 }
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();
1689 }
1690 break;
1691 case DecoderStateTables.UTF8_FOUR_BYTES:
1692 {
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();
1699 }
1700 break;
1701 }
1702 default:
1703 decodeUtf8NCNameIllegalState();
1704 }
1705 }
1707 private char decodeUtf8ThreeByteChar(int end, int b1) throws IOException {
1708 // Decode byte 2
1709 if (end == _octetBufferOffset) {
1710 decodeUtf8StringLengthTooSmall();
1711 }
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();
1717 }
1719 // Decode byte 3
1720 if (end == _octetBufferOffset) {
1721 decodeUtf8StringLengthTooSmall();
1722 }
1723 final int b3 = _octetBuffer[_octetBufferOffset++] & 0xFF;
1724 if ((b3 & 0xC0) != 0x80) {
1725 decodeUtf8StringIllegalState();
1726 }
1728 return (char) (
1729 (b1 & 0x0F) << 12
1730 | (b2 & 0x3F) << 6
1731 | (b3 & 0x3F));
1732 }
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();
1741 }
1742 final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF;
1743 if ((b2 & 0xC0) != 0x80
1744 || ((b2 & 0x30) == 0 && (b1 & 0x07) == 0)) {
1745 decodeUtf8StringIllegalState();
1746 }
1748 // Decode byte 3
1749 if (end == _octetBufferOffset) {
1750 decodeUtf8StringLengthTooSmall();
1751 }
1752 final int b3 = _octetBuffer[_octetBufferOffset++] & 0xFF;
1753 if ((b3 & 0xC0) != 0x80) {
1754 decodeUtf8StringIllegalState();
1755 }
1757 // Decode byte 4
1758 if (end == _octetBufferOffset) {
1759 decodeUtf8StringLengthTooSmall();
1760 }
1761 final int b4 = _octetBuffer[_octetBufferOffset++] & 0xFF;
1762 if ((b4 & 0xC0) != 0x80) {
1763 decodeUtf8StringIllegalState();
1764 }
1766 final int uuuuu = ((b1 << 2) & 0x001C) | ((b2 >> 4) & 0x0003);
1767 if (uuuuu > 0x10) {
1768 decodeUtf8StringIllegalState();
1769 }
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);
1778 }
1780 private void decodeUtf8StringLengthTooSmall() throws IOException {
1781 throw new IOException(CommonResourceBundle.getInstance().getString("message.deliminatorTooSmall"));
1782 }
1784 private void decodeUtf8StringIllegalState() throws IOException {
1785 throw new IOException(CommonResourceBundle.getInstance().getString("message.UTF8Encoded"));
1786 }
1788 private void decodeUtf8NCNameIllegalState() throws IOException {
1789 throw new IOException(CommonResourceBundle.getInstance().getString("message.UTF8EncodedNCName"));
1790 }
1792 private void decodeUtf16StringIntoCharBuffer() throws IOException {
1793 _charBufferLength = _octetBufferLength / 2;
1794 if (_charBuffer.length < _charBufferLength) {
1795 _charBuffer = new char[_charBufferLength];
1796 }
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;
1802 }
1804 }
1806 protected String createQualifiedNameString(String second) {
1807 return createQualifiedNameString(XMLNS_NAMESPACE_PREFIX_CHARS, second);
1808 }
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();
1824 }
1825 }
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"));
1834 }
1836 _octetBufferOffset = 1;
1837 return _octetBuffer[0] & 0xFF;
1838 }
1839 }
1841 protected final void closeIfRequired() throws IOException {
1842 if (_s != null && _needForceStreamClose) {
1843 _s.close();
1844 }
1845 }
1847 protected final int peek() throws IOException {
1848 return peek(null);
1849 }
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();
1857 }
1859 _octetBufferEnd = _s.read(_octetBuffer);
1860 if (_octetBufferEnd < 0) {
1861 throw new EOFException(CommonResourceBundle.getInstance().getString("message.EOF"));
1862 }
1864 _octetBufferOffset = 0;
1865 return _octetBuffer[0] & 0xFF;
1866 }
1867 }
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();
1875 }
1877 int offset = 0;
1878 if (_octetBufferOffset < _octetBufferEnd) {
1879 _octetBuffer[0] = _octetBuffer[_octetBufferOffset];
1880 offset = 1;
1881 }
1882 _octetBufferEnd = _s.read(_octetBuffer, offset, _octetBuffer.length - offset);
1884 if (_octetBufferEnd < 0) {
1885 throw new EOFException(CommonResourceBundle.getInstance().getString("message.EOF"));
1886 }
1888 _octetBufferOffset = 0;
1889 return _octetBuffer[1] & 0xFF;
1890 }
1891 }
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;
1900 }
1901 }
1903 @Override
1904 public int read(byte b[]) throws IOException {
1905 return read(b, 0, b.length);
1906 }
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;
1917 }
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;
1931 }
1932 }
1933 }
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;
1971 }
1972 }
1973 }
1975 return false;
1976 }
1978 // Fast Infoset document with binary header
1979 return true;
1980 }
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;
1986 }
1987 }
1989 return true;
1990 }
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;
2005 }
2007 // TODO
2008 return true;
2009 }
2010 }