aoqi@0: /* aoqi@0: * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.fastinfoset.algorithm; aoqi@0: aoqi@0: aoqi@0: import java.io.EOFException; aoqi@0: import java.io.IOException; aoqi@0: import java.io.InputStream; aoqi@0: import java.io.OutputStream; aoqi@0: import java.nio.CharBuffer; aoqi@0: import java.util.ArrayList; aoqi@0: import java.util.List; aoqi@0: aoqi@0: import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmException; aoqi@0: import com.sun.xml.internal.fastinfoset.CommonResourceBundle; aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * aoqi@0: * An encoder for handling boolean values. Suppports the builtin BOOLEAN encoder. aoqi@0: * aoqi@0: * @author Alan Hudson aoqi@0: * @author Paul Sandoz aoqi@0: * aoqi@0: */ aoqi@0: public class BooleanEncodingAlgorithm extends BuiltInEncodingAlgorithm { aoqi@0: aoqi@0: /** Table for setting a particular bit of a byte */ aoqi@0: private static final int[] BIT_TABLE = { aoqi@0: 1 << 7, aoqi@0: 1 << 6, aoqi@0: 1 << 5, aoqi@0: 1 << 4, aoqi@0: 1 << 3, aoqi@0: 1 << 2, aoqi@0: 1 << 1, aoqi@0: 1 << 0}; aoqi@0: aoqi@0: public int getPrimtiveLengthFromOctetLength(int octetLength) throws EncodingAlgorithmException { aoqi@0: // Cannot determine the number of boolean values from just the octet length aoqi@0: throw new UnsupportedOperationException(); aoqi@0: } aoqi@0: aoqi@0: public int getOctetLengthFromPrimitiveLength(int primitiveLength) { aoqi@0: if (primitiveLength < 5) { aoqi@0: return 1; aoqi@0: } else { aoqi@0: final int div = primitiveLength / 8; aoqi@0: return (div == 0) ? 2 : 1 + div; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final Object decodeFromBytes(byte[] b, int start, int length) throws EncodingAlgorithmException { aoqi@0: final int blength = getPrimtiveLengthFromOctetLength(length, b[start]); aoqi@0: boolean[] data = new boolean[blength]; aoqi@0: aoqi@0: decodeFromBytesToBooleanArray(data, 0, blength, b, start, length); aoqi@0: return data; aoqi@0: } aoqi@0: aoqi@0: public final Object decodeFromInputStream(InputStream s) throws IOException { aoqi@0: final List booleanList = new ArrayList(); aoqi@0: aoqi@0: int value = s.read(); aoqi@0: if (value == -1) { aoqi@0: throw new EOFException(); aoqi@0: } aoqi@0: final int unusedBits = (value >> 4) & 0xFF; aoqi@0: aoqi@0: int bitPosition = 4; aoqi@0: int bitPositionEnd = 8; aoqi@0: int valueNext = 0; aoqi@0: do { aoqi@0: valueNext = s.read(); aoqi@0: if (valueNext == -1) { aoqi@0: bitPositionEnd -= unusedBits; aoqi@0: } aoqi@0: aoqi@0: while(bitPosition < bitPositionEnd) { aoqi@0: booleanList.add( aoqi@0: Boolean.valueOf((value & BIT_TABLE[bitPosition++]) > 0)); aoqi@0: } aoqi@0: aoqi@0: value = valueNext; aoqi@0: } while (value != -1); aoqi@0: aoqi@0: return generateArrayFromList(booleanList); aoqi@0: } aoqi@0: aoqi@0: public void encodeToOutputStream(Object data, OutputStream s) throws IOException { aoqi@0: if (!(data instanceof boolean[])) { aoqi@0: throw new IllegalArgumentException(CommonResourceBundle.getInstance().getString("message.dataNotBoolean")); aoqi@0: } aoqi@0: aoqi@0: boolean array[] = (boolean[])data; aoqi@0: final int alength = array.length; aoqi@0: aoqi@0: final int mod = (alength + 4) % 8; aoqi@0: final int unusedBits = (mod == 0) ? 0 : 8 - mod; aoqi@0: aoqi@0: int bitPosition = 4; aoqi@0: int value = unusedBits << 4; aoqi@0: int astart = 0; aoqi@0: while (astart < alength) { aoqi@0: if (array[astart++]) { aoqi@0: value |= BIT_TABLE[bitPosition]; aoqi@0: } aoqi@0: aoqi@0: if (++bitPosition == 8) { aoqi@0: s.write(value); aoqi@0: bitPosition = value = 0; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (bitPosition != 8) { aoqi@0: s.write(value); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final Object convertFromCharacters(char[] ch, int start, int length) { aoqi@0: if (length == 0) { aoqi@0: return new boolean[0]; aoqi@0: } aoqi@0: aoqi@0: final CharBuffer cb = CharBuffer.wrap(ch, start, length); aoqi@0: final List booleanList = new ArrayList(); aoqi@0: aoqi@0: matchWhiteSpaceDelimnatedWords(cb, aoqi@0: new WordListener() { aoqi@0: public void word(int start, int end) { aoqi@0: if (cb.charAt(start) == 't') { aoqi@0: booleanList.add(Boolean.TRUE); aoqi@0: } else { aoqi@0: booleanList.add(Boolean.FALSE); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: ); aoqi@0: aoqi@0: return generateArrayFromList(booleanList); aoqi@0: } aoqi@0: aoqi@0: public final void convertToCharacters(Object data, StringBuffer s) { aoqi@0: if (data == null) { aoqi@0: return; aoqi@0: } aoqi@0: aoqi@0: final boolean[] value = (boolean[]) data; aoqi@0: if (value.length == 0) { aoqi@0: return; aoqi@0: } aoqi@0: aoqi@0: // Insure conservately as all false aoqi@0: s.ensureCapacity(value.length * 5); aoqi@0: aoqi@0: final int end = value.length - 1; aoqi@0: for (int i = 0; i <= end; i++) { aoqi@0: if (value[i]) { aoqi@0: s.append("true"); aoqi@0: } else { aoqi@0: s.append("false"); aoqi@0: } aoqi@0: if (i != end) { aoqi@0: s.append(' '); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public int getPrimtiveLengthFromOctetLength(int octetLength, int firstOctet) throws EncodingAlgorithmException { aoqi@0: final int unusedBits = (firstOctet >> 4) & 0xFF; aoqi@0: if (octetLength == 1) { aoqi@0: if (unusedBits > 3) { aoqi@0: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.unusedBits4")); aoqi@0: } aoqi@0: return 4 - unusedBits; aoqi@0: } else { aoqi@0: if (unusedBits > 7) { aoqi@0: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.unusedBits8")); aoqi@0: } aoqi@0: return octetLength * 8 - 4 - unusedBits; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final void decodeFromBytesToBooleanArray(boolean[] bdata, int bstart, int blength, byte[] b, int start, int length) { aoqi@0: int value = b[start++] & 0xFF; aoqi@0: int bitPosition = 4; aoqi@0: final int bend = bstart + blength; aoqi@0: while (bstart < bend) { aoqi@0: if (bitPosition == 8) { aoqi@0: value = b[start++] & 0xFF; aoqi@0: bitPosition = 0; aoqi@0: } aoqi@0: aoqi@0: bdata[bstart++] = (value & BIT_TABLE[bitPosition++]) > 0; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public void encodeToBytes(Object array, int astart, int alength, byte[] b, int start) { aoqi@0: if (!(array instanceof boolean[])) { aoqi@0: throw new IllegalArgumentException(CommonResourceBundle.getInstance().getString("message.dataNotBoolean")); aoqi@0: } aoqi@0: aoqi@0: encodeToBytesFromBooleanArray((boolean[])array, astart, alength, b, start); aoqi@0: } aoqi@0: aoqi@0: public void encodeToBytesFromBooleanArray(boolean[] array, int astart, int alength, byte[] b, int start) { aoqi@0: final int mod = (alength + 4) % 8; aoqi@0: final int unusedBits = (mod == 0) ? 0 : 8 - mod; aoqi@0: aoqi@0: int bitPosition = 4; aoqi@0: int value = unusedBits << 4; aoqi@0: final int aend = astart + alength; aoqi@0: while (astart < aend) { aoqi@0: if (array[astart++]) { aoqi@0: value |= BIT_TABLE[bitPosition]; aoqi@0: } aoqi@0: aoqi@0: if (++bitPosition == 8) { aoqi@0: b[start++] = (byte)value; aoqi@0: bitPosition = value = 0; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (bitPosition > 0) { aoqi@0: b[start] = (byte)value; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * aoqi@0: * Generate a boolean array from a list of Booleans. aoqi@0: * aoqi@0: * @param array The array aoqi@0: * aoqi@0: */ aoqi@0: private boolean[] generateArrayFromList(List array) { aoqi@0: boolean[] bdata = new boolean[array.size()]; aoqi@0: for (int i = 0; i < bdata.length; i++) { aoqi@0: bdata[i] = ((Boolean)array.get(i)).booleanValue(); aoqi@0: } aoqi@0: aoqi@0: return bdata; aoqi@0: } aoqi@0: aoqi@0: }