1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/Encoder.java Wed Apr 27 01:27:09 2016 +0800 1.3 @@ -0,0 +1,2594 @@ 1.4 +/* 1.5 + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + * 1.28 + * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC. 1.29 + */ 1.30 + 1.31 +package com.sun.xml.internal.fastinfoset; 1.32 + 1.33 +import com.sun.xml.internal.fastinfoset.algorithm.BuiltInEncodingAlgorithmFactory; 1.34 +import com.sun.xml.internal.fastinfoset.org.apache.xerces.util.XMLChar; 1.35 +import com.sun.xml.internal.fastinfoset.util.CharArrayIntMap; 1.36 +import com.sun.xml.internal.fastinfoset.util.KeyIntMap; 1.37 +import com.sun.xml.internal.fastinfoset.util.LocalNameQualifiedNamesMap; 1.38 +import com.sun.xml.internal.fastinfoset.util.StringIntMap; 1.39 +import com.sun.xml.internal.fastinfoset.vocab.SerializerVocabulary; 1.40 +import java.io.IOException; 1.41 +import java.io.OutputStream; 1.42 +import java.util.HashMap; 1.43 +import java.util.Map; 1.44 +import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithm; 1.45 +import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmException; 1.46 +import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmIndexes; 1.47 +import com.sun.xml.internal.org.jvnet.fastinfoset.ExternalVocabulary; 1.48 +import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetException; 1.49 +import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetSerializer; 1.50 +import com.sun.xml.internal.org.jvnet.fastinfoset.RestrictedAlphabet; 1.51 +import com.sun.xml.internal.org.jvnet.fastinfoset.VocabularyApplicationData; 1.52 +import org.xml.sax.helpers.DefaultHandler; 1.53 + 1.54 +/** 1.55 + * Abstract encoder for developing concrete encoders. 1.56 + * 1.57 + * Concrete implementations extending Encoder will utilize methods on Encoder 1.58 + * to encode XML infoset according to the Fast Infoset standard. It is the 1.59 + * responsibility of the concrete implementation to ensure that methods are 1.60 + * invoked in the correct order to produce a valid fast infoset document. 1.61 + * 1.62 + * <p> 1.63 + * This class extends org.sax.xml.DefaultHandler so that concrete SAX 1.64 + * implementations can be used with javax.xml.parsers.SAXParser and the parse 1.65 + * methods that take org.sax.xml.DefaultHandler as a parameter. 1.66 + * 1.67 + * <p> 1.68 + * Buffering of octets that are written to an {@link java.io.OutputStream} is 1.69 + * supported in a similar manner to a {@link java.io.BufferedOutputStream}. 1.70 + * Combining buffering with encoding enables better performance. 1.71 + * 1.72 + * <p> 1.73 + * More than one fast infoset document may be encoded to the 1.74 + * {@link java.io.OutputStream}. 1.75 + * 1.76 + */ 1.77 +public abstract class Encoder extends DefaultHandler implements FastInfosetSerializer { 1.78 + 1.79 + /** 1.80 + * Character encoding scheme system property for the encoding 1.81 + * of content and attribute values. 1.82 + */ 1.83 + public static final String CHARACTER_ENCODING_SCHEME_SYSTEM_PROPERTY = 1.84 + "com.sun.xml.internal.fastinfoset.serializer.character-encoding-scheme"; 1.85 + 1.86 + /** 1.87 + * Default character encoding scheme system property for the encoding 1.88 + * of content and attribute values. 1.89 + */ 1.90 + protected static final String _characterEncodingSchemeSystemDefault = getDefaultEncodingScheme(); 1.91 + 1.92 + private static String getDefaultEncodingScheme() { 1.93 + String p = System.getProperty(CHARACTER_ENCODING_SCHEME_SYSTEM_PROPERTY, 1.94 + UTF_8); 1.95 + if (p.equals(UTF_16BE)) { 1.96 + return UTF_16BE; 1.97 + } else { 1.98 + return UTF_8; 1.99 + } 1.100 + } 1.101 + 1.102 + private static int[] NUMERIC_CHARACTERS_TABLE; 1.103 + 1.104 + private static int[] DATE_TIME_CHARACTERS_TABLE; 1.105 + 1.106 + static { 1.107 + NUMERIC_CHARACTERS_TABLE = new int[maxCharacter(RestrictedAlphabet.NUMERIC_CHARACTERS) + 1]; 1.108 + DATE_TIME_CHARACTERS_TABLE = new int[maxCharacter(RestrictedAlphabet.DATE_TIME_CHARACTERS) + 1]; 1.109 + 1.110 + for (int i = 0; i < NUMERIC_CHARACTERS_TABLE.length ; i++) { 1.111 + NUMERIC_CHARACTERS_TABLE[i] = -1; 1.112 + } 1.113 + for (int i = 0; i < DATE_TIME_CHARACTERS_TABLE.length ; i++) { 1.114 + DATE_TIME_CHARACTERS_TABLE[i] = -1; 1.115 + } 1.116 + 1.117 + for (int i = 0; i < RestrictedAlphabet.NUMERIC_CHARACTERS.length() ; i++) { 1.118 + NUMERIC_CHARACTERS_TABLE[RestrictedAlphabet.NUMERIC_CHARACTERS.charAt(i)] = i; 1.119 + } 1.120 + for (int i = 0; i < RestrictedAlphabet.DATE_TIME_CHARACTERS.length() ; i++) { 1.121 + DATE_TIME_CHARACTERS_TABLE[RestrictedAlphabet.DATE_TIME_CHARACTERS.charAt(i)] = i; 1.122 + } 1.123 + } 1.124 + 1.125 + private static int maxCharacter(String alphabet) { 1.126 + int c = 0; 1.127 + for (int i = 0; i < alphabet.length() ; i++) { 1.128 + if (c < alphabet.charAt(i)) { 1.129 + c = alphabet.charAt(i); 1.130 + } 1.131 + } 1.132 + 1.133 + return c; 1.134 + } 1.135 + 1.136 + /** 1.137 + * True if DTD and internal subset shall be ignored. 1.138 + */ 1.139 + private boolean _ignoreDTD; 1.140 + 1.141 + /** 1.142 + * True if comments shall be ignored. 1.143 + */ 1.144 + private boolean _ignoreComments; 1.145 + 1.146 + /** 1.147 + * True if procesing instructions shall be ignored. 1.148 + */ 1.149 + private boolean _ignoreProcessingInstructions; 1.150 + 1.151 + /** 1.152 + * True if white space characters for text content shall be ignored. 1.153 + */ 1.154 + private boolean _ignoreWhiteSpaceTextContent; 1.155 + 1.156 + /** 1.157 + * True, if the local name string is used as the key to find the 1.158 + * associated set of qualified names. 1.159 + * <p> 1.160 + * False, if the <prefix>:<local name> string is used as the key 1.161 + * to find the associated set of qualified names. 1.162 + */ 1.163 + private boolean _useLocalNameAsKeyForQualifiedNameLookup; 1.164 + 1.165 + /** 1.166 + * True if strings for text content and attribute values will be 1.167 + * UTF-8 encoded otherwise they will be UTF-16 encoded. 1.168 + */ 1.169 + private boolean _encodingStringsAsUtf8 = true; 1.170 + 1.171 + /** 1.172 + * Encoding constant generated from the string encoding. 1.173 + */ 1.174 + private int _nonIdentifyingStringOnThirdBitCES; 1.175 + 1.176 + /** 1.177 + * Encoding constant generated from the string encoding. 1.178 + */ 1.179 + private int _nonIdentifyingStringOnFirstBitCES; 1.180 + 1.181 + /** 1.182 + * The map of URIs to algorithms. 1.183 + */ 1.184 + private Map _registeredEncodingAlgorithms = new HashMap(); 1.185 + 1.186 + /** 1.187 + * The vocabulary that is used by the encoder 1.188 + */ 1.189 + protected SerializerVocabulary _v; 1.190 + 1.191 + /** 1.192 + * The vocabulary application data that is used by the encoder 1.193 + */ 1.194 + protected VocabularyApplicationData _vData; 1.195 + 1.196 + /** 1.197 + * True if the vocubulary is internal to the encoder 1.198 + */ 1.199 + private boolean _vIsInternal; 1.200 + 1.201 + /** 1.202 + * True if terminatation of an information item is required 1.203 + */ 1.204 + protected boolean _terminate = false; 1.205 + 1.206 + /** 1.207 + * The current octet that is to be written. 1.208 + */ 1.209 + protected int _b; 1.210 + 1.211 + /** 1.212 + * The {@link java.io.OutputStream} that the encoded XML infoset (the 1.213 + * fast infoset document) is written to. 1.214 + */ 1.215 + protected OutputStream _s; 1.216 + 1.217 + /** 1.218 + * The internal buffer of characters used for the UTF-8 or UTF-16 encoding 1.219 + * of characters. 1.220 + */ 1.221 + protected char[] _charBuffer = new char[512]; 1.222 + 1.223 + /** 1.224 + * The internal buffer of bytes. 1.225 + */ 1.226 + protected byte[] _octetBuffer = new byte[1024]; 1.227 + 1.228 + /** 1.229 + * The current position in the internal buffer. 1.230 + */ 1.231 + protected int _octetBufferIndex; 1.232 + 1.233 + /** 1.234 + * The current mark in the internal buffer. 1.235 + * 1.236 + * <p> 1.237 + * If the value of the mark is < 0 then the mark is not set. 1.238 + */ 1.239 + protected int _markIndex = -1; 1.240 + 1.241 + /** 1.242 + * The minimum size of [normalized value] of Attribute Information 1.243 + * Items that will be indexed. 1.244 + */ 1.245 + protected int minAttributeValueSize = FastInfosetSerializer.MIN_ATTRIBUTE_VALUE_SIZE; 1.246 + 1.247 + /** 1.248 + * The maximum size of [normalized value] of Attribute Information 1.249 + * Items that will be indexed. 1.250 + */ 1.251 + protected int maxAttributeValueSize = FastInfosetSerializer.MAX_ATTRIBUTE_VALUE_SIZE; 1.252 + 1.253 + /** 1.254 + * The limit on the size of indexed Map for attribute values 1.255 + * Limit is measured in characters number 1.256 + */ 1.257 + protected int attributeValueMapTotalCharactersConstraint = FastInfosetSerializer.ATTRIBUTE_VALUE_MAP_MEMORY_CONSTRAINT / 2; 1.258 + 1.259 + /** 1.260 + * The minimum size of character content chunks 1.261 + * of Character Information Items or Comment Information Items that 1.262 + * will be indexed. 1.263 + */ 1.264 + protected int minCharacterContentChunkSize = FastInfosetSerializer.MIN_CHARACTER_CONTENT_CHUNK_SIZE; 1.265 + 1.266 + /** 1.267 + * The maximum size of character content chunks 1.268 + * of Character Information Items or Comment Information Items that 1.269 + * will be indexed. 1.270 + */ 1.271 + protected int maxCharacterContentChunkSize = FastInfosetSerializer.MAX_CHARACTER_CONTENT_CHUNK_SIZE; 1.272 + 1.273 + /** 1.274 + * The limit on the size of indexed Map for character content chunks 1.275 + * Limit is measured in characters number 1.276 + */ 1.277 + protected int characterContentChunkMapTotalCharactersConstraint = FastInfosetSerializer.CHARACTER_CONTENT_CHUNK_MAP_MEMORY_CONSTRAINT / 2; 1.278 + 1.279 + /** 1.280 + * Default constructor for the Encoder. 1.281 + */ 1.282 + protected Encoder() { 1.283 + setCharacterEncodingScheme(_characterEncodingSchemeSystemDefault); 1.284 + } 1.285 + 1.286 + protected Encoder(boolean useLocalNameAsKeyForQualifiedNameLookup) { 1.287 + setCharacterEncodingScheme(_characterEncodingSchemeSystemDefault); 1.288 + _useLocalNameAsKeyForQualifiedNameLookup = useLocalNameAsKeyForQualifiedNameLookup; 1.289 + } 1.290 + 1.291 + 1.292 + // FastInfosetSerializer interface 1.293 + 1.294 + /** 1.295 + * {@inheritDoc} 1.296 + */ 1.297 + public final void setIgnoreDTD(boolean ignoreDTD) { 1.298 + _ignoreDTD = ignoreDTD; 1.299 + } 1.300 + 1.301 + /** 1.302 + * {@inheritDoc} 1.303 + */ 1.304 + public final boolean getIgnoreDTD() { 1.305 + return _ignoreDTD; 1.306 + } 1.307 + 1.308 + /** 1.309 + * {@inheritDoc} 1.310 + */ 1.311 + public final void setIgnoreComments(boolean ignoreComments) { 1.312 + _ignoreComments = ignoreComments; 1.313 + } 1.314 + 1.315 + /** 1.316 + * {@inheritDoc} 1.317 + */ 1.318 + public final boolean getIgnoreComments() { 1.319 + return _ignoreComments; 1.320 + } 1.321 + 1.322 + /** 1.323 + * {@inheritDoc} 1.324 + */ 1.325 + public final void setIgnoreProcesingInstructions(boolean 1.326 + ignoreProcesingInstructions) { 1.327 + _ignoreProcessingInstructions = ignoreProcesingInstructions; 1.328 + } 1.329 + 1.330 + /** 1.331 + * {@inheritDoc} 1.332 + */ 1.333 + public final boolean getIgnoreProcesingInstructions() { 1.334 + return _ignoreProcessingInstructions; 1.335 + } 1.336 + 1.337 + /** 1.338 + * {@inheritDoc} 1.339 + */ 1.340 + public final void setIgnoreWhiteSpaceTextContent(boolean ignoreWhiteSpaceTextContent) { 1.341 + _ignoreWhiteSpaceTextContent = ignoreWhiteSpaceTextContent; 1.342 + } 1.343 + 1.344 + /** 1.345 + * {@inheritDoc} 1.346 + */ 1.347 + public final boolean getIgnoreWhiteSpaceTextContent() { 1.348 + return _ignoreWhiteSpaceTextContent; 1.349 + } 1.350 + 1.351 + /** 1.352 + * {@inheritDoc} 1.353 + */ 1.354 + public void setCharacterEncodingScheme(String characterEncodingScheme) { 1.355 + if (characterEncodingScheme.equals(UTF_16BE)) { 1.356 + _encodingStringsAsUtf8 = false; 1.357 + _nonIdentifyingStringOnThirdBitCES = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_UTF_16_FLAG; 1.358 + _nonIdentifyingStringOnFirstBitCES = EncodingConstants.NISTRING_UTF_16_FLAG; 1.359 + } else { 1.360 + _encodingStringsAsUtf8 = true; 1.361 + _nonIdentifyingStringOnThirdBitCES = EncodingConstants.CHARACTER_CHUNK; 1.362 + _nonIdentifyingStringOnFirstBitCES = 0; 1.363 + } 1.364 + } 1.365 + 1.366 + /** 1.367 + * {@inheritDoc} 1.368 + */ 1.369 + public String getCharacterEncodingScheme() { 1.370 + return (_encodingStringsAsUtf8) ? UTF_8 : UTF_16BE; 1.371 + } 1.372 + 1.373 + /** 1.374 + * {@inheritDoc} 1.375 + */ 1.376 + public void setRegisteredEncodingAlgorithms(Map algorithms) { 1.377 + _registeredEncodingAlgorithms = algorithms; 1.378 + if (_registeredEncodingAlgorithms == null) { 1.379 + _registeredEncodingAlgorithms = new HashMap(); 1.380 + } 1.381 + } 1.382 + 1.383 + /** 1.384 + * {@inheritDoc} 1.385 + */ 1.386 + public Map getRegisteredEncodingAlgorithms() { 1.387 + return _registeredEncodingAlgorithms; 1.388 + } 1.389 + 1.390 + /** 1.391 + * {@inheritDoc} 1.392 + */ 1.393 + public int getMinCharacterContentChunkSize() { 1.394 + return minCharacterContentChunkSize; 1.395 + } 1.396 + 1.397 + /** 1.398 + * {@inheritDoc} 1.399 + */ 1.400 + public void setMinCharacterContentChunkSize(int size) { 1.401 + if (size < 0 ) { 1.402 + size = 0; 1.403 + } 1.404 + 1.405 + minCharacterContentChunkSize = size; 1.406 + } 1.407 + 1.408 + /** 1.409 + * {@inheritDoc} 1.410 + */ 1.411 + public int getMaxCharacterContentChunkSize() { 1.412 + return maxCharacterContentChunkSize; 1.413 + } 1.414 + 1.415 + /** 1.416 + * {@inheritDoc} 1.417 + */ 1.418 + public void setMaxCharacterContentChunkSize(int size) { 1.419 + if (size < 0 ) { 1.420 + size = 0; 1.421 + } 1.422 + 1.423 + maxCharacterContentChunkSize = size; 1.424 + } 1.425 + 1.426 + /** 1.427 + * {@inheritDoc} 1.428 + */ 1.429 + public int getCharacterContentChunkMapMemoryLimit() { 1.430 + return characterContentChunkMapTotalCharactersConstraint * 2; 1.431 + } 1.432 + 1.433 + /** 1.434 + * {@inheritDoc} 1.435 + */ 1.436 + public void setCharacterContentChunkMapMemoryLimit(int size) { 1.437 + if (size < 0 ) { 1.438 + size = 0; 1.439 + } 1.440 + 1.441 + characterContentChunkMapTotalCharactersConstraint = size / 2; 1.442 + } 1.443 + 1.444 + /** 1.445 + * Checks whether character content chunk (its length) matches length limit 1.446 + * 1.447 + * @param length the length of character content chunk is checking to be added to Map. 1.448 + * @return whether character content chunk length matches limit 1.449 + */ 1.450 + public boolean isCharacterContentChunkLengthMatchesLimit(int length) { 1.451 + return length >= minCharacterContentChunkSize && 1.452 + length < maxCharacterContentChunkSize; 1.453 + } 1.454 + 1.455 + /** 1.456 + * Checks whether character content table has enough memory to 1.457 + * store character content chunk with the given length 1.458 + * 1.459 + * @param length the length of character content chunk is checking to be added to Map. 1.460 + * @param map the custom CharArrayIntMap, which memory limits will be checked. 1.461 + * @return whether character content map has enough memory 1.462 + */ 1.463 + public boolean canAddCharacterContentToTable(int length, CharArrayIntMap map) { 1.464 + return map.getTotalCharacterCount() + length < 1.465 + characterContentChunkMapTotalCharactersConstraint; 1.466 + } 1.467 + 1.468 + /** 1.469 + * {@inheritDoc} 1.470 + */ 1.471 + public int getMinAttributeValueSize() { 1.472 + return minAttributeValueSize; 1.473 + } 1.474 + 1.475 + /** 1.476 + * {@inheritDoc} 1.477 + */ 1.478 + public void setMinAttributeValueSize(int size) { 1.479 + if (size < 0 ) { 1.480 + size = 0; 1.481 + } 1.482 + 1.483 + minAttributeValueSize = size; 1.484 + } 1.485 + 1.486 + /** 1.487 + * {@inheritDoc} 1.488 + */ 1.489 + public int getMaxAttributeValueSize() { 1.490 + return maxAttributeValueSize; 1.491 + } 1.492 + 1.493 + /** 1.494 + * {@inheritDoc} 1.495 + */ 1.496 + public void setMaxAttributeValueSize(int size) { 1.497 + if (size < 0 ) { 1.498 + size = 0; 1.499 + } 1.500 + 1.501 + maxAttributeValueSize = size; 1.502 + } 1.503 + 1.504 + /** 1.505 + * {@inheritDoc} 1.506 + */ 1.507 + public void setAttributeValueMapMemoryLimit(int size) { 1.508 + if (size < 0 ) { 1.509 + size = 0; 1.510 + } 1.511 + 1.512 + attributeValueMapTotalCharactersConstraint = size / 2; 1.513 + 1.514 + } 1.515 + 1.516 + /** 1.517 + * {@inheritDoc} 1.518 + */ 1.519 + public int getAttributeValueMapMemoryLimit() { 1.520 + return attributeValueMapTotalCharactersConstraint * 2; 1.521 + } 1.522 + 1.523 + /** 1.524 + * Checks whether attribute value (its length) matches length limit 1.525 + * 1.526 + * @param length the length of attribute 1.527 + * @return whether attribute value matches limit 1.528 + */ 1.529 + public boolean isAttributeValueLengthMatchesLimit(int length) { 1.530 + return length >= minAttributeValueSize && 1.531 + length < maxAttributeValueSize; 1.532 + } 1.533 + 1.534 + /** 1.535 + * Checks whether attribute table has enough memory to 1.536 + * store attribute value with the given length 1.537 + * 1.538 + * @param length the length of attribute value is checking to be added to Map. 1.539 + * @return whether attribute map has enough memory 1.540 + */ 1.541 + public boolean canAddAttributeToTable(int length) { 1.542 + return _v.attributeValue.getTotalCharacterCount() + length < 1.543 + attributeValueMapTotalCharactersConstraint; 1.544 + } 1.545 + 1.546 + /** 1.547 + * {@inheritDoc} 1.548 + */ 1.549 + public void setExternalVocabulary(ExternalVocabulary v) { 1.550 + // Create internal serializer vocabulary 1.551 + _v = new SerializerVocabulary(); 1.552 + // Set the external vocabulary 1.553 + SerializerVocabulary ev = new SerializerVocabulary(v.vocabulary, 1.554 + _useLocalNameAsKeyForQualifiedNameLookup); 1.555 + _v.setExternalVocabulary(v.URI, 1.556 + ev, false); 1.557 + 1.558 + _vIsInternal = true; 1.559 + } 1.560 + 1.561 + /** 1.562 + * {@inheritDoc} 1.563 + */ 1.564 + public void setVocabularyApplicationData(VocabularyApplicationData data) { 1.565 + _vData = data; 1.566 + } 1.567 + 1.568 + /** 1.569 + * {@inheritDoc} 1.570 + */ 1.571 + public VocabularyApplicationData getVocabularyApplicationData() { 1.572 + return _vData; 1.573 + } 1.574 + 1.575 + // End of FastInfosetSerializer interface 1.576 + 1.577 + /** 1.578 + * Reset the encoder for reuse encoding another XML infoset. 1.579 + */ 1.580 + public void reset() { 1.581 + _terminate = false; 1.582 + } 1.583 + 1.584 + /** 1.585 + * Set the OutputStream to encode the XML infoset to a 1.586 + * fast infoset document. 1.587 + * 1.588 + * @param s the OutputStream where the fast infoset document is written to. 1.589 + */ 1.590 + public void setOutputStream(OutputStream s) { 1.591 + _octetBufferIndex = 0; 1.592 + _markIndex = -1; 1.593 + _s = s; 1.594 + } 1.595 + 1.596 + /** 1.597 + * Set the SerializerVocabulary to be used for encoding. 1.598 + * 1.599 + * @param vocabulary the vocabulary to be used for encoding. 1.600 + */ 1.601 + public void setVocabulary(SerializerVocabulary vocabulary) { 1.602 + _v = vocabulary; 1.603 + _vIsInternal = false; 1.604 + } 1.605 + 1.606 + /** 1.607 + * Encode the header of a fast infoset document. 1.608 + * 1.609 + * @param encodeXmlDecl true if the XML declaration should be encoded. 1.610 + */ 1.611 + protected final void encodeHeader(boolean encodeXmlDecl) throws IOException { 1.612 + if (encodeXmlDecl) { 1.613 + _s.write(EncodingConstants.XML_DECLARATION_VALUES[0]); 1.614 + } 1.615 + _s.write(EncodingConstants.BINARY_HEADER); 1.616 + } 1.617 + 1.618 + /** 1.619 + * Encode the initial vocabulary of a fast infoset document. 1.620 + * 1.621 + */ 1.622 + protected final void encodeInitialVocabulary() throws IOException { 1.623 + if (_v == null) { 1.624 + _v = new SerializerVocabulary(); 1.625 + _vIsInternal = true; 1.626 + } else if (_vIsInternal) { 1.627 + _v.clear(); 1.628 + if (_vData != null) 1.629 + _vData.clear(); 1.630 + } 1.631 + 1.632 + if (!_v.hasInitialVocabulary() && !_v.hasExternalVocabulary()) { 1.633 + write(0); 1.634 + } else if (_v.hasInitialVocabulary()) { 1.635 + _b = EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG; 1.636 + write(_b); 1.637 + 1.638 + SerializerVocabulary initialVocabulary = _v.getReadOnlyVocabulary(); 1.639 + 1.640 + // TODO check for contents of vocabulary to assign bits 1.641 + if (initialVocabulary.hasExternalVocabulary()) { 1.642 + _b = EncodingConstants.INITIAL_VOCABULARY_EXTERNAL_VOCABULARY_FLAG; 1.643 + write(_b); 1.644 + write(0); 1.645 + } 1.646 + 1.647 + if (initialVocabulary.hasExternalVocabulary()) { 1.648 + encodeNonEmptyOctetStringOnSecondBit(_v.getExternalVocabularyURI()); 1.649 + } 1.650 + 1.651 + // TODO check for contents of vocabulary to encode values 1.652 + } else if (_v.hasExternalVocabulary()) { 1.653 + _b = EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG; 1.654 + write(_b); 1.655 + 1.656 + _b = EncodingConstants.INITIAL_VOCABULARY_EXTERNAL_VOCABULARY_FLAG; 1.657 + write(_b); 1.658 + write(0); 1.659 + 1.660 + encodeNonEmptyOctetStringOnSecondBit(_v.getExternalVocabularyURI()); 1.661 + } 1.662 + } 1.663 + 1.664 + /** 1.665 + * Encode the termination of the Document Information Item. 1.666 + * 1.667 + */ 1.668 + protected final void encodeDocumentTermination() throws IOException { 1.669 + encodeElementTermination(); 1.670 + encodeTermination(); 1.671 + _flush(); 1.672 + _s.flush(); 1.673 + } 1.674 + 1.675 + /** 1.676 + * Encode the termination of an Element Information Item. 1.677 + * 1.678 + */ 1.679 + protected final void encodeElementTermination() throws IOException { 1.680 + _terminate = true; 1.681 + switch (_b) { 1.682 + case EncodingConstants.TERMINATOR: 1.683 + _b = EncodingConstants.DOUBLE_TERMINATOR; 1.684 + break; 1.685 + case EncodingConstants.DOUBLE_TERMINATOR: 1.686 + write(EncodingConstants.DOUBLE_TERMINATOR); 1.687 + default: 1.688 + _b = EncodingConstants.TERMINATOR; 1.689 + } 1.690 + } 1.691 + 1.692 + /** 1.693 + * Encode a termination if required. 1.694 + * 1.695 + */ 1.696 + protected final void encodeTermination() throws IOException { 1.697 + if (_terminate) { 1.698 + write(_b); 1.699 + _b = 0; 1.700 + _terminate = false; 1.701 + } 1.702 + } 1.703 + 1.704 + /** 1.705 + * Encode a Attribute Information Item that is a namespace declaration. 1.706 + * 1.707 + * @param prefix the prefix of the namespace declaration, 1.708 + * if "" then there is no prefix for the namespace declaration. 1.709 + * @param uri the URI of the namespace declaration, 1.710 + * if "" then there is no URI for the namespace declaration. 1.711 + */ 1.712 + protected final void encodeNamespaceAttribute(String prefix, String uri) throws IOException { 1.713 + _b = EncodingConstants.NAMESPACE_ATTRIBUTE; 1.714 + if (prefix.length() > 0) { 1.715 + _b |= EncodingConstants.NAMESPACE_ATTRIBUTE_PREFIX_FLAG; 1.716 + } 1.717 + if (uri.length() > 0) { 1.718 + _b |= EncodingConstants.NAMESPACE_ATTRIBUTE_NAME_FLAG; 1.719 + } 1.720 + 1.721 + // NOTE a prefix with out a namespace name is an undeclaration 1.722 + // of the namespace bound to the prefix 1.723 + // TODO needs to investigate how the startPrefixMapping works in 1.724 + // relation to undeclaration 1.725 + 1.726 + write(_b); 1.727 + 1.728 + if (prefix.length() > 0) { 1.729 + encodeIdentifyingNonEmptyStringOnFirstBit(prefix, _v.prefix); 1.730 + } 1.731 + if (uri.length() > 0) { 1.732 + encodeIdentifyingNonEmptyStringOnFirstBit(uri, _v.namespaceName); 1.733 + } 1.734 + } 1.735 + 1.736 + /** 1.737 + * Encode a chunk of Character Information Items. 1.738 + * 1.739 + * @param ch the array of characters. 1.740 + * @param offset the offset into the array of characters. 1.741 + * @param length the length of characters. 1.742 + * @throws ArrayIndexOutOfBoundsException. 1.743 + */ 1.744 + protected final void encodeCharacters(char[] ch, int offset, int length) throws IOException { 1.745 + final boolean addToTable = isCharacterContentChunkLengthMatchesLimit(length); 1.746 + encodeNonIdentifyingStringOnThirdBit(ch, offset, length, _v.characterContentChunk, addToTable, true); 1.747 + } 1.748 + 1.749 + /** 1.750 + * Encode a chunk of Character Information Items. 1.751 + * 1.752 + * If the array of characters is to be indexed (as determined by 1.753 + * {@link Encoder#characterContentChunkSizeContraint}) then the array is not cloned 1.754 + * when adding the array to the vocabulary. 1.755 + * 1.756 + * @param ch the array of characters. 1.757 + * @param offset the offset into the array of characters. 1.758 + * @param length the length of characters. 1.759 + * @throws ArrayIndexOutOfBoundsException. 1.760 + */ 1.761 + protected final void encodeCharactersNoClone(char[] ch, int offset, int length) throws IOException { 1.762 + final boolean addToTable = isCharacterContentChunkLengthMatchesLimit(length); 1.763 + encodeNonIdentifyingStringOnThirdBit(ch, offset, length, _v.characterContentChunk, addToTable, false); 1.764 + } 1.765 + 1.766 + /** 1.767 + * Encode a chunk of Character Information Items using a numeric 1.768 + * alphabet that results in the encoding of a character in 4 bits 1.769 + * (or two characters per octet). 1.770 + * 1.771 + * @param id the restricted alphabet identifier. 1.772 + * @param table the table mapping characters to 4 bit values. 1.773 + * @param ch the array of characters. 1.774 + * @param offset the offset into the array of characters. 1.775 + * @param length the length of characters. 1.776 + * @param addToTable if characters should be added to table. 1.777 + * @throws ArrayIndexOutOfBoundsException. 1.778 + */ 1.779 + protected final void encodeNumericFourBitCharacters(char[] ch, int offset, int length, 1.780 + boolean addToTable) throws FastInfosetException, IOException { 1.781 + encodeFourBitCharacters(RestrictedAlphabet.NUMERIC_CHARACTERS_INDEX, 1.782 + NUMERIC_CHARACTERS_TABLE, ch, offset, length, addToTable); 1.783 + } 1.784 + 1.785 + /** 1.786 + * Encode a chunk of Character Information Items using a date-time 1.787 + * alphabet that results in the encoding of a character in 4 bits 1.788 + * (or two characters per octet). 1.789 + * 1.790 + * @param id the restricted alphabet identifier. 1.791 + * @param table the table mapping characters to 4 bit values. 1.792 + * @param ch the array of characters. 1.793 + * @param offset the offset into the array of characters. 1.794 + * @param length the length of characters. 1.795 + * @param addToTable if characters should be added to table. 1.796 + * @throws ArrayIndexOutOfBoundsException. 1.797 + */ 1.798 + protected final void encodeDateTimeFourBitCharacters(char[] ch, int offset, int length, 1.799 + boolean addToTable) throws FastInfosetException, IOException { 1.800 + encodeFourBitCharacters(RestrictedAlphabet.DATE_TIME_CHARACTERS_INDEX, 1.801 + DATE_TIME_CHARACTERS_TABLE, ch, offset, length, addToTable); 1.802 + } 1.803 + 1.804 + /** 1.805 + * Encode a chunk of Character Information Items using a restricted 1.806 + * alphabet that results in the encoding of a character in 4 bits 1.807 + * (or two characters per octet). 1.808 + * 1.809 + * @param id the restricted alphabet identifier. 1.810 + * @param table the table mapping characters to 4 bit values. 1.811 + * @param ch the array of characters. 1.812 + * @param offset the offset into the array of characters. 1.813 + * @param length the length of characters. 1.814 + * @param addToTable if characters should be added to table. 1.815 + * @throws ArrayIndexOutOfBoundsException. 1.816 + */ 1.817 + protected final void encodeFourBitCharacters(int id, int[] table, char[] ch, int offset, int length, 1.818 + boolean addToTable) throws FastInfosetException, IOException { 1.819 + if (addToTable) { 1.820 + // if char array could be added to table 1.821 + boolean canAddCharacterContentToTable = 1.822 + canAddCharacterContentToTable(length, _v.characterContentChunk); 1.823 + 1.824 + // obtain/get index 1.825 + int index = canAddCharacterContentToTable ? 1.826 + _v.characterContentChunk.obtainIndex(ch, offset, length, true) : 1.827 + _v.characterContentChunk.get(ch, offset, length); 1.828 + 1.829 + if (index != KeyIntMap.NOT_PRESENT) { 1.830 + // if char array is in table 1.831 + _b = EncodingConstants.CHARACTER_CHUNK | 0x20; 1.832 + encodeNonZeroIntegerOnFourthBit(index); 1.833 + return; 1.834 + } else if (canAddCharacterContentToTable) { 1.835 + // if char array is not in table, but could be added 1.836 + _b = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG | EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG; 1.837 + } else { 1.838 + // if char array is not in table and could not be added 1.839 + _b = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG; 1.840 + } 1.841 + } else { 1.842 + _b = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG; 1.843 + } 1.844 + 1.845 + write (_b); 1.846 + 1.847 + // Encode bottom 6 bits of enoding algorithm id 1.848 + _b = id << 2; 1.849 + 1.850 + encodeNonEmptyFourBitCharacterStringOnSeventhBit(table, ch, offset, length); 1.851 + } 1.852 + 1.853 + /** 1.854 + * Encode a chunk of Character Information Items using a restricted 1.855 + * alphabet table. 1.856 + * 1.857 + * @param alphabet the alphabet defining the mapping between characters and 1.858 + * integer values. 1.859 + * @param ch the array of characters. 1.860 + * @param offset the offset into the array of characters. 1.861 + * @param length the length of characters. 1.862 + * @param addToTable if characters should be added to table 1.863 + * @throws ArrayIndexOutOfBoundsException. 1.864 + * @throws FastInfosetException if the alphabet is not present in the 1.865 + * vocabulary. 1.866 + */ 1.867 + protected final void encodeAlphabetCharacters(String alphabet, char[] ch, int offset, int length, 1.868 + boolean addToTable) throws FastInfosetException, IOException { 1.869 + if (addToTable) { 1.870 + // if char array could be added to table 1.871 + boolean canAddCharacterContentToTable = 1.872 + canAddCharacterContentToTable(length, _v.characterContentChunk); 1.873 + 1.874 + // obtain/get index 1.875 + int index = canAddCharacterContentToTable ? 1.876 + _v.characterContentChunk.obtainIndex(ch, offset, length, true) : 1.877 + _v.characterContentChunk.get(ch, offset, length); 1.878 + 1.879 + if (index != KeyIntMap.NOT_PRESENT) { 1.880 + // if char array is in table 1.881 + _b = EncodingConstants.CHARACTER_CHUNK | 0x20; 1.882 + encodeNonZeroIntegerOnFourthBit(index); 1.883 + return; 1.884 + } else if (canAddCharacterContentToTable) { 1.885 + // if char array is not in table, but could be added 1.886 + _b = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG | EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG; 1.887 + } else { 1.888 + // if char array is not in table and could not be added 1.889 + _b = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG; 1.890 + } 1.891 + } else { 1.892 + _b = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG; 1.893 + } 1.894 + 1.895 + int id = _v.restrictedAlphabet.get(alphabet); 1.896 + if (id == KeyIntMap.NOT_PRESENT) { 1.897 + throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.restrictedAlphabetNotPresent")); 1.898 + } 1.899 + id += EncodingConstants.RESTRICTED_ALPHABET_APPLICATION_START; 1.900 + 1.901 + _b |= (id & 0xC0) >> 6; 1.902 + write(_b); 1.903 + 1.904 + // Encode bottom 6 bits of enoding algorithm id 1.905 + _b = (id & 0x3F) << 2; 1.906 + 1.907 + encodeNonEmptyNBitCharacterStringOnSeventhBit(alphabet, ch, offset, length); 1.908 + } 1.909 + 1.910 + /** 1.911 + * Encode a Processing Instruction Information Item. 1.912 + * 1.913 + * @param target the target of the processing instruction. 1.914 + * @param data the data of the processing instruction. 1.915 + */ 1.916 + protected final void encodeProcessingInstruction(String target, String data) throws IOException { 1.917 + write(EncodingConstants.PROCESSING_INSTRUCTION); 1.918 + 1.919 + // Target 1.920 + encodeIdentifyingNonEmptyStringOnFirstBit(target, _v.otherNCName); 1.921 + 1.922 + // Data 1.923 + boolean addToTable = isCharacterContentChunkLengthMatchesLimit(data.length()); 1.924 + encodeNonIdentifyingStringOnFirstBit(data, _v.otherString, addToTable); 1.925 + } 1.926 + 1.927 + /** 1.928 + * Encode a Document Type Declaration. 1.929 + * 1.930 + * @param systemId the system identifier of the external subset. 1.931 + * @param publicId the public identifier of the external subset. 1.932 + */ 1.933 + protected final void encodeDocumentTypeDeclaration(String systemId, String publicId) throws IOException { 1.934 + _b = EncodingConstants.DOCUMENT_TYPE_DECLARATION; 1.935 + if (systemId != null && systemId.length() > 0) { 1.936 + _b |= EncodingConstants.DOCUMENT_TYPE_SYSTEM_IDENTIFIER_FLAG; 1.937 + } 1.938 + if (publicId != null && publicId.length() > 0) { 1.939 + _b |= EncodingConstants.DOCUMENT_TYPE_PUBLIC_IDENTIFIER_FLAG; 1.940 + } 1.941 + write(_b); 1.942 + 1.943 + if (systemId != null && systemId.length() > 0) { 1.944 + encodeIdentifyingNonEmptyStringOnFirstBit(systemId, _v.otherURI); 1.945 + } 1.946 + if (publicId != null && publicId.length() > 0) { 1.947 + encodeIdentifyingNonEmptyStringOnFirstBit(publicId, _v.otherURI); 1.948 + } 1.949 + } 1.950 + 1.951 + /** 1.952 + * Encode a Comment Information Item. 1.953 + * 1.954 + * @param ch the array of characters that is as comment. 1.955 + * @param offset the offset into the array of characters. 1.956 + * @param length the length of characters. 1.957 + * @throws ArrayIndexOutOfBoundsException. 1.958 + */ 1.959 + protected final void encodeComment(char[] ch, int offset, int length) throws IOException { 1.960 + write(EncodingConstants.COMMENT); 1.961 + 1.962 + boolean addToTable = isCharacterContentChunkLengthMatchesLimit(length); 1.963 + encodeNonIdentifyingStringOnFirstBit(ch, offset, length, _v.otherString, addToTable, true); 1.964 + } 1.965 + 1.966 + /** 1.967 + * Encode a Comment Information Item. 1.968 + * 1.969 + * If the array of characters that is a comment is to be indexed (as 1.970 + * determined by {@link Encoder#characterContentChunkSizeContraint}) then 1.971 + * the array is not cloned when adding the array to the vocabulary. 1.972 + * 1.973 + * @param ch the array of characters. 1.974 + * @param offset the offset into the array of characters. 1.975 + * @param length the length of characters. 1.976 + * @throws ArrayIndexOutOfBoundsException. 1.977 + */ 1.978 + protected final void encodeCommentNoClone(char[] ch, int offset, int length) throws IOException { 1.979 + write(EncodingConstants.COMMENT); 1.980 + 1.981 + boolean addToTable = isCharacterContentChunkLengthMatchesLimit(length); 1.982 + encodeNonIdentifyingStringOnFirstBit(ch, offset, length, _v.otherString, addToTable, false); 1.983 + } 1.984 + 1.985 + /** 1.986 + * Encode a qualified name of an Element Informaiton Item on the third bit 1.987 + * of an octet. 1.988 + * Implementation of clause C.18 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.989 + * 1.990 + * <p> 1.991 + * The index of the qualified name will be encoded if the name is present 1.992 + * in the vocabulary otherwise the qualified name will be encoded literally 1.993 + * (see {@link #encodeLiteralElementQualifiedNameOnThirdBit}). 1.994 + * 1.995 + * @param namespaceURI the namespace URI of the qualified name. 1.996 + * @param prefix the prefix of the qualified name. 1.997 + * @param localName the local name of the qualified name. 1.998 + */ 1.999 + protected final void encodeElementQualifiedNameOnThirdBit(String namespaceURI, String prefix, String localName) throws IOException { 1.1000 + LocalNameQualifiedNamesMap.Entry entry = _v.elementName.obtainEntry(localName); 1.1001 + if (entry._valueIndex > 0) { 1.1002 + QualifiedName[] names = entry._value; 1.1003 + for (int i = 0; i < entry._valueIndex; i++) { 1.1004 + if ((prefix == names[i].prefix || prefix.equals(names[i].prefix)) 1.1005 + && (namespaceURI == names[i].namespaceName || namespaceURI.equals(names[i].namespaceName))) { 1.1006 + encodeNonZeroIntegerOnThirdBit(names[i].index); 1.1007 + return; 1.1008 + } 1.1009 + } 1.1010 + } 1.1011 + 1.1012 + encodeLiteralElementQualifiedNameOnThirdBit(namespaceURI, prefix, 1.1013 + localName, entry); 1.1014 + } 1.1015 + 1.1016 + /** 1.1017 + * Encode a literal qualified name of an Element Informaiton Item on the 1.1018 + * third bit of an octet. 1.1019 + * Implementation of clause C.18 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1020 + * 1.1021 + * @param namespaceURI the namespace URI of the qualified name. 1.1022 + * @param prefix the prefix of the qualified name. 1.1023 + * @param localName the local name of the qualified name. 1.1024 + */ 1.1025 + protected final void encodeLiteralElementQualifiedNameOnThirdBit(String namespaceURI, String prefix, String localName, 1.1026 + LocalNameQualifiedNamesMap.Entry entry) throws IOException { 1.1027 + QualifiedName name = new QualifiedName(prefix, namespaceURI, localName, "", _v.elementName.getNextIndex()); 1.1028 + entry.addQualifiedName(name); 1.1029 + 1.1030 + int namespaceURIIndex = KeyIntMap.NOT_PRESENT; 1.1031 + int prefixIndex = KeyIntMap.NOT_PRESENT; 1.1032 + if (namespaceURI.length() > 0) { 1.1033 + namespaceURIIndex = _v.namespaceName.get(namespaceURI); 1.1034 + if (namespaceURIIndex == KeyIntMap.NOT_PRESENT) { 1.1035 + throw new IOException(CommonResourceBundle.getInstance().getString("message.namespaceURINotIndexed", new Object[]{namespaceURI})); 1.1036 + } 1.1037 + 1.1038 + if (prefix.length() > 0) { 1.1039 + prefixIndex = _v.prefix.get(prefix); 1.1040 + if (prefixIndex == KeyIntMap.NOT_PRESENT) { 1.1041 + throw new IOException(CommonResourceBundle.getInstance().getString("message.prefixNotIndexed", new Object[]{prefix})); 1.1042 + } 1.1043 + } 1.1044 + } 1.1045 + 1.1046 + int localNameIndex = _v.localName.obtainIndex(localName); 1.1047 + 1.1048 + _b |= EncodingConstants.ELEMENT_LITERAL_QNAME_FLAG; 1.1049 + if (namespaceURIIndex >= 0) { 1.1050 + _b |= EncodingConstants.LITERAL_QNAME_NAMESPACE_NAME_FLAG; 1.1051 + if (prefixIndex >= 0) { 1.1052 + _b |= EncodingConstants.LITERAL_QNAME_PREFIX_FLAG; 1.1053 + } 1.1054 + } 1.1055 + write(_b); 1.1056 + 1.1057 + if (namespaceURIIndex >= 0) { 1.1058 + if (prefixIndex >= 0) { 1.1059 + encodeNonZeroIntegerOnSecondBitFirstBitOne(prefixIndex); 1.1060 + } 1.1061 + encodeNonZeroIntegerOnSecondBitFirstBitOne(namespaceURIIndex); 1.1062 + } 1.1063 + 1.1064 + if (localNameIndex >= 0) { 1.1065 + encodeNonZeroIntegerOnSecondBitFirstBitOne(localNameIndex); 1.1066 + } else { 1.1067 + encodeNonEmptyOctetStringOnSecondBit(localName); 1.1068 + } 1.1069 + } 1.1070 + 1.1071 + /** 1.1072 + * Encode a qualified name of an Attribute Informaiton Item on the third bit 1.1073 + * of an octet. 1.1074 + * Implementation of clause C.17 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1075 + * 1.1076 + * <p> 1.1077 + * The index of the qualified name will be encoded if the name is present 1.1078 + * in the vocabulary otherwise the qualified name will be encoded literally 1.1079 + * (see {@link #encodeLiteralAttributeQualifiedNameOnSecondBit}). 1.1080 + * 1.1081 + * @param namespaceURI the namespace URI of the qualified name. 1.1082 + * @param prefix the prefix of the qualified name. 1.1083 + * @param localName the local name of the qualified name. 1.1084 + */ 1.1085 + protected final void encodeAttributeQualifiedNameOnSecondBit(String namespaceURI, String prefix, String localName) throws IOException { 1.1086 + LocalNameQualifiedNamesMap.Entry entry = _v.attributeName.obtainEntry(localName); 1.1087 + if (entry._valueIndex > 0) { 1.1088 + QualifiedName[] names = entry._value; 1.1089 + for (int i = 0; i < entry._valueIndex; i++) { 1.1090 + if ((prefix == names[i].prefix || prefix.equals(names[i].prefix)) 1.1091 + && (namespaceURI == names[i].namespaceName || namespaceURI.equals(names[i].namespaceName))) { 1.1092 + encodeNonZeroIntegerOnSecondBitFirstBitZero(names[i].index); 1.1093 + return; 1.1094 + } 1.1095 + } 1.1096 + } 1.1097 + 1.1098 + encodeLiteralAttributeQualifiedNameOnSecondBit(namespaceURI, prefix, 1.1099 + localName, entry); 1.1100 + } 1.1101 + 1.1102 + /** 1.1103 + * Encode a literal qualified name of an Attribute Informaiton Item on the 1.1104 + * third bit of an octet. 1.1105 + * Implementation of clause C.17 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1106 + * 1.1107 + * @param namespaceURI the namespace URI of the qualified name. 1.1108 + * @param prefix the prefix of the qualified name. 1.1109 + * @param localName the local name of the qualified name. 1.1110 + */ 1.1111 + protected final boolean encodeLiteralAttributeQualifiedNameOnSecondBit(String namespaceURI, String prefix, String localName, 1.1112 + LocalNameQualifiedNamesMap.Entry entry) throws IOException { 1.1113 + int namespaceURIIndex = KeyIntMap.NOT_PRESENT; 1.1114 + int prefixIndex = KeyIntMap.NOT_PRESENT; 1.1115 + if (namespaceURI.length() > 0) { 1.1116 + namespaceURIIndex = _v.namespaceName.get(namespaceURI); 1.1117 + if (namespaceURIIndex == KeyIntMap.NOT_PRESENT) { 1.1118 + if (namespaceURI == EncodingConstants.XMLNS_NAMESPACE_NAME || 1.1119 + namespaceURI.equals(EncodingConstants.XMLNS_NAMESPACE_NAME)) { 1.1120 + return false; 1.1121 + } else { 1.1122 + throw new IOException(CommonResourceBundle.getInstance().getString("message.namespaceURINotIndexed", new Object[]{namespaceURI})); 1.1123 + } 1.1124 + } 1.1125 + 1.1126 + if (prefix.length() > 0) { 1.1127 + prefixIndex = _v.prefix.get(prefix); 1.1128 + if (prefixIndex == KeyIntMap.NOT_PRESENT) { 1.1129 + throw new IOException(CommonResourceBundle.getInstance().getString("message.prefixNotIndexed", new Object[]{prefix})); 1.1130 + } 1.1131 + } 1.1132 + } 1.1133 + 1.1134 + int localNameIndex = _v.localName.obtainIndex(localName); 1.1135 + 1.1136 + QualifiedName name = new QualifiedName(prefix, namespaceURI, localName, "", _v.attributeName.getNextIndex()); 1.1137 + entry.addQualifiedName(name); 1.1138 + 1.1139 + _b = EncodingConstants.ATTRIBUTE_LITERAL_QNAME_FLAG; 1.1140 + if (namespaceURI.length() > 0) { 1.1141 + _b |= EncodingConstants.LITERAL_QNAME_NAMESPACE_NAME_FLAG; 1.1142 + if (prefix.length() > 0) { 1.1143 + _b |= EncodingConstants.LITERAL_QNAME_PREFIX_FLAG; 1.1144 + } 1.1145 + } 1.1146 + 1.1147 + write(_b); 1.1148 + 1.1149 + if (namespaceURIIndex >= 0) { 1.1150 + if (prefixIndex >= 0) { 1.1151 + encodeNonZeroIntegerOnSecondBitFirstBitOne(prefixIndex); 1.1152 + } 1.1153 + encodeNonZeroIntegerOnSecondBitFirstBitOne(namespaceURIIndex); 1.1154 + } else if (namespaceURI != "") { 1.1155 + // XML prefix and namespace name 1.1156 + encodeNonEmptyOctetStringOnSecondBit("xml"); 1.1157 + encodeNonEmptyOctetStringOnSecondBit("http://www.w3.org/XML/1998/namespace"); 1.1158 + } 1.1159 + 1.1160 + if (localNameIndex >= 0) { 1.1161 + encodeNonZeroIntegerOnSecondBitFirstBitOne(localNameIndex); 1.1162 + } else { 1.1163 + encodeNonEmptyOctetStringOnSecondBit(localName); 1.1164 + } 1.1165 + 1.1166 + return true; 1.1167 + } 1.1168 + 1.1169 + /** 1.1170 + * Encode a non identifying string on the first bit of an octet. 1.1171 + * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1172 + * 1.1173 + * @param s the string to encode 1.1174 + * @param map the vocabulary table of strings to indexes. 1.1175 + * @param addToTable true if the string could be added to the vocabulary 1.1176 + * table (if table has enough memory) 1.1177 + * @param mustBeAddedToTable true if the string must be added to the vocabulary 1.1178 + * table (if not already present in the table). 1.1179 + */ 1.1180 + protected final void encodeNonIdentifyingStringOnFirstBit(String s, StringIntMap map, 1.1181 + boolean addToTable, boolean mustBeAddedToTable) throws IOException { 1.1182 + if (s == null || s.length() == 0) { 1.1183 + // C.26 an index (first bit '1') with seven '1' bits for an empty string 1.1184 + write(0xFF); 1.1185 + } else { 1.1186 + if (addToTable || mustBeAddedToTable) { 1.1187 + // if attribute value could be added to table 1.1188 + boolean canAddAttributeToTable = mustBeAddedToTable || 1.1189 + canAddAttributeToTable(s.length()); 1.1190 + 1.1191 + // obtain/get index 1.1192 + int index = canAddAttributeToTable ? 1.1193 + map.obtainIndex(s) : 1.1194 + map.get(s); 1.1195 + 1.1196 + if (index != KeyIntMap.NOT_PRESENT) { 1.1197 + // if attribute value is in table 1.1198 + encodeNonZeroIntegerOnSecondBitFirstBitOne(index); 1.1199 + } else if (canAddAttributeToTable) { 1.1200 + // if attribute value is not in table, but could be added 1.1201 + _b = EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG | 1.1202 + _nonIdentifyingStringOnFirstBitCES; 1.1203 + encodeNonEmptyCharacterStringOnFifthBit(s); 1.1204 + } else { 1.1205 + // if attribute value is not in table and could not be added 1.1206 + _b = _nonIdentifyingStringOnFirstBitCES; 1.1207 + encodeNonEmptyCharacterStringOnFifthBit(s); 1.1208 + } 1.1209 + } else { 1.1210 + _b = _nonIdentifyingStringOnFirstBitCES; 1.1211 + encodeNonEmptyCharacterStringOnFifthBit(s); 1.1212 + } 1.1213 + } 1.1214 + } 1.1215 + 1.1216 + /** 1.1217 + * Encode a non identifying string on the first bit of an octet. 1.1218 + * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1219 + * 1.1220 + * @param s the string to encode 1.1221 + * @param map the vocabulary table of character arrays to indexes. 1.1222 + * @param addToTable true if the string should be added to the vocabulary 1.1223 + * table (if not already present in the table). 1.1224 + */ 1.1225 + protected final void encodeNonIdentifyingStringOnFirstBit(String s, CharArrayIntMap map, boolean addToTable) throws IOException { 1.1226 + if (s == null || s.length() == 0) { 1.1227 + // C.26 an index (first bit '1') with seven '1' bits for an empty string 1.1228 + write(0xFF); 1.1229 + } else { 1.1230 + if (addToTable) { 1.1231 + final char[] ch = s.toCharArray(); 1.1232 + final int length = s.length(); 1.1233 + 1.1234 + // if char array could be added to table 1.1235 + boolean canAddCharacterContentToTable = 1.1236 + canAddCharacterContentToTable(length, map); 1.1237 + 1.1238 + // obtain/get index 1.1239 + int index = canAddCharacterContentToTable ? 1.1240 + map.obtainIndex(ch, 0, length, false) : 1.1241 + map.get(ch, 0, length); 1.1242 + 1.1243 + if (index != KeyIntMap.NOT_PRESENT) { 1.1244 + // if char array is in table 1.1245 + encodeNonZeroIntegerOnSecondBitFirstBitOne(index); 1.1246 + } else if (canAddCharacterContentToTable) { 1.1247 + // if char array is not in table, but could be added 1.1248 + _b = EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG | 1.1249 + _nonIdentifyingStringOnFirstBitCES; 1.1250 + encodeNonEmptyCharacterStringOnFifthBit(ch, 0, length); 1.1251 + } else { 1.1252 + // if char array is not in table and could not be added 1.1253 + _b = _nonIdentifyingStringOnFirstBitCES; 1.1254 + encodeNonEmptyCharacterStringOnFifthBit(s); 1.1255 + } 1.1256 + } else { 1.1257 + _b = _nonIdentifyingStringOnFirstBitCES; 1.1258 + encodeNonEmptyCharacterStringOnFifthBit(s); 1.1259 + } 1.1260 + } 1.1261 + } 1.1262 + 1.1263 + /** 1.1264 + * Encode a non identifying string on the first bit of an octet. 1.1265 + * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1266 + * 1.1267 + * @param ch the array of characters. 1.1268 + * @param offset the offset into the array of characters. 1.1269 + * @param length the length of characters. 1.1270 + * @param map the vocabulary table of character arrays to indexes. 1.1271 + * @param addToTable true if the string should be added to the vocabulary 1.1272 + * table (if not already present in the table). 1.1273 + * @param clone true if the array of characters should be cloned if added 1.1274 + * to the vocabulary table. 1.1275 + */ 1.1276 + protected final void encodeNonIdentifyingStringOnFirstBit(char[] ch, int offset, int length, CharArrayIntMap map, 1.1277 + boolean addToTable, boolean clone) throws IOException { 1.1278 + if (length == 0) { 1.1279 + // C.26 an index (first bit '1') with seven '1' bits for an empty string 1.1280 + write(0xFF); 1.1281 + } else { 1.1282 + if (addToTable) { 1.1283 + // if char array could be added to table 1.1284 + boolean canAddCharacterContentToTable = 1.1285 + canAddCharacterContentToTable(length, map); 1.1286 + 1.1287 + // obtain/get index 1.1288 + int index = canAddCharacterContentToTable ? 1.1289 + map.obtainIndex(ch, offset, length, clone) : 1.1290 + map.get(ch, offset, length); 1.1291 + 1.1292 + if (index != KeyIntMap.NOT_PRESENT) { 1.1293 + // if char array is in table 1.1294 + encodeNonZeroIntegerOnSecondBitFirstBitOne(index); 1.1295 + } else if (canAddCharacterContentToTable) { 1.1296 + // if char array is not in table, but could be added 1.1297 + _b = EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG | 1.1298 + _nonIdentifyingStringOnFirstBitCES; 1.1299 + encodeNonEmptyCharacterStringOnFifthBit(ch, offset, length); 1.1300 + } else { 1.1301 + // if char array is not in table and could not be added 1.1302 + _b = _nonIdentifyingStringOnFirstBitCES; 1.1303 + encodeNonEmptyCharacterStringOnFifthBit(ch, offset, length); 1.1304 + } 1.1305 + } else { 1.1306 + _b = _nonIdentifyingStringOnFirstBitCES; 1.1307 + encodeNonEmptyCharacterStringOnFifthBit(ch, offset, length); 1.1308 + } 1.1309 + } 1.1310 + } 1.1311 + 1.1312 + protected final void encodeNumericNonIdentifyingStringOnFirstBit( 1.1313 + String s, boolean addToTable, boolean mustBeAddedToTable) 1.1314 + throws IOException, FastInfosetException { 1.1315 + encodeNonIdentifyingStringOnFirstBit( 1.1316 + RestrictedAlphabet.NUMERIC_CHARACTERS_INDEX, 1.1317 + NUMERIC_CHARACTERS_TABLE, s, addToTable, 1.1318 + mustBeAddedToTable); 1.1319 + } 1.1320 + 1.1321 + protected final void encodeDateTimeNonIdentifyingStringOnFirstBit( 1.1322 + String s, boolean addToTable, boolean mustBeAddedToTable) 1.1323 + throws IOException, FastInfosetException { 1.1324 + encodeNonIdentifyingStringOnFirstBit( 1.1325 + RestrictedAlphabet.DATE_TIME_CHARACTERS_INDEX, 1.1326 + DATE_TIME_CHARACTERS_TABLE, s, addToTable, 1.1327 + mustBeAddedToTable); 1.1328 + } 1.1329 + 1.1330 + protected final void encodeNonIdentifyingStringOnFirstBit(int id, int[] table, 1.1331 + String s, boolean addToTable, boolean mustBeAddedToTable) 1.1332 + throws IOException, FastInfosetException { 1.1333 + if (s == null || s.length() == 0) { 1.1334 + // C.26 an index (first bit '1') with seven '1' bits for an empty string 1.1335 + write(0xFF); 1.1336 + return; 1.1337 + } 1.1338 + 1.1339 + if (addToTable || mustBeAddedToTable) { 1.1340 + // if attribute value could be added to table 1.1341 + boolean canAddAttributeToTable = mustBeAddedToTable || 1.1342 + canAddAttributeToTable(s.length()); 1.1343 + 1.1344 + // obtain/get index 1.1345 + int index = canAddAttributeToTable ? 1.1346 + _v.attributeValue.obtainIndex(s) : 1.1347 + _v.attributeValue.get(s); 1.1348 + 1.1349 + if (index != KeyIntMap.NOT_PRESENT) { 1.1350 + // if attribute value is in table 1.1351 + encodeNonZeroIntegerOnSecondBitFirstBitOne(index); 1.1352 + return; 1.1353 + } else if (canAddAttributeToTable) { 1.1354 + // if attribute value is not in table, but could be added 1.1355 + _b = EncodingConstants.NISTRING_RESTRICTED_ALPHABET_FLAG | 1.1356 + EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG; 1.1357 + } else { 1.1358 + // if attribute value is not in table and could not be added 1.1359 + _b = EncodingConstants.NISTRING_RESTRICTED_ALPHABET_FLAG; 1.1360 + } 1.1361 + } else { 1.1362 + _b = EncodingConstants.NISTRING_RESTRICTED_ALPHABET_FLAG; 1.1363 + } 1.1364 + 1.1365 + // Encode identification and top four bits of alphabet id 1.1366 + write (_b | ((id & 0xF0) >> 4)); 1.1367 + // Encode bottom 4 bits of alphabet id 1.1368 + _b = (id & 0x0F) << 4; 1.1369 + 1.1370 + final int length = s.length(); 1.1371 + final int octetPairLength = length / 2; 1.1372 + final int octetSingleLength = length % 2; 1.1373 + encodeNonZeroOctetStringLengthOnFifthBit(octetPairLength + octetSingleLength); 1.1374 + encodeNonEmptyFourBitCharacterString(table, s.toCharArray(), 0, octetPairLength, octetSingleLength); 1.1375 + } 1.1376 + 1.1377 + /** 1.1378 + * Encode a non identifying string on the first bit of an octet as binary 1.1379 + * data using an encoding algorithm. 1.1380 + * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1381 + * 1.1382 + * @param URI the encoding algorithm URI. If the URI == null then the 1.1383 + * encoding algorithm identifier takes precendence. 1.1384 + * @param id the encoding algorithm identifier. 1.1385 + * @param data the data to be encoded using an encoding algorithm. 1.1386 + * @throws EncodingAlgorithmException if the encoding algorithm URI is not 1.1387 + * present in the vocabulary, or the encoding algorithm identifier 1.1388 + * is not with the required range. 1.1389 + */ 1.1390 + protected final void encodeNonIdentifyingStringOnFirstBit(String URI, int id, Object data) throws FastInfosetException, IOException { 1.1391 + if (URI != null) { 1.1392 + id = _v.encodingAlgorithm.get(URI); 1.1393 + if (id == KeyIntMap.NOT_PRESENT) { 1.1394 + throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.EncodingAlgorithmURI", new Object[]{URI})); 1.1395 + } 1.1396 + id += EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START; 1.1397 + 1.1398 + EncodingAlgorithm ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(URI); 1.1399 + if (ea != null) { 1.1400 + encodeAIIObjectAlgorithmData(id, data, ea); 1.1401 + } else { 1.1402 + if (data instanceof byte[]) { 1.1403 + byte[] d = (byte[])data; 1.1404 + encodeAIIOctetAlgorithmData(id, d, 0, d.length); 1.1405 + } else { 1.1406 + throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.nullEncodingAlgorithmURI")); 1.1407 + } 1.1408 + } 1.1409 + } else if (id <= EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) { 1.1410 + int length = 0; 1.1411 + switch(id) { 1.1412 + case EncodingAlgorithmIndexes.HEXADECIMAL: 1.1413 + case EncodingAlgorithmIndexes.BASE64: 1.1414 + length = ((byte[])data).length; 1.1415 + break; 1.1416 + case EncodingAlgorithmIndexes.SHORT: 1.1417 + length = ((short[])data).length; 1.1418 + break; 1.1419 + case EncodingAlgorithmIndexes.INT: 1.1420 + length = ((int[])data).length; 1.1421 + break; 1.1422 + case EncodingAlgorithmIndexes.LONG: 1.1423 + case EncodingAlgorithmIndexes.UUID: 1.1424 + length = ((long[])data).length; 1.1425 + break; 1.1426 + case EncodingAlgorithmIndexes.BOOLEAN: 1.1427 + length = ((boolean[])data).length; 1.1428 + break; 1.1429 + case EncodingAlgorithmIndexes.FLOAT: 1.1430 + length = ((float[])data).length; 1.1431 + break; 1.1432 + case EncodingAlgorithmIndexes.DOUBLE: 1.1433 + length = ((double[])data).length; 1.1434 + break; 1.1435 + case EncodingAlgorithmIndexes.CDATA: 1.1436 + throw new UnsupportedOperationException(CommonResourceBundle.getInstance().getString("message.CDATA")); 1.1437 + default: 1.1438 + throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.UnsupportedBuiltInAlgorithm", new Object[]{Integer.valueOf(id)})); 1.1439 + } 1.1440 + encodeAIIBuiltInAlgorithmData(id, data, 0, length); 1.1441 + } else if (id >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) { 1.1442 + if (data instanceof byte[]) { 1.1443 + byte[] d = (byte[])data; 1.1444 + encodeAIIOctetAlgorithmData(id, d, 0, d.length); 1.1445 + } else { 1.1446 + throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.nullEncodingAlgorithmURI")); 1.1447 + } 1.1448 + } else { 1.1449 + throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved")); 1.1450 + } 1.1451 + } 1.1452 + 1.1453 + /** 1.1454 + * Encode the [normalized value] of an Attribute Information Item using 1.1455 + * using an encoding algorithm. 1.1456 + * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1457 + * 1.1458 + * @param id the encoding algorithm identifier. 1.1459 + * @param d the data, as an array of bytes, to be encoded. 1.1460 + * @param offset the offset into the array of bytes. 1.1461 + * @param length the length of bytes. 1.1462 + */ 1.1463 + protected final void encodeAIIOctetAlgorithmData(int id, byte[] d, int offset, int length) throws IOException { 1.1464 + // Encode identification and top four bits of encoding algorithm id 1.1465 + write (EncodingConstants.NISTRING_ENCODING_ALGORITHM_FLAG | 1.1466 + ((id & 0xF0) >> 4)); 1.1467 + 1.1468 + // Encode bottom 4 bits of enoding algorithm id 1.1469 + _b = (id & 0x0F) << 4; 1.1470 + 1.1471 + // Encode the length 1.1472 + encodeNonZeroOctetStringLengthOnFifthBit(length); 1.1473 + 1.1474 + write(d, offset, length); 1.1475 + } 1.1476 + 1.1477 + /** 1.1478 + * Encode the [normalized value] of an Attribute Information Item using 1.1479 + * using an encoding algorithm. 1.1480 + * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1481 + * 1.1482 + * @param id the encoding algorithm identifier. 1.1483 + * @param data the data to be encoded using an encoding algorithm. 1.1484 + * @param ea the encoding algorithm to use to encode the data into an 1.1485 + * array of bytes. 1.1486 + */ 1.1487 + protected final void encodeAIIObjectAlgorithmData(int id, Object data, EncodingAlgorithm ea) throws FastInfosetException, IOException { 1.1488 + // Encode identification and top four bits of encoding algorithm id 1.1489 + write (EncodingConstants.NISTRING_ENCODING_ALGORITHM_FLAG | 1.1490 + ((id & 0xF0) >> 4)); 1.1491 + 1.1492 + // Encode bottom 4 bits of enoding algorithm id 1.1493 + _b = (id & 0x0F) << 4; 1.1494 + 1.1495 + _encodingBufferOutputStream.reset(); 1.1496 + ea.encodeToOutputStream(data, _encodingBufferOutputStream); 1.1497 + encodeNonZeroOctetStringLengthOnFifthBit(_encodingBufferIndex); 1.1498 + write(_encodingBuffer, _encodingBufferIndex); 1.1499 + } 1.1500 + 1.1501 + /** 1.1502 + * Encode the [normalized value] of an Attribute Information Item using 1.1503 + * using a built in encoding algorithm. 1.1504 + * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1505 + * 1.1506 + * @param id the built in encoding algorithm identifier. 1.1507 + * @param data the data to be encoded using an encoding algorithm. The data 1.1508 + * represents an array of items specified by the encoding algorithm 1.1509 + * identifier 1.1510 + * @param offset the offset into the array of bytes. 1.1511 + * @param length the length of bytes. 1.1512 + */ 1.1513 + protected final void encodeAIIBuiltInAlgorithmData(int id, Object data, int offset, int length) throws IOException { 1.1514 + // Encode identification and top four bits of encoding algorithm id 1.1515 + write (EncodingConstants.NISTRING_ENCODING_ALGORITHM_FLAG | 1.1516 + ((id & 0xF0) >> 4)); 1.1517 + 1.1518 + // Encode bottom 4 bits of enoding algorithm id 1.1519 + _b = (id & 0x0F) << 4; 1.1520 + 1.1521 + final int octetLength = BuiltInEncodingAlgorithmFactory.getAlgorithm(id). 1.1522 + getOctetLengthFromPrimitiveLength(length); 1.1523 + 1.1524 + encodeNonZeroOctetStringLengthOnFifthBit(octetLength); 1.1525 + 1.1526 + ensureSize(octetLength); 1.1527 + BuiltInEncodingAlgorithmFactory.getAlgorithm(id). 1.1528 + encodeToBytes(data, offset, length, _octetBuffer, _octetBufferIndex); 1.1529 + _octetBufferIndex += octetLength; 1.1530 + } 1.1531 + 1.1532 + /** 1.1533 + * Encode a non identifying string on the third bit of an octet. 1.1534 + * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1535 + * 1.1536 + * @param ch the array of characters. 1.1537 + * @param offset the offset into the array of characters. 1.1538 + * @param length the length of characters. 1.1539 + * @param map the vocabulary table of character arrays to indexes. 1.1540 + * @param addToTable true if the array of characters should be added to the vocabulary 1.1541 + * table (if not already present in the table). 1.1542 + * @param clone true if the array of characters should be cloned if added 1.1543 + * to the vocabulary table. 1.1544 + */ 1.1545 + protected final void encodeNonIdentifyingStringOnThirdBit(char[] ch, int offset, int length, 1.1546 + CharArrayIntMap map, boolean addToTable, boolean clone) throws IOException { 1.1547 + // length cannot be zero since sequence of CIIs has to be > 0 1.1548 + 1.1549 + if (addToTable) { 1.1550 + // if char array could be added to table 1.1551 + boolean canAddCharacterContentToTable = 1.1552 + canAddCharacterContentToTable(length, map); 1.1553 + 1.1554 + // obtain/get index 1.1555 + int index = canAddCharacterContentToTable ? 1.1556 + map.obtainIndex(ch, offset, length, clone) : 1.1557 + map.get(ch, offset, length); 1.1558 + 1.1559 + if (index != KeyIntMap.NOT_PRESENT) { 1.1560 + // if char array is in table 1.1561 + _b = EncodingConstants.CHARACTER_CHUNK | 0x20; 1.1562 + encodeNonZeroIntegerOnFourthBit(index); 1.1563 + } else if (canAddCharacterContentToTable) { 1.1564 + // if char array is not in table, but could be added 1.1565 + _b = EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG | 1.1566 + _nonIdentifyingStringOnThirdBitCES; 1.1567 + encodeNonEmptyCharacterStringOnSeventhBit(ch, offset, length); 1.1568 + } else { 1.1569 + // if char array is not in table and could not be added 1.1570 + _b = _nonIdentifyingStringOnThirdBitCES; 1.1571 + encodeNonEmptyCharacterStringOnSeventhBit(ch, offset, length); 1.1572 + } 1.1573 + } else { 1.1574 + // char array will not be added to map 1.1575 + _b = _nonIdentifyingStringOnThirdBitCES; 1.1576 + encodeNonEmptyCharacterStringOnSeventhBit(ch, offset, length); 1.1577 + } 1.1578 + } 1.1579 + 1.1580 + /** 1.1581 + * Encode a non identifying string on the third bit of an octet as binary 1.1582 + * data using an encoding algorithm. 1.1583 + * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1584 + * 1.1585 + * @param URI the encoding algorithm URI. If the URI == null then the 1.1586 + * encoding algorithm identifier takes precendence. 1.1587 + * @param id the encoding algorithm identifier. 1.1588 + * @param data the data to be encoded using an encoding algorithm. 1.1589 + * @throws EncodingAlgorithmException if the encoding algorithm URI is not 1.1590 + * present in the vocabulary, or the encoding algorithm identifier 1.1591 + * is not with the required range. 1.1592 + */ 1.1593 + protected final void encodeNonIdentifyingStringOnThirdBit(String URI, int id, Object data) throws FastInfosetException, IOException { 1.1594 + if (URI != null) { 1.1595 + id = _v.encodingAlgorithm.get(URI); 1.1596 + if (id == KeyIntMap.NOT_PRESENT) { 1.1597 + throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.EncodingAlgorithmURI", new Object[]{URI})); 1.1598 + } 1.1599 + id += EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START; 1.1600 + 1.1601 + EncodingAlgorithm ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(URI); 1.1602 + if (ea != null) { 1.1603 + encodeCIIObjectAlgorithmData(id, data, ea); 1.1604 + } else { 1.1605 + if (data instanceof byte[]) { 1.1606 + byte[] d = (byte[])data; 1.1607 + encodeCIIOctetAlgorithmData(id, d, 0, d.length); 1.1608 + } else { 1.1609 + throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.nullEncodingAlgorithmURI")); 1.1610 + } 1.1611 + } 1.1612 + } else if (id <= EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) { 1.1613 + int length = 0; 1.1614 + switch(id) { 1.1615 + case EncodingAlgorithmIndexes.HEXADECIMAL: 1.1616 + case EncodingAlgorithmIndexes.BASE64: 1.1617 + length = ((byte[])data).length; 1.1618 + break; 1.1619 + case EncodingAlgorithmIndexes.SHORT: 1.1620 + length = ((short[])data).length; 1.1621 + break; 1.1622 + case EncodingAlgorithmIndexes.INT: 1.1623 + length = ((int[])data).length; 1.1624 + break; 1.1625 + case EncodingAlgorithmIndexes.LONG: 1.1626 + case EncodingAlgorithmIndexes.UUID: 1.1627 + length = ((long[])data).length; 1.1628 + break; 1.1629 + case EncodingAlgorithmIndexes.BOOLEAN: 1.1630 + length = ((boolean[])data).length; 1.1631 + break; 1.1632 + case EncodingAlgorithmIndexes.FLOAT: 1.1633 + length = ((float[])data).length; 1.1634 + break; 1.1635 + case EncodingAlgorithmIndexes.DOUBLE: 1.1636 + length = ((double[])data).length; 1.1637 + break; 1.1638 + case EncodingAlgorithmIndexes.CDATA: 1.1639 + throw new UnsupportedOperationException(CommonResourceBundle.getInstance().getString("message.CDATA")); 1.1640 + default: 1.1641 + throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.UnsupportedBuiltInAlgorithm", new Object[]{Integer.valueOf(id)})); 1.1642 + } 1.1643 + encodeCIIBuiltInAlgorithmData(id, data, 0, length); 1.1644 + } else if (id >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) { 1.1645 + if (data instanceof byte[]) { 1.1646 + byte[] d = (byte[])data; 1.1647 + encodeCIIOctetAlgorithmData(id, d, 0, d.length); 1.1648 + } else { 1.1649 + throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.nullEncodingAlgorithmURI")); 1.1650 + } 1.1651 + } else { 1.1652 + throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved")); 1.1653 + } 1.1654 + } 1.1655 + 1.1656 + /** 1.1657 + * Encode a non identifying string on the third bit of an octet as binary 1.1658 + * data using an encoding algorithm. 1.1659 + * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1660 + * 1.1661 + * @param URI the encoding algorithm URI. If the URI == null then the 1.1662 + * encoding algorithm identifier takes precendence. 1.1663 + * @param id the encoding algorithm identifier. 1.1664 + * @param d the data, as an array of bytes, to be encoded. 1.1665 + * @param offset the offset into the array of bytes. 1.1666 + * @param length the length of bytes. 1.1667 + * @throws EncodingAlgorithmException if the encoding algorithm URI is not 1.1668 + * present in the vocabulary. 1.1669 + */ 1.1670 + protected final void encodeNonIdentifyingStringOnThirdBit(String URI, int id, byte[] d, int offset, int length) throws FastInfosetException, IOException { 1.1671 + if (URI != null) { 1.1672 + id = _v.encodingAlgorithm.get(URI); 1.1673 + if (id == KeyIntMap.NOT_PRESENT) { 1.1674 + throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.EncodingAlgorithmURI", new Object[]{URI})); 1.1675 + } 1.1676 + id += EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START; 1.1677 + } 1.1678 + 1.1679 + encodeCIIOctetAlgorithmData(id, d, offset, length); 1.1680 + } 1.1681 + 1.1682 + /** 1.1683 + * Encode a chunk of Character Information Items using 1.1684 + * using an encoding algorithm. 1.1685 + * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1686 + * 1.1687 + * @param id the encoding algorithm identifier. 1.1688 + * @param d the data, as an array of bytes, to be encoded. 1.1689 + * @param offset the offset into the array of bytes. 1.1690 + * @param length the length of bytes. 1.1691 + */ 1.1692 + protected final void encodeCIIOctetAlgorithmData(int id, byte[] d, int offset, int length) throws IOException { 1.1693 + // Encode identification and top two bits of encoding algorithm id 1.1694 + write (EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_ENCODING_ALGORITHM_FLAG | 1.1695 + ((id & 0xC0) >> 6)); 1.1696 + 1.1697 + // Encode bottom 6 bits of enoding algorithm id 1.1698 + _b = (id & 0x3F) << 2; 1.1699 + 1.1700 + // Encode the length 1.1701 + encodeNonZeroOctetStringLengthOnSenventhBit(length); 1.1702 + 1.1703 + write(d, offset, length); 1.1704 + } 1.1705 + 1.1706 + /** 1.1707 + * Encode a chunk of Character Information Items using 1.1708 + * using an encoding algorithm. 1.1709 + * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1710 + * 1.1711 + * @param id the encoding algorithm identifier. 1.1712 + * @param data the data to be encoded using an encoding algorithm. 1.1713 + * @param ea the encoding algorithm to use to encode the data into an 1.1714 + * array of bytes. 1.1715 + */ 1.1716 + protected final void encodeCIIObjectAlgorithmData(int id, Object data, EncodingAlgorithm ea) throws FastInfosetException, IOException { 1.1717 + // Encode identification and top two bits of encoding algorithm id 1.1718 + write (EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_ENCODING_ALGORITHM_FLAG | 1.1719 + ((id & 0xC0) >> 6)); 1.1720 + 1.1721 + // Encode bottom 6 bits of enoding algorithm id 1.1722 + _b = (id & 0x3F) << 2; 1.1723 + 1.1724 + _encodingBufferOutputStream.reset(); 1.1725 + ea.encodeToOutputStream(data, _encodingBufferOutputStream); 1.1726 + encodeNonZeroOctetStringLengthOnSenventhBit(_encodingBufferIndex); 1.1727 + write(_encodingBuffer, _encodingBufferIndex); 1.1728 + } 1.1729 + 1.1730 + /** 1.1731 + * Encode a chunk of Character Information Items using 1.1732 + * using an encoding algorithm. 1.1733 + * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1734 + * 1.1735 + * @param id the built in encoding algorithm identifier. 1.1736 + * @param data the data to be encoded using an encoding algorithm. The data 1.1737 + * represents an array of items specified by the encoding algorithm 1.1738 + * identifier 1.1739 + * @param offset the offset into the array of bytes. 1.1740 + * @param length the length of bytes. 1.1741 + */ 1.1742 + protected final void encodeCIIBuiltInAlgorithmData(int id, Object data, int offset, int length) throws FastInfosetException, IOException { 1.1743 + // Encode identification and top two bits of encoding algorithm id 1.1744 + write (EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_ENCODING_ALGORITHM_FLAG | 1.1745 + ((id & 0xC0) >> 6)); 1.1746 + 1.1747 + // Encode bottom 6 bits of enoding algorithm id 1.1748 + _b = (id & 0x3F) << 2; 1.1749 + 1.1750 + final int octetLength = BuiltInEncodingAlgorithmFactory.getAlgorithm(id). 1.1751 + getOctetLengthFromPrimitiveLength(length); 1.1752 + 1.1753 + encodeNonZeroOctetStringLengthOnSenventhBit(octetLength); 1.1754 + 1.1755 + ensureSize(octetLength); 1.1756 + BuiltInEncodingAlgorithmFactory.getAlgorithm(id). 1.1757 + encodeToBytes(data, offset, length, _octetBuffer, _octetBufferIndex); 1.1758 + _octetBufferIndex += octetLength; 1.1759 + } 1.1760 + 1.1761 + /** 1.1762 + * Encode a chunk of Character Information Items using 1.1763 + * using the CDATA built in encoding algorithm. 1.1764 + * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1765 + * 1.1766 + * @param ch the array of characters. 1.1767 + * @param offset the offset into the array of characters. 1.1768 + * @param length the length of characters. 1.1769 + */ 1.1770 + protected final void encodeCIIBuiltInAlgorithmDataAsCDATA(char[] ch, int offset, int length) throws FastInfosetException, IOException { 1.1771 + // Encode identification and top two bits of encoding algorithm id 1.1772 + write (EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_ENCODING_ALGORITHM_FLAG); 1.1773 + 1.1774 + // Encode bottom 6 bits of enoding algorithm id 1.1775 + _b = EncodingAlgorithmIndexes.CDATA << 2; 1.1776 + 1.1777 + 1.1778 + length = encodeUTF8String(ch, offset, length); 1.1779 + encodeNonZeroOctetStringLengthOnSenventhBit(length); 1.1780 + write(_encodingBuffer, length); 1.1781 + } 1.1782 + 1.1783 + /** 1.1784 + * Encode a non empty identifying string on the first bit of an octet. 1.1785 + * Implementation of clause C.13 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1786 + * 1.1787 + * @param s the identifying string. 1.1788 + * @param map the vocabulary table to use to determin the index of the 1.1789 + * identifying string 1.1790 + */ 1.1791 + protected final void encodeIdentifyingNonEmptyStringOnFirstBit(String s, StringIntMap map) throws IOException { 1.1792 + int index = map.obtainIndex(s); 1.1793 + if (index == KeyIntMap.NOT_PRESENT) { 1.1794 + // _b = 0; 1.1795 + encodeNonEmptyOctetStringOnSecondBit(s); 1.1796 + } else { 1.1797 + // _b = 0x80; 1.1798 + encodeNonZeroIntegerOnSecondBitFirstBitOne(index); 1.1799 + } 1.1800 + } 1.1801 + 1.1802 + /** 1.1803 + * Encode a non empty string on the second bit of an octet using the UTF-8 1.1804 + * encoding. 1.1805 + * Implementation of clause C.22 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1806 + * 1.1807 + * @param s the string. 1.1808 + */ 1.1809 + protected final void encodeNonEmptyOctetStringOnSecondBit(String s) throws IOException { 1.1810 + final int length = encodeUTF8String(s); 1.1811 + encodeNonZeroOctetStringLengthOnSecondBit(length); 1.1812 + write(_encodingBuffer, length); 1.1813 + } 1.1814 + 1.1815 + /** 1.1816 + * Encode the length of a UTF-8 encoded string on the second bit of an octet. 1.1817 + * Implementation of clause C.22 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1818 + * 1.1819 + * @param length the length to encode. 1.1820 + */ 1.1821 + protected final void encodeNonZeroOctetStringLengthOnSecondBit(int length) throws IOException { 1.1822 + if (length < EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT) { 1.1823 + // [1, 64] 1.1824 + write(length - 1); 1.1825 + } else if (length < EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT) { 1.1826 + // [65, 320] 1.1827 + write(EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_FLAG); // 010 00000 1.1828 + write(length - EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT); 1.1829 + } else { 1.1830 + // [321, 4294967296] 1.1831 + write(EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_LARGE_FLAG); // 0110 0000 1.1832 + length -= EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT; 1.1833 + write(length >>> 24); 1.1834 + write((length >> 16) & 0xFF); 1.1835 + write((length >> 8) & 0xFF); 1.1836 + write(length & 0xFF); 1.1837 + } 1.1838 + } 1.1839 + 1.1840 + /** 1.1841 + * Encode a non empty string on the fifth bit of an octet using the UTF-8 1.1842 + * or UTF-16 encoding. 1.1843 + * Implementation of clause C.23 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1844 + * 1.1845 + * @param s the string. 1.1846 + */ 1.1847 + protected final void encodeNonEmptyCharacterStringOnFifthBit(String s) throws IOException { 1.1848 + final int length = (_encodingStringsAsUtf8) ? encodeUTF8String(s) : encodeUtf16String(s); 1.1849 + encodeNonZeroOctetStringLengthOnFifthBit(length); 1.1850 + write(_encodingBuffer, length); 1.1851 + } 1.1852 + 1.1853 + /** 1.1854 + * Encode a non empty string on the fifth bit of an octet using the UTF-8 1.1855 + * or UTF-16 encoding. 1.1856 + * Implementation of clause C.23 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1857 + * 1.1858 + * @param ch the array of characters. 1.1859 + * @param offset the offset into the array of characters. 1.1860 + * @param length the length of characters. 1.1861 + */ 1.1862 + protected final void encodeNonEmptyCharacterStringOnFifthBit(char[] ch, int offset, int length) throws IOException { 1.1863 + length = (_encodingStringsAsUtf8) ? encodeUTF8String(ch, offset, length) : encodeUtf16String(ch, offset, length); 1.1864 + encodeNonZeroOctetStringLengthOnFifthBit(length); 1.1865 + write(_encodingBuffer, length); 1.1866 + } 1.1867 + 1.1868 + /** 1.1869 + * Encode the length of a UTF-8 or UTF-16 encoded string on the fifth bit 1.1870 + * of an octet. 1.1871 + * Implementation of clause C.23 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1872 + * 1.1873 + * @param length the length to encode. 1.1874 + */ 1.1875 + protected final void encodeNonZeroOctetStringLengthOnFifthBit(int length) throws IOException { 1.1876 + if (length < EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT) { 1.1877 + // [1, 8] 1.1878 + write(_b | (length - 1)); 1.1879 + } else if (length < EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT) { 1.1880 + // [9, 264] 1.1881 + write(_b | EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_FLAG); // 000010 00 1.1882 + write(length - EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT); 1.1883 + } else { 1.1884 + // [265, 4294967296] 1.1885 + write(_b | EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_LARGE_FLAG); // 000011 00 1.1886 + length -= EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT; 1.1887 + write(length >>> 24); 1.1888 + write((length >> 16) & 0xFF); 1.1889 + write((length >> 8) & 0xFF); 1.1890 + write(length & 0xFF); 1.1891 + } 1.1892 + } 1.1893 + 1.1894 + /** 1.1895 + * Encode a non empty string on the seventh bit of an octet using the UTF-8 1.1896 + * or UTF-16 encoding. 1.1897 + * Implementation of clause C.24 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1898 + * 1.1899 + * @param ch the array of characters. 1.1900 + * @param offset the offset into the array of characters. 1.1901 + * @param length the length of characters. 1.1902 + */ 1.1903 + protected final void encodeNonEmptyCharacterStringOnSeventhBit(char[] ch, int offset, int length) throws IOException { 1.1904 + length = (_encodingStringsAsUtf8) ? encodeUTF8String(ch, offset, length) : encodeUtf16String(ch, offset, length); 1.1905 + encodeNonZeroOctetStringLengthOnSenventhBit(length); 1.1906 + write(_encodingBuffer, length); 1.1907 + } 1.1908 + 1.1909 + /** 1.1910 + * Encode a non empty string on the seventh bit of an octet using a restricted 1.1911 + * alphabet that results in the encoding of a character in 4 bits 1.1912 + * (or two characters per octet). 1.1913 + * Implementation of clause C.24 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1914 + * 1.1915 + * @param table the table mapping characters to 4 bit values. 1.1916 + * @param ch the array of characters. 1.1917 + * @param offset the offset into the array of characters. 1.1918 + * @param length the length of characters. 1.1919 + */ 1.1920 + protected final void encodeNonEmptyFourBitCharacterStringOnSeventhBit(int[] table, char[] ch, int offset, int length) throws FastInfosetException, IOException { 1.1921 + final int octetPairLength = length / 2; 1.1922 + final int octetSingleLength = length % 2; 1.1923 + 1.1924 + // Encode the length 1.1925 + encodeNonZeroOctetStringLengthOnSenventhBit(octetPairLength + octetSingleLength); 1.1926 + encodeNonEmptyFourBitCharacterString(table, ch, offset, octetPairLength, octetSingleLength); 1.1927 + } 1.1928 + 1.1929 + protected final void encodeNonEmptyFourBitCharacterString(int[] table, char[] ch, int offset, 1.1930 + int octetPairLength, int octetSingleLength) throws FastInfosetException, IOException { 1.1931 + ensureSize(octetPairLength + octetSingleLength); 1.1932 + // Encode all pairs 1.1933 + int v = 0; 1.1934 + for (int i = 0; i < octetPairLength; i++) { 1.1935 + v = (table[ch[offset++]] << 4) | table[ch[offset++]]; 1.1936 + if (v < 0) { 1.1937 + throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.characterOutofAlphabetRange")); 1.1938 + } 1.1939 + _octetBuffer[_octetBufferIndex++] = (byte)v; 1.1940 + } 1.1941 + // Encode single character at end with termination bits 1.1942 + if (octetSingleLength == 1) { 1.1943 + v = (table[ch[offset]] << 4) | 0x0F; 1.1944 + if (v < 0) { 1.1945 + throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.characterOutofAlphabetRange")); 1.1946 + } 1.1947 + _octetBuffer[_octetBufferIndex++] = (byte)v; 1.1948 + } 1.1949 + } 1.1950 + 1.1951 + /** 1.1952 + * Encode a non empty string on the seventh bit of an octet using a restricted 1.1953 + * alphabet table. 1.1954 + * Implementation of clause C.24 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.1955 + * 1.1956 + * @param alphabet the alphabet defining the mapping between characters and 1.1957 + * integer values. 1.1958 + * @param ch the array of characters. 1.1959 + * @param offset the offset into the array of characters. 1.1960 + * @param length the length of characters. 1.1961 + */ 1.1962 + protected final void encodeNonEmptyNBitCharacterStringOnSeventhBit(String alphabet, char[] ch, int offset, int length) throws FastInfosetException, IOException { 1.1963 + int bitsPerCharacter = 1; 1.1964 + while ((1 << bitsPerCharacter) <= alphabet.length()) { 1.1965 + bitsPerCharacter++; 1.1966 + } 1.1967 + 1.1968 + final int bits = length * bitsPerCharacter; 1.1969 + final int octets = bits / 8; 1.1970 + final int bitsOfLastOctet = bits % 8; 1.1971 + final int totalOctets = octets + ((bitsOfLastOctet > 0) ? 1 : 0); 1.1972 + 1.1973 + // Encode the length 1.1974 + encodeNonZeroOctetStringLengthOnSenventhBit(totalOctets); 1.1975 + 1.1976 + resetBits(); 1.1977 + ensureSize(totalOctets); 1.1978 + int v = 0; 1.1979 + for (int i = 0; i < length; i++) { 1.1980 + final char c = ch[offset + i]; 1.1981 + // This is grotesquely slow, need to use hash table of character to int value 1.1982 + for (v = 0; v < alphabet.length(); v++) { 1.1983 + if (c == alphabet.charAt(v)) { 1.1984 + break; 1.1985 + } 1.1986 + } 1.1987 + if (v == alphabet.length()) { 1.1988 + throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.characterOutofAlphabetRange")); 1.1989 + } 1.1990 + writeBits(bitsPerCharacter, v); 1.1991 + } 1.1992 + 1.1993 + if (bitsOfLastOctet > 0) { 1.1994 + _b |= (1 << (8 - bitsOfLastOctet)) - 1; 1.1995 + write(_b); 1.1996 + } 1.1997 + } 1.1998 + 1.1999 + private int _bitsLeftInOctet; 1.2000 + 1.2001 + private final void resetBits() { 1.2002 + _bitsLeftInOctet = 8; 1.2003 + _b = 0; 1.2004 + } 1.2005 + 1.2006 + private final void writeBits(int bits, int v) throws IOException { 1.2007 + while (bits > 0) { 1.2008 + final int bit = (v & (1 << --bits)) > 0 ? 1 : 0; 1.2009 + _b |= bit << (--_bitsLeftInOctet); 1.2010 + if (_bitsLeftInOctet == 0) { 1.2011 + write(_b); 1.2012 + _bitsLeftInOctet = 8; 1.2013 + _b = 0; 1.2014 + } 1.2015 + } 1.2016 + } 1.2017 + 1.2018 + /** 1.2019 + * Encode the length of a encoded string on the seventh bit 1.2020 + * of an octet. 1.2021 + * Implementation of clause C.24 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.2022 + * 1.2023 + * @param length the length to encode. 1.2024 + */ 1.2025 + protected final void encodeNonZeroOctetStringLengthOnSenventhBit(int length) throws IOException { 1.2026 + if (length < EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT) { 1.2027 + // [1, 2] 1.2028 + write(_b | (length - 1)); 1.2029 + } else if (length < EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT) { 1.2030 + // [3, 258] 1.2031 + write(_b | EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_FLAG); // 00000010 1.2032 + write(length - EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT); 1.2033 + } else { 1.2034 + // [259, 4294967296] 1.2035 + write(_b | EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_LARGE_FLAG); // 00000011 1.2036 + length -= EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT; 1.2037 + write(length >>> 24); 1.2038 + write((length >> 16) & 0xFF); 1.2039 + write((length >> 8) & 0xFF); 1.2040 + write(length & 0xFF); 1.2041 + } 1.2042 + } 1.2043 + 1.2044 + /** 1.2045 + * Encode a non zero integer on the second bit of an octet, setting 1.2046 + * the first bit to 1. 1.2047 + * Implementation of clause C.24 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.2048 + * 1.2049 + * <p> 1.2050 + * The first bit of the first octet is set, as specified in clause C.13 of 1.2051 + * ITU-T Rec. X.891 | ISO/IEC 24824-1 1.2052 + * 1.2053 + * @param i The integer to encode, which is a member of the interval 1.2054 + * [0, 1048575]. In the specification the interval is [1, 1048576] 1.2055 + * 1.2056 + */ 1.2057 + protected final void encodeNonZeroIntegerOnSecondBitFirstBitOne(int i) throws IOException { 1.2058 + if (i < EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT) { 1.2059 + // [1, 64] ( [0, 63] ) 6 bits 1.2060 + write(0x80 | i); 1.2061 + } else if (i < EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT) { 1.2062 + // [65, 8256] ( [64, 8255] ) 13 bits 1.2063 + i -= EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; 1.2064 + _b = (0x80 | EncodingConstants.INTEGER_2ND_BIT_MEDIUM_FLAG) | (i >> 8); // 010 00000 1.2065 + // _b = 0xC0 | (i >> 8); // 010 00000 1.2066 + write(_b); 1.2067 + write(i & 0xFF); 1.2068 + } else if (i < EncodingConstants.INTEGER_2ND_BIT_LARGE_LIMIT) { 1.2069 + // [8257, 1048576] ( [8256, 1048575] ) 20 bits 1.2070 + i -= EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; 1.2071 + _b = (0x80 | EncodingConstants.INTEGER_2ND_BIT_LARGE_FLAG) | (i >> 16); // 0110 0000 1.2072 + // _b = 0xE0 | (i >> 16); // 0110 0000 1.2073 + write(_b); 1.2074 + write((i >> 8) & 0xFF); 1.2075 + write(i & 0xFF); 1.2076 + } else { 1.2077 + throw new IOException( 1.2078 + CommonResourceBundle.getInstance().getString("message.integerMaxSize", 1.2079 + new Object[]{Integer.valueOf(EncodingConstants.INTEGER_2ND_BIT_LARGE_LIMIT)})); 1.2080 + } 1.2081 + } 1.2082 + 1.2083 + /** 1.2084 + * Encode a non zero integer on the second bit of an octet, setting 1.2085 + * the first bit to 0. 1.2086 + * Implementation of clause C.25 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.2087 + * 1.2088 + * <p> 1.2089 + * The first bit of the first octet is set, as specified in clause C.13 of 1.2090 + * ITU-T Rec. X.891 | ISO/IEC 24824-1 1.2091 + * 1.2092 + * @param i The integer to encode, which is a member of the interval 1.2093 + * [0, 1048575]. In the specification the interval is [1, 1048576] 1.2094 + * 1.2095 + */ 1.2096 + protected final void encodeNonZeroIntegerOnSecondBitFirstBitZero(int i) throws IOException { 1.2097 + if (i < EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT) { 1.2098 + // [1, 64] ( [0, 63] ) 6 bits 1.2099 + write(i); 1.2100 + } else if (i < EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT) { 1.2101 + // [65, 8256] ( [64, 8255] ) 13 bits 1.2102 + i -= EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; 1.2103 + _b = EncodingConstants.INTEGER_2ND_BIT_MEDIUM_FLAG | (i >> 8); // 010 00000 1.2104 + write(_b); 1.2105 + write(i & 0xFF); 1.2106 + } else { 1.2107 + // [8257, 1048576] ( [8256, 1048575] ) 20 bits 1.2108 + i -= EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; 1.2109 + _b = EncodingConstants.INTEGER_2ND_BIT_LARGE_FLAG | (i >> 16); // 0110 0000 1.2110 + write(_b); 1.2111 + write((i >> 8) & 0xFF); 1.2112 + write(i & 0xFF); 1.2113 + } 1.2114 + } 1.2115 + 1.2116 + /** 1.2117 + * Encode a non zero integer on the third bit of an octet. 1.2118 + * Implementation of clause C.27 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.2119 + * 1.2120 + * @param i The integer to encode, which is a member of the interval 1.2121 + * [0, 1048575]. In the specification the interval is [1, 1048576] 1.2122 + * 1.2123 + */ 1.2124 + protected final void encodeNonZeroIntegerOnThirdBit(int i) throws IOException { 1.2125 + if (i < EncodingConstants.INTEGER_3RD_BIT_SMALL_LIMIT) { 1.2126 + // [1, 32] ( [0, 31] ) 5 bits 1.2127 + write(_b | i); 1.2128 + } else if (i < EncodingConstants.INTEGER_3RD_BIT_MEDIUM_LIMIT) { 1.2129 + // [33, 2080] ( [32, 2079] ) 11 bits 1.2130 + i -= EncodingConstants.INTEGER_3RD_BIT_SMALL_LIMIT; 1.2131 + _b |= EncodingConstants.INTEGER_3RD_BIT_MEDIUM_FLAG | (i >> 8); // 00100 000 1.2132 + write(_b); 1.2133 + write(i & 0xFF); 1.2134 + } else if (i < EncodingConstants.INTEGER_3RD_BIT_LARGE_LIMIT) { 1.2135 + // [2081, 526368] ( [2080, 526367] ) 19 bits 1.2136 + i -= EncodingConstants.INTEGER_3RD_BIT_MEDIUM_LIMIT; 1.2137 + _b |= EncodingConstants.INTEGER_3RD_BIT_LARGE_FLAG | (i >> 16); // 00101 000 1.2138 + write(_b); 1.2139 + write((i >> 8) & 0xFF); 1.2140 + write(i & 0xFF); 1.2141 + } else { 1.2142 + // [526369, 1048576] ( [526368, 1048575] ) 20 bits 1.2143 + i -= EncodingConstants.INTEGER_3RD_BIT_LARGE_LIMIT; 1.2144 + _b |= EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_FLAG; // 00110 000 1.2145 + write(_b); 1.2146 + write(i >> 16); 1.2147 + write((i >> 8) & 0xFF); 1.2148 + write(i & 0xFF); 1.2149 + } 1.2150 + } 1.2151 + 1.2152 + /** 1.2153 + * Encode a non zero integer on the fourth bit of an octet. 1.2154 + * Implementation of clause C.28 of ITU-T Rec. X.891 | ISO/IEC 24824-1. 1.2155 + * 1.2156 + * @param i The integer to encode, which is a member of the interval 1.2157 + * [0, 1048575]. In the specification the interval is [1, 1048576] 1.2158 + * 1.2159 + */ 1.2160 + protected final void encodeNonZeroIntegerOnFourthBit(int i) throws IOException { 1.2161 + if (i < EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT) { 1.2162 + // [1, 16] ( [0, 15] ) 4 bits 1.2163 + write(_b | i); 1.2164 + } else if (i < EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT) { 1.2165 + // [17, 1040] ( [16, 1039] ) 10 bits 1.2166 + i -= EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT; 1.2167 + _b |= EncodingConstants.INTEGER_4TH_BIT_MEDIUM_FLAG | (i >> 8); // 000 100 00 1.2168 + write(_b); 1.2169 + write(i & 0xFF); 1.2170 + } else if (i < EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT) { 1.2171 + // [1041, 263184] ( [1040, 263183] ) 18 bits 1.2172 + i -= EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT; 1.2173 + _b |= EncodingConstants.INTEGER_4TH_BIT_LARGE_FLAG | (i >> 16); // 000 101 00 1.2174 + write(_b); 1.2175 + write((i >> 8) & 0xFF); 1.2176 + write(i & 0xFF); 1.2177 + } else { 1.2178 + // [263185, 1048576] ( [263184, 1048575] ) 20 bits 1.2179 + i -= EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT; 1.2180 + _b |= EncodingConstants.INTEGER_4TH_BIT_LARGE_LARGE_FLAG; // 000 110 00 1.2181 + write(_b); 1.2182 + write(i >> 16); 1.2183 + write((i >> 8) & 0xFF); 1.2184 + write(i & 0xFF); 1.2185 + } 1.2186 + } 1.2187 + 1.2188 + /** 1.2189 + * Encode a non empty string using the UTF-8 encoding. 1.2190 + * 1.2191 + * @param b the current octet that is being written. 1.2192 + * @param s the string to be UTF-8 encoded. 1.2193 + * @param constants the array of constants to use when encoding to determin 1.2194 + * how the length of the UTF-8 encoded string is encoded. 1.2195 + */ 1.2196 + protected final void encodeNonEmptyUTF8StringAsOctetString(int b, String s, int[] constants) throws IOException { 1.2197 + final char[] ch = s.toCharArray(); 1.2198 + encodeNonEmptyUTF8StringAsOctetString(b, ch, 0, ch.length, constants); 1.2199 + } 1.2200 + 1.2201 + /** 1.2202 + * Encode a non empty string using the UTF-8 encoding. 1.2203 + * 1.2204 + * @param b the current octet that is being written. 1.2205 + * @param ch the array of characters. 1.2206 + * @param offset the offset into the array of characters. 1.2207 + * @param length the length of characters. 1.2208 + * how the length of the UTF-8 encoded string is encoded. 1.2209 + * @param constants the array of constants to use when encoding to determin 1.2210 + * how the length of the UTF-8 encoded string is encoded. 1.2211 + */ 1.2212 + protected final void encodeNonEmptyUTF8StringAsOctetString(int b, char ch[], int offset, int length, int[] constants) throws IOException { 1.2213 + length = encodeUTF8String(ch, offset, length); 1.2214 + encodeNonZeroOctetStringLength(b, length, constants); 1.2215 + write(_encodingBuffer, length); 1.2216 + } 1.2217 + 1.2218 + /** 1.2219 + * Encode the length of non empty UTF-8 encoded string. 1.2220 + * 1.2221 + * @param b the current octet that is being written. 1.2222 + * @param length the length of the UTF-8 encoded string. 1.2223 + * how the length of the UTF-8 encoded string is encoded. 1.2224 + * @param constants the array of constants to use when encoding to determin 1.2225 + * how the length of the UTF-8 encoded string is encoded. 1.2226 + */ 1.2227 + protected final void encodeNonZeroOctetStringLength(int b, int length, int[] constants) throws IOException { 1.2228 + if (length < constants[EncodingConstants.OCTET_STRING_LENGTH_SMALL_LIMIT]) { 1.2229 + write(b | (length - 1)); 1.2230 + } else if (length < constants[EncodingConstants.OCTET_STRING_LENGTH_MEDIUM_LIMIT]) { 1.2231 + write(b | constants[EncodingConstants.OCTET_STRING_LENGTH_MEDIUM_FLAG]); 1.2232 + write(length - constants[EncodingConstants.OCTET_STRING_LENGTH_SMALL_LIMIT]); 1.2233 + } else { 1.2234 + write(b | constants[EncodingConstants.OCTET_STRING_LENGTH_LARGE_FLAG]); 1.2235 + length -= constants[EncodingConstants.OCTET_STRING_LENGTH_MEDIUM_LIMIT]; 1.2236 + write(length >>> 24); 1.2237 + write((length >> 16) & 0xFF); 1.2238 + write((length >> 8) & 0xFF); 1.2239 + write(length & 0xFF); 1.2240 + } 1.2241 + } 1.2242 + 1.2243 + /** 1.2244 + * Encode a non zero integer. 1.2245 + * 1.2246 + * @param b the current octet that is being written. 1.2247 + * @param i the non zero integer. 1.2248 + * @param constants the array of constants to use when encoding to determin 1.2249 + * how the non zero integer is encoded. 1.2250 + */ 1.2251 + protected final void encodeNonZeroInteger(int b, int i, int[] constants) throws IOException { 1.2252 + if (i < constants[EncodingConstants.INTEGER_SMALL_LIMIT]) { 1.2253 + write(b | i); 1.2254 + } else if (i < constants[EncodingConstants.INTEGER_MEDIUM_LIMIT]) { 1.2255 + i -= constants[EncodingConstants.INTEGER_SMALL_LIMIT]; 1.2256 + write(b | constants[EncodingConstants.INTEGER_MEDIUM_FLAG] | (i >> 8)); 1.2257 + write(i & 0xFF); 1.2258 + } else if (i < constants[EncodingConstants.INTEGER_LARGE_LIMIT]) { 1.2259 + i -= constants[EncodingConstants.INTEGER_MEDIUM_LIMIT]; 1.2260 + write(b | constants[EncodingConstants.INTEGER_LARGE_FLAG] | (i >> 16)); 1.2261 + write((i >> 8) & 0xFF); 1.2262 + write(i & 0xFF); 1.2263 + } else if (i < EncodingConstants.INTEGER_MAXIMUM_SIZE) { 1.2264 + i -= constants[EncodingConstants.INTEGER_LARGE_LIMIT]; 1.2265 + write(b | constants[EncodingConstants.INTEGER_LARGE_LARGE_FLAG]); 1.2266 + write(i >> 16); 1.2267 + write((i >> 8) & 0xFF); 1.2268 + write(i & 0xFF); 1.2269 + } else { 1.2270 + throw new IOException(CommonResourceBundle.getInstance().getString("message.integerMaxSize", new Object[]{Integer.valueOf(EncodingConstants.INTEGER_MAXIMUM_SIZE)})); 1.2271 + } 1.2272 + } 1.2273 + 1.2274 + /** 1.2275 + * Mark the current position in the buffered stream. 1.2276 + */ 1.2277 + protected final void mark() { 1.2278 + _markIndex = _octetBufferIndex; 1.2279 + } 1.2280 + 1.2281 + /** 1.2282 + * Reset the marked position in the buffered stream. 1.2283 + */ 1.2284 + protected final void resetMark() { 1.2285 + _markIndex = -1; 1.2286 + } 1.2287 + 1.2288 + /** 1.2289 + * @return true if the mark has been set, otherwise false if the mark 1.2290 + * has not been set. 1.2291 + */ 1.2292 + protected final boolean hasMark() { 1.2293 + return _markIndex != -1; 1.2294 + } 1.2295 + 1.2296 + /** 1.2297 + * Write a byte to the buffered stream. 1.2298 + */ 1.2299 + protected final void write(int i) throws IOException { 1.2300 + if (_octetBufferIndex < _octetBuffer.length) { 1.2301 + _octetBuffer[_octetBufferIndex++] = (byte)i; 1.2302 + } else { 1.2303 + if (_markIndex == -1) { 1.2304 + _s.write(_octetBuffer); 1.2305 + _octetBufferIndex = 1; 1.2306 + _octetBuffer[0] = (byte)i; 1.2307 + } else { 1.2308 + resize(_octetBuffer.length * 3 / 2); 1.2309 + _octetBuffer[_octetBufferIndex++] = (byte)i; 1.2310 + } 1.2311 + } 1.2312 + } 1.2313 + 1.2314 + /** 1.2315 + * Write an array of bytes to the buffered stream. 1.2316 + * 1.2317 + * @param b the array of bytes. 1.2318 + * @param length the length of bytes. 1.2319 + */ 1.2320 + protected final void write(byte[] b, int length) throws IOException { 1.2321 + write(b, 0, length); 1.2322 + } 1.2323 + 1.2324 + /** 1.2325 + * Write an array of bytes to the buffered stream. 1.2326 + * 1.2327 + * @param b the array of bytes. 1.2328 + * @param offset the offset into the array of bytes. 1.2329 + * @param length the length of bytes. 1.2330 + */ 1.2331 + protected final void write(byte[] b, int offset, int length) throws IOException { 1.2332 + if ((_octetBufferIndex + length) < _octetBuffer.length) { 1.2333 + System.arraycopy(b, offset, _octetBuffer, _octetBufferIndex, length); 1.2334 + _octetBufferIndex += length; 1.2335 + } else { 1.2336 + if (_markIndex == -1) { 1.2337 + _s.write(_octetBuffer, 0, _octetBufferIndex); 1.2338 + _s.write(b, offset, length); 1.2339 + _octetBufferIndex = 0; 1.2340 + } else { 1.2341 + resize((_octetBuffer.length + length) * 3 / 2 + 1); 1.2342 + System.arraycopy(b, offset, _octetBuffer, _octetBufferIndex, length); 1.2343 + _octetBufferIndex += length; 1.2344 + } 1.2345 + } 1.2346 + } 1.2347 + 1.2348 + private void ensureSize(int length) { 1.2349 + if ((_octetBufferIndex + length) > _octetBuffer.length) { 1.2350 + resize((_octetBufferIndex + length) * 3 / 2 + 1); 1.2351 + } 1.2352 + } 1.2353 + 1.2354 + private void resize(int length) { 1.2355 + byte[] b = new byte[length]; 1.2356 + System.arraycopy(_octetBuffer, 0, b, 0, _octetBufferIndex); 1.2357 + _octetBuffer = b; 1.2358 + } 1.2359 + 1.2360 + private void _flush() throws IOException { 1.2361 + if (_octetBufferIndex > 0) { 1.2362 + _s.write(_octetBuffer, 0, _octetBufferIndex); 1.2363 + _octetBufferIndex = 0; 1.2364 + } 1.2365 + } 1.2366 + 1.2367 + 1.2368 + private EncodingBufferOutputStream _encodingBufferOutputStream = new EncodingBufferOutputStream(); 1.2369 + 1.2370 + private byte[] _encodingBuffer = new byte[512]; 1.2371 + 1.2372 + private int _encodingBufferIndex; 1.2373 + 1.2374 + private class EncodingBufferOutputStream extends OutputStream { 1.2375 + 1.2376 + public void write(int b) throws IOException { 1.2377 + if (_encodingBufferIndex < _encodingBuffer.length) { 1.2378 + _encodingBuffer[_encodingBufferIndex++] = (byte)b; 1.2379 + } else { 1.2380 + byte newbuf[] = new byte[Math.max(_encodingBuffer.length << 1, _encodingBufferIndex)]; 1.2381 + System.arraycopy(_encodingBuffer, 0, newbuf, 0, _encodingBufferIndex); 1.2382 + _encodingBuffer = newbuf; 1.2383 + 1.2384 + _encodingBuffer[_encodingBufferIndex++] = (byte)b; 1.2385 + } 1.2386 + } 1.2387 + 1.2388 + public void write(byte b[], int off, int len) throws IOException { 1.2389 + if ((off < 0) || (off > b.length) || (len < 0) || 1.2390 + ((off + len) > b.length) || ((off + len) < 0)) { 1.2391 + throw new IndexOutOfBoundsException(); 1.2392 + } else if (len == 0) { 1.2393 + return; 1.2394 + } 1.2395 + final int newoffset = _encodingBufferIndex + len; 1.2396 + if (newoffset > _encodingBuffer.length) { 1.2397 + byte newbuf[] = new byte[Math.max(_encodingBuffer.length << 1, newoffset)]; 1.2398 + System.arraycopy(_encodingBuffer, 0, newbuf, 0, _encodingBufferIndex); 1.2399 + _encodingBuffer = newbuf; 1.2400 + } 1.2401 + System.arraycopy(b, off, _encodingBuffer, _encodingBufferIndex, len); 1.2402 + _encodingBufferIndex = newoffset; 1.2403 + } 1.2404 + 1.2405 + public int getLength() { 1.2406 + return _encodingBufferIndex; 1.2407 + } 1.2408 + 1.2409 + public void reset() { 1.2410 + _encodingBufferIndex = 0; 1.2411 + } 1.2412 + } 1.2413 + 1.2414 + /** 1.2415 + * Encode a string using the UTF-8 encoding. 1.2416 + * 1.2417 + * @param s the string to encode. 1.2418 + */ 1.2419 + protected final int encodeUTF8String(String s) throws IOException { 1.2420 + final int length = s.length(); 1.2421 + if (length < _charBuffer.length) { 1.2422 + s.getChars(0, length, _charBuffer, 0); 1.2423 + return encodeUTF8String(_charBuffer, 0, length); 1.2424 + } else { 1.2425 + char[] ch = s.toCharArray(); 1.2426 + return encodeUTF8String(ch, 0, length); 1.2427 + } 1.2428 + } 1.2429 + 1.2430 + private void ensureEncodingBufferSizeForUtf8String(int length) { 1.2431 + final int newLength = 4 * length; 1.2432 + if (_encodingBuffer.length < newLength) { 1.2433 + _encodingBuffer = new byte[newLength]; 1.2434 + } 1.2435 + } 1.2436 + 1.2437 + /** 1.2438 + * Encode a string using the UTF-8 encoding. 1.2439 + * 1.2440 + * @param ch the array of characters. 1.2441 + * @param offset the offset into the array of characters. 1.2442 + * @param length the length of characters. 1.2443 + */ 1.2444 + protected final int encodeUTF8String(char[] ch, int offset, int length) throws IOException { 1.2445 + int bpos = 0; 1.2446 + 1.2447 + // Make sure buffer is large enough 1.2448 + ensureEncodingBufferSizeForUtf8String(length); 1.2449 + 1.2450 + final int end = offset + length; 1.2451 + int c; 1.2452 + while (end != offset) { 1.2453 + c = ch[offset++]; 1.2454 + if (c < 0x80) { 1.2455 + // 1 byte, 7 bits 1.2456 + _encodingBuffer[bpos++] = (byte) c; 1.2457 + } else if (c < 0x800) { 1.2458 + // 2 bytes, 11 bits 1.2459 + _encodingBuffer[bpos++] = 1.2460 + (byte) (0xC0 | (c >> 6)); // first 5 1.2461 + _encodingBuffer[bpos++] = 1.2462 + (byte) (0x80 | (c & 0x3F)); // second 6 1.2463 + } else if (c <= '\uFFFF') { 1.2464 + if (!XMLChar.isHighSurrogate(c) && !XMLChar.isLowSurrogate(c)) { 1.2465 + // 3 bytes, 16 bits 1.2466 + _encodingBuffer[bpos++] = 1.2467 + (byte) (0xE0 | (c >> 12)); // first 4 1.2468 + _encodingBuffer[bpos++] = 1.2469 + (byte) (0x80 | ((c >> 6) & 0x3F)); // second 6 1.2470 + _encodingBuffer[bpos++] = 1.2471 + (byte) (0x80 | (c & 0x3F)); // third 6 1.2472 + } else { 1.2473 + // 4 bytes, high and low surrogate 1.2474 + encodeCharacterAsUtf8FourByte(c, ch, offset, end, bpos); 1.2475 + bpos += 4; 1.2476 + offset++; 1.2477 + } 1.2478 + } 1.2479 + } 1.2480 + 1.2481 + return bpos; 1.2482 + } 1.2483 + 1.2484 + private void encodeCharacterAsUtf8FourByte(int c, char[] ch, int chpos, int chend, int bpos) throws IOException { 1.2485 + if (chpos == chend) { 1.2486 + throw new IOException(""); 1.2487 + } 1.2488 + 1.2489 + final char d = ch[chpos]; 1.2490 + if (!XMLChar.isLowSurrogate(d)) { 1.2491 + throw new IOException(""); 1.2492 + } 1.2493 + 1.2494 + final int uc = (((c & 0x3ff) << 10) | (d & 0x3ff)) + 0x10000; 1.2495 + if (uc < 0 || uc >= 0x200000) { 1.2496 + throw new IOException(""); 1.2497 + } 1.2498 + 1.2499 + _encodingBuffer[bpos++] = (byte)(0xF0 | ((uc >> 18))); 1.2500 + _encodingBuffer[bpos++] = (byte)(0x80 | ((uc >> 12) & 0x3F)); 1.2501 + _encodingBuffer[bpos++] = (byte)(0x80 | ((uc >> 6) & 0x3F)); 1.2502 + _encodingBuffer[bpos++] = (byte)(0x80 | (uc & 0x3F)); 1.2503 + } 1.2504 + 1.2505 + /** 1.2506 + * Encode a string using the UTF-16 encoding. 1.2507 + * 1.2508 + * @param s the string to encode. 1.2509 + */ 1.2510 + protected final int encodeUtf16String(String s) throws IOException { 1.2511 + final int length = s.length(); 1.2512 + if (length < _charBuffer.length) { 1.2513 + s.getChars(0, length, _charBuffer, 0); 1.2514 + return encodeUtf16String(_charBuffer, 0, length); 1.2515 + } else { 1.2516 + char[] ch = s.toCharArray(); 1.2517 + return encodeUtf16String(ch, 0, length); 1.2518 + } 1.2519 + } 1.2520 + 1.2521 + private void ensureEncodingBufferSizeForUtf16String(int length) { 1.2522 + final int newLength = 2 * length; 1.2523 + if (_encodingBuffer.length < newLength) { 1.2524 + _encodingBuffer = new byte[newLength]; 1.2525 + } 1.2526 + } 1.2527 + 1.2528 + /** 1.2529 + * Encode a string using the UTF-16 encoding. 1.2530 + * 1.2531 + * @param ch the array of characters. 1.2532 + * @param offset the offset into the array of characters. 1.2533 + * @param length the length of characters. 1.2534 + */ 1.2535 + protected final int encodeUtf16String(char[] ch, int offset, int length) throws IOException { 1.2536 + int byteLength = 0; 1.2537 + 1.2538 + // Make sure buffer is large enough 1.2539 + ensureEncodingBufferSizeForUtf16String(length); 1.2540 + 1.2541 + final int n = offset + length; 1.2542 + for (int i = offset; i < n; i++) { 1.2543 + final int c = (int) ch[i]; 1.2544 + _encodingBuffer[byteLength++] = (byte)(c >> 8); 1.2545 + _encodingBuffer[byteLength++] = (byte)(c & 0xFF); 1.2546 + } 1.2547 + 1.2548 + return byteLength; 1.2549 + } 1.2550 + 1.2551 + /** 1.2552 + * Obtain the prefix from a qualified name. 1.2553 + * 1.2554 + * @param qName the qualified name 1.2555 + * @return the prefix, or "" if there is no prefix. 1.2556 + */ 1.2557 + public static String getPrefixFromQualifiedName(String qName) { 1.2558 + int i = qName.indexOf(':'); 1.2559 + String prefix = ""; 1.2560 + if (i != -1) { 1.2561 + prefix = qName.substring(0, i); 1.2562 + } 1.2563 + return prefix; 1.2564 + } 1.2565 + 1.2566 + /** 1.2567 + * Check if character array contains characters that are all white space. 1.2568 + * 1.2569 + * @param ch the character array 1.2570 + * @param start the starting character index into the array to check from 1.2571 + * @param length the number of characters to check 1.2572 + * @return true if all characters are white space, false otherwise 1.2573 + */ 1.2574 + public static boolean isWhiteSpace(final char[] ch, int start, final int length) { 1.2575 + if (!XMLChar.isSpace(ch[start])) return false; 1.2576 + 1.2577 + final int end = start + length; 1.2578 + while(++start < end && XMLChar.isSpace(ch[start])); 1.2579 + 1.2580 + return start == end; 1.2581 + } 1.2582 + 1.2583 + /** 1.2584 + * Check if a String contains characters that are all white space. 1.2585 + * 1.2586 + * @param s the string 1.2587 + * @return true if all characters are white space, false otherwise 1.2588 + */ 1.2589 + public static boolean isWhiteSpace(String s) { 1.2590 + if (!XMLChar.isSpace(s.charAt(0))) return false; 1.2591 + 1.2592 + final int end = s.length(); 1.2593 + int start = 1; 1.2594 + while(start < end && XMLChar.isSpace(s.charAt(start++))); 1.2595 + return start == end; 1.2596 + } 1.2597 +}