1/*
2 * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 *
25 * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC.
26 */
27
28package com.sun.xml.internal.fastinfoset.algorithm;
29
30import java.io.EOFException;
31import java.io.IOException;
32import java.io.InputStream;
33import java.io.OutputStream;
34import java.nio.CharBuffer;
35import java.util.ArrayList;
36import java.util.List;
37import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmException;
38import com.sun.xml.internal.fastinfoset.CommonResourceBundle;
39
40
41
42public class DoubleEncodingAlgorithm extends IEEE754FloatingPointEncodingAlgorithm {
43
44    public final int getPrimtiveLengthFromOctetLength(int octetLength) throws EncodingAlgorithmException {
45        if (octetLength % DOUBLE_SIZE != 0) {
46            throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().
47                    getString("message.lengthIsNotMultipleOfDouble", new Object[]{Integer.valueOf(DOUBLE_SIZE)}));
48        }
49
50        return octetLength / DOUBLE_SIZE;
51    }
52
53    public int getOctetLengthFromPrimitiveLength(int primitiveLength) {
54        return primitiveLength * DOUBLE_SIZE;
55    }
56
57    public final Object decodeFromBytes(byte[] b, int start, int length) throws EncodingAlgorithmException {
58        double[] data = new double[getPrimtiveLengthFromOctetLength(length)];
59        decodeFromBytesToDoubleArray(data, 0, b, start, length);
60
61        return data;
62    }
63
64    public final Object decodeFromInputStream(InputStream s) throws IOException {
65        return decodeFromInputStreamToDoubleArray(s);
66    }
67
68
69    public void encodeToOutputStream(Object data, OutputStream s) throws IOException {
70        if (!(data instanceof double[])) {
71            throw new IllegalArgumentException(CommonResourceBundle.getInstance().getString("message.dataNotDouble"));
72        }
73
74        final double[] fdata = (double[])data;
75
76        encodeToOutputStreamFromDoubleArray(fdata, s);
77    }
78
79    public final Object convertFromCharacters(char[] ch, int start, int length) {
80        final CharBuffer cb = CharBuffer.wrap(ch, start, length);
81        final List doubleList = new ArrayList();
82
83        matchWhiteSpaceDelimnatedWords(cb,
84                new WordListener() {
85            public void word(int start, int end) {
86                String fStringValue = cb.subSequence(start, end).toString();
87                doubleList.add(Double.valueOf(fStringValue));
88            }
89        }
90        );
91
92        return generateArrayFromList(doubleList);
93    }
94
95    public final void convertToCharacters(Object data, StringBuffer s) {
96        if (!(data instanceof double[])) {
97            throw new IllegalArgumentException(CommonResourceBundle.getInstance().getString("message.dataNotDouble"));
98        }
99
100        final double[] fdata = (double[])data;
101
102        convertToCharactersFromDoubleArray(fdata, s);
103    }
104
105
106    public final void decodeFromBytesToDoubleArray(double[] data, int fstart, byte[] b, int start, int length) {
107        final int size = length / DOUBLE_SIZE;
108        for (int i = 0; i < size; i++) {
109            final long bits =
110                    ((long)(b[start++] & 0xFF) << 56) |
111                    ((long)(b[start++] & 0xFF) << 48) |
112                    ((long)(b[start++] & 0xFF) << 40) |
113                    ((long)(b[start++] & 0xFF) << 32) |
114                    ((long)(b[start++] & 0xFF) << 24) |
115                    ((long)(b[start++] & 0xFF) << 16) |
116                    ((long)(b[start++] & 0xFF) << 8) |
117                    (long)(b[start++] & 0xFF);
118            data[fstart++] = Double.longBitsToDouble(bits);
119        }
120    }
121
122    public final double[] decodeFromInputStreamToDoubleArray(InputStream s) throws IOException {
123        final List doubleList = new ArrayList();
124        final byte[] b = new byte[DOUBLE_SIZE];
125
126        while (true) {
127            int n = s.read(b);
128            if (n != DOUBLE_SIZE) {
129                if (n == -1) {
130                    break;
131                }
132
133                while(n != DOUBLE_SIZE) {
134                    final int m = s.read(b, n, DOUBLE_SIZE - n);
135                    if (m == -1) {
136                        throw new EOFException();
137                    }
138                    n += m;
139                }
140            }
141
142            final long bits =
143                    ((long)(b[0] & 0xFF) << 56) |
144                    ((long)(b[1] & 0xFF) << 48) |
145                    ((long)(b[2] & 0xFF) << 40) |
146                    ((long)(b[3] & 0xFF) << 32) |
147                    ((b[4] & 0xFF) << 24) |
148                    ((b[5] & 0xFF) << 16) |
149                    ((b[6] & 0xFF) << 8) |
150                    (b[7] & 0xFF);
151
152            doubleList.add(Double.valueOf(Double.longBitsToDouble(bits)));
153        }
154
155        return generateArrayFromList(doubleList);
156    }
157
158
159    public final void encodeToOutputStreamFromDoubleArray(double[] fdata, OutputStream s) throws IOException {
160        for (int i = 0; i < fdata.length; i++) {
161            final long bits = Double.doubleToLongBits(fdata[i]);
162            s.write((int)((bits >>> 56) & 0xFF));
163            s.write((int)((bits >>> 48) & 0xFF));
164            s.write((int)((bits >>> 40) & 0xFF));
165            s.write((int)((bits >>> 32) & 0xFF));
166            s.write((int)((bits >>> 24) & 0xFF));
167            s.write((int)((bits >>> 16) & 0xFF));
168            s.write((int)((bits >>>  8) & 0xFF));
169            s.write((int)(bits & 0xFF));
170        }
171    }
172
173    public final void encodeToBytes(Object array, int astart, int alength, byte[] b, int start) {
174        encodeToBytesFromDoubleArray((double[])array, astart, alength, b, start);
175    }
176
177    public final void encodeToBytesFromDoubleArray(double[] fdata, int fstart, int flength, byte[] b, int start) {
178        final int fend = fstart + flength;
179        for (int i = fstart; i < fend; i++) {
180            final long bits = Double.doubleToLongBits(fdata[i]);
181            b[start++] = (byte)((bits >>> 56) & 0xFF);
182            b[start++] = (byte)((bits >>> 48) & 0xFF);
183            b[start++] = (byte)((bits >>> 40) & 0xFF);
184            b[start++] = (byte)((bits >>> 32) & 0xFF);
185            b[start++] = (byte)((bits >>> 24) & 0xFF);
186            b[start++] = (byte)((bits >>> 16) & 0xFF);
187            b[start++] = (byte)((bits >>>  8) & 0xFF);
188            b[start++] = (byte)(bits & 0xFF);
189        }
190    }
191
192
193    public final void convertToCharactersFromDoubleArray(double[] fdata, StringBuffer s) {
194        final int end = fdata.length - 1;
195        for (int i = 0; i <= end; i++) {
196            s.append(Double.toString(fdata[i]));
197            if (i != end) {
198                s.append(' ');
199            }
200        }
201    }
202
203
204    public final double[] generateArrayFromList(List array) {
205        double[] fdata = new double[array.size()];
206        for (int i = 0; i < fdata.length; i++) {
207            fdata[i] = ((Double)array.get(i)).doubleValue();
208        }
209
210        return fdata;
211    }
212
213}
214