001: /*
002: * Fast Infoset ver. 0.1 software ("Software")
003: *
004: * Copyright, 2004-2005 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * Software is licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License. You may
008: * obtain a copy of the License at:
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015: * License for the specific language governing permissions and limitations.
016: *
017: * Sun supports and benefits from the global community of open source
018: * developers, and thanks the community for its important contributions and
019: * open standards-based technology, which Sun has adopted into many of its
020: * products.
021: *
022: * Please note that portions of Software may be provided with notices and
023: * open source licenses from such communities and third parties that govern the
024: * use of those portions, and any licenses granted hereunder do not alter any
025: * rights and obligations you may have under such open source licenses,
026: * however, the disclaimer of warranty and limitation of liability provisions
027: * in this License will apply to all Software in this distribution.
028: *
029: * You acknowledge that the Software is not designed, licensed or intended
030: * for use in the design, construction, operation or maintenance of any nuclear
031: * facility.
032: *
033: * Apache License
034: * Version 2.0, January 2004
035: * http://www.apache.org/licenses/
036: *
037: */
038:
039: package com.sun.xml.fastinfoset.algorithm;
040:
041: import java.io.EOFException;
042: import java.io.IOException;
043: import java.io.InputStream;
044: import java.io.OutputStream;
045: import java.nio.CharBuffer;
046: import java.util.ArrayList;
047: import java.util.List;
048:
049: import org.jvnet.fastinfoset.EncodingAlgorithmException;
050: import com.sun.xml.fastinfoset.CommonResourceBundle;
051:
052: /**
053: *
054: * An encoder for handling boolean values. Suppports the builtin BOOLEAN encoder.
055: *
056: * @author Alan Hudson
057: * @author Paul Sandoz
058: *
059: */
060: public class BooleanEncodingAlgorithm extends BuiltInEncodingAlgorithm {
061:
062: /** Table for setting a particular bit of a byte */
063: private static final int[] BIT_TABLE = { 1 << 7, 1 << 6, 1 << 5,
064: 1 << 4, 1 << 3, 1 << 2, 1 << 1, 1 << 0 };
065:
066: public int getPrimtiveLengthFromOctetLength(int octetLength)
067: throws EncodingAlgorithmException {
068: // Cannot determine the number of boolean values from just the octet length
069: throw new UnsupportedOperationException();
070: }
071:
072: public int getOctetLengthFromPrimitiveLength(int primitiveLength) {
073: if (primitiveLength < 5) {
074: return 1;
075: } else {
076: final int div = primitiveLength / 8;
077: return (div == 0) ? 2 : 1 + div;
078: }
079: }
080:
081: public final Object decodeFromBytes(byte[] b, int start, int length)
082: throws EncodingAlgorithmException {
083: final int blength = getPrimtiveLengthFromOctetLength(length,
084: b[start]);
085: boolean[] data = new boolean[blength];
086:
087: decodeFromBytesToBooleanArray(data, 0, blength, b, start,
088: length);
089: return data;
090: }
091:
092: public final Object decodeFromInputStream(InputStream s)
093: throws IOException {
094: final List booleanList = new ArrayList();
095:
096: int value = s.read();
097: if (value == -1) {
098: throw new EOFException();
099: }
100: final int unusedBits = (value >> 4) & 0xFF;
101:
102: int bitPosition = 4;
103: int bitPositionEnd = 8;
104: int valueNext = 0;
105: do {
106: valueNext = s.read();
107: if (valueNext == -1) {
108: bitPositionEnd -= unusedBits;
109: }
110:
111: while (bitPosition < bitPositionEnd) {
112: booleanList
113: .add(Boolean
114: .valueOf((value & BIT_TABLE[bitPosition++]) > 0));
115: }
116:
117: value = valueNext;
118: } while (value != -1);
119:
120: return generateArrayFromList(booleanList);
121: }
122:
123: public void encodeToOutputStream(Object data, OutputStream s)
124: throws IOException {
125: if (!(data instanceof boolean[])) {
126: throw new IllegalArgumentException(CommonResourceBundle
127: .getInstance().getString("message.dataNotBoolean"));
128: }
129:
130: boolean array[] = (boolean[]) data;
131: final int alength = array.length;
132:
133: final int mod = (alength + 4) % 8;
134: final int unusedBits = (mod == 0) ? 0 : 8 - mod;
135:
136: int bitPosition = 4;
137: int value = unusedBits << 4;
138: int astart = 0;
139: while (astart < alength) {
140: if (array[astart++]) {
141: value |= BIT_TABLE[bitPosition];
142: }
143:
144: if (++bitPosition == 8) {
145: s.write(value);
146: bitPosition = value = 0;
147: }
148: }
149:
150: if (bitPosition != 8) {
151: s.write(value);
152: }
153: }
154:
155: public final Object convertFromCharacters(char[] ch, int start,
156: int length) {
157: if (length == 0) {
158: return new boolean[0];
159: }
160:
161: final CharBuffer cb = CharBuffer.wrap(ch, start, length);
162: final List booleanList = new ArrayList();
163:
164: matchWhiteSpaceDelimnatedWords(cb, new WordListener() {
165: public void word(int start, int end) {
166: if (cb.charAt(start) == 't') {
167: booleanList.add(Boolean.TRUE);
168: } else {
169: booleanList.add(Boolean.FALSE);
170: }
171: }
172: });
173:
174: return generateArrayFromList(booleanList);
175: }
176:
177: public final void convertToCharacters(Object data, StringBuffer s) {
178: if (data == null) {
179: return;
180: }
181:
182: final boolean[] value = (boolean[]) data;
183: if (value.length == 0) {
184: return;
185: }
186:
187: // Insure conservately as all false
188: s.ensureCapacity(value.length * 5);
189:
190: final int end = value.length - 1;
191: for (int i = 0; i <= end; i++) {
192: if (value[i]) {
193: s.append("true");
194: } else {
195: s.append("false");
196: }
197: if (i != end) {
198: s.append(' ');
199: }
200: }
201: }
202:
203: public int getPrimtiveLengthFromOctetLength(int octetLength,
204: int firstOctet) throws EncodingAlgorithmException {
205: final int unusedBits = (firstOctet >> 4) & 0xFF;
206: if (octetLength == 1) {
207: if (unusedBits > 3) {
208: throw new EncodingAlgorithmException(
209: CommonResourceBundle.getInstance().getString(
210: "message.unusedBits4"));
211: }
212: return 4 - unusedBits;
213: } else {
214: if (unusedBits > 7) {
215: throw new EncodingAlgorithmException(
216: CommonResourceBundle.getInstance().getString(
217: "message.unusedBits8"));
218: }
219: return octetLength * 8 - 4 - unusedBits;
220: }
221: }
222:
223: public final void decodeFromBytesToBooleanArray(boolean[] bdata,
224: int bstart, int blength, byte[] b, int start, int length) {
225: int value = b[start++] & 0xFF;
226: int bitPosition = 4;
227: final int bend = bstart + blength;
228: while (bstart < bend) {
229: if (bitPosition == 8) {
230: value = b[start++] & 0xFF;
231: bitPosition = 0;
232: }
233:
234: bdata[bstart++] = (value & BIT_TABLE[bitPosition++]) > 0;
235: }
236: }
237:
238: public void encodeToBytes(Object array, int astart, int alength,
239: byte[] b, int start) {
240: if (!(array instanceof boolean[])) {
241: throw new IllegalArgumentException(CommonResourceBundle
242: .getInstance().getString("message.dataNotBoolean"));
243: }
244:
245: encodeToBytesFromBooleanArray((boolean[]) array, astart,
246: alength, b, start);
247: }
248:
249: public void encodeToBytesFromBooleanArray(boolean[] array,
250: int astart, int alength, byte[] b, int start) {
251: final int mod = (alength + 4) % 8;
252: final int unusedBits = (mod == 0) ? 0 : 8 - mod;
253:
254: int bitPosition = 4;
255: int value = unusedBits << 4;
256: final int aend = astart + alength;
257: while (astart < aend) {
258: if (array[astart++]) {
259: value |= BIT_TABLE[bitPosition];
260: }
261:
262: if (++bitPosition == 8) {
263: b[start++] = (byte) value;
264: bitPosition = value = 0;
265: }
266: }
267:
268: if (bitPosition > 0) {
269: b[start] = (byte) value;
270: }
271: }
272:
273: /**
274: *
275: * Generate a boolean array from a list of Booleans.
276: *
277: * @param array The array
278: *
279: */
280: private final boolean[] generateArrayFromList(List array) {
281: boolean[] bdata = new boolean[array.size()];
282: for (int i = 0; i < bdata.length; i++) {
283: bdata[i] = ((Boolean) array.get(i)).booleanValue();
284: }
285:
286: return bdata;
287: }
288:
289: }
|