001/* ***** BEGIN LICENSE BLOCK *****
002 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
003 *
004 * The contents of this file are subject to the Mozilla Public License Version
005 * 1.1 (the "License"); you may not use this file except in compliance with
006 * the License. You may obtain a copy of the License at
007 * http://www.mozilla.org/MPL/
008 *
009 * Software distributed under the License is distributed on an "AS IS" basis,
010 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011 * for the specific language governing rights and limitations under the
012 * License.
013 *
014 * The Original Code is part of dcm4che, an implementation of DICOM(TM) in
015 * Java(TM), hosted at https://github.com/gunterze/dcm4che.
016 *
017 * The Initial Developer of the Original Code is
018 * Agfa Healthcare.
019 * Portions created by the Initial Developer are Copyright (C) 2011
020 * the Initial Developer. All Rights Reserved.
021 *
022 * Contributor(s):
023 * See @authors listed below
024 *
025 * Alternatively, the contents of this file may be used under the terms of
026 * either the GNU General Public License Version 2 or later (the "GPL"), or
027 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
028 * in which case the provisions of the GPL or the LGPL are applicable instead
029 * of those above. If you wish to allow use of your version of this file only
030 * under the terms of either the GPL or the LGPL, and not to allow others to
031 * use your version of this file under the terms of the MPL, indicate your
032 * decision by deleting the provisions above and replace them with the notice
033 * and other provisions required by the GPL or the LGPL. If you do not delete
034 * the provisions above, a recipient may use your version of this file under
035 * the terms of any one of the MPL, the GPL or the LGPL.
036 *
037 * ***** END LICENSE BLOCK ***** */
038
039package org.dcm4che3.util;
040
041/**
042 * @author Gunter Zeilinger <gunterze@gmail.com>
043 */
044public class ByteUtils {
045
046    public static final byte[] EMPTY_BYTES = {};
047    public static final int[] EMPTY_INTS = {};
048    public static final float[] EMPTY_FLOATS = {};
049    public static final double[] EMPTY_DOUBLES = {};
050
051    public static int bytesToVR(byte[] bytes, int off) {
052        return bytesToUShortBE(bytes, off);
053    }
054
055    public static int bytesToUShort(byte[] bytes, int off, boolean bigEndian) {
056        return bigEndian ? bytesToUShortBE(bytes, off)
057                         : bytesToUShortLE(bytes, off);
058    }
059
060    public static int bytesToUShortBE(byte[] bytes, int off) {
061        return ((bytes[off] & 255) << 8) + (bytes[off + 1] & 255);
062    }
063
064    public static int bytesToUShortLE(byte[] bytes, int off) {
065        return ((bytes[off + 1] & 255) << 8) + (bytes[off] & 255);
066    }
067
068    public static int bytesToShort(byte[] bytes, int off, boolean bigEndian) {
069        return bigEndian ? bytesToShortBE(bytes, off)
070                         : bytesToShortLE(bytes, off);
071    }
072
073    public static int bytesToShortBE(byte[] bytes, int off) {
074        return (bytes[off] << 8) + (bytes[off + 1] & 255);
075    }
076
077    public static int bytesToShortLE(byte[] bytes, int off) {
078        return (bytes[off + 1] << 8)  + (bytes[off] & 255);
079    }
080
081    public static void bytesToShorts(byte[] src, int srcPos, short[] dest, int destPos, int length, boolean bigEndian) {
082        if (bigEndian)
083            bytesToShortsBE(src, srcPos, dest, destPos, length);
084        else
085            bytesToShortsLE(src, srcPos, dest, destPos, length);
086    }
087
088    public static void bytesToShortsBE(byte[] src, int srcPos, short[] dest, int destPos, int length) {
089        for (int i = 0; i < length; i++)
090            dest[destPos+i] = (short) bytesToShortBE(src, srcPos + (i << 1));
091    }
092
093    public static void bytesToShortsLE(byte[] src, int srcPos, short[] dest, int destPos, int length) {
094        for (int i = 0; i < length; i++)
095            dest[destPos+i] = (short) bytesToShortLE(src, srcPos+(i<<1));
096    }
097
098    public static int bytesToInt(byte[] bytes, int off, boolean bigEndian) {
099        return bigEndian ? bytesToIntBE(bytes, off) : bytesToIntLE(bytes, off);
100    }
101
102    public static int bytesToIntBE(byte[] bytes, int off) {
103        return (bytes[off] << 24) + ((bytes[off + 1] & 255) << 16)
104                + ((bytes[off + 2] & 255) << 8) + (bytes[off + 3] & 255);
105    }
106
107    public static int bytesToIntLE(byte[] bytes, int off) {
108        return (bytes[off + 3] << 24) + ((bytes[off + 2] & 255) << 16)
109                + ((bytes[off + 1] & 255) << 8) + (bytes[off] & 255);
110    }
111
112    public static int bytesToTag(byte[] bytes, int off, boolean bigEndian) {
113        return bigEndian ? bytesToTagBE(bytes, off) : bytesToTagLE(bytes, off);
114    }
115
116    public static int bytesToTagBE(byte[] bytes, int off) {
117        return bytesToIntBE(bytes, off);
118    }
119
120    public static int bytesToTagLE(byte[] bytes, int off) {
121        return (bytes[off + 1] << 24) + ((bytes[off] & 255) << 16)
122                + ((bytes[off + 3] & 255) << 8) + (bytes[off + 2] & 255);
123    }
124
125    public static float bytesToFloat(byte[] bytes, int off, boolean bigEndian) {
126        return bigEndian ? bytesToFloatBE(bytes, off)
127                         : bytesToFloatLE(bytes, off);
128    }
129
130    public static float bytesToFloatBE(byte[] bytes, int off) {
131        return Float.intBitsToFloat(bytesToIntBE(bytes, off));
132    }
133
134    public static float bytesToFloatLE(byte[] bytes, int off) {
135        return Float.intBitsToFloat(bytesToIntLE(bytes, off));
136    }
137
138    public static long bytesToLong(byte[] bytes, int off, boolean bigEndian) {
139        return bigEndian ? bytesToLongBE(bytes, off)
140                         : bytesToLongLE(bytes, off);
141    }
142
143    public static long bytesToLongBE(byte[] bytes, int off) {
144        return ((long) bytes[off] << 56)
145                + ((long) (bytes[off + 1] & 255) << 48)
146                + ((long) (bytes[off + 2] & 255) << 40)
147                + ((long) (bytes[off + 3] & 255) << 32)
148                + ((long) (bytes[off + 4] & 255) << 24)
149                + ((bytes[off + 5] & 255) << 16)
150                + ((bytes[off + 6] & 255) << 8)
151                + (bytes[off + 7] & 255);
152     }
153
154    public static long bytesToLongLE(byte[] bytes, int off) {
155        return ((long) bytes[off + 7] << 56)
156                + ((long) (bytes[off + 6] & 255) << 48)
157                + ((long) (bytes[off + 5] & 255) << 40)
158                + ((long) (bytes[off + 4] & 255) << 32)
159                + ((long) (bytes[off + 3] & 255) << 24)
160                + ((bytes[off + 2] & 255) << 16)
161                + ((bytes[off + 1] & 255) << 8)
162                + (bytes[off] & 255);
163    }
164
165    public static double bytesToDouble(byte[] bytes, int off, boolean bigEndian) {
166        return bigEndian ? bytesToDoubleBE(bytes, off)
167                         : bytesToDoubleLE(bytes, off);
168    }
169
170    public static double bytesToDoubleBE(byte[] bytes, int off) {
171        return Double.longBitsToDouble(bytesToLongBE(bytes, off));
172    }
173
174    public static double bytesToDoubleLE(byte[] bytes, int off) {
175        return Double.longBitsToDouble(bytesToLongLE(bytes, off));
176    }
177
178    public static byte[] shortToBytes(int i, byte[] bytes, int off,
179            boolean bigEndian) {
180        return bigEndian ? shortToBytesBE(i, bytes, off)
181                         : shortToBytesLE(i, bytes, off);
182    }
183
184    public static byte[] shortToBytesBE(int i, byte[] bytes, int off) {
185        bytes[off] = (byte) (i >> 8);
186        bytes[off + 1] = (byte) i;
187        return bytes;
188    }
189
190    public static byte[] shortToBytesLE(int i, byte[] bytes, int off) {
191        bytes[off + 1] = (byte) (i >> 8);
192        bytes[off] = (byte) i;
193        return bytes;
194    }
195
196    public static byte[] intToBytes(int i, byte[] bytes, int off,
197            boolean bigEndian) {
198        return bigEndian ? intToBytesBE(i, bytes, off)
199                         : intToBytesLE(i, bytes, off);
200    }
201
202    public static byte[] intToBytesBE(int i, byte[] bytes, int off) {
203        bytes[off] = (byte) (i >> 24);
204        bytes[off + 1] = (byte) (i >> 16);
205        bytes[off + 2] = (byte) (i >> 8);
206        bytes[off + 3] = (byte) i;
207        return bytes;
208    }
209
210    public static byte[] intToBytesLE(int i, byte[] bytes, int off) {
211        bytes[off + 3] = (byte) (i >> 24);
212        bytes[off + 2] = (byte) (i >> 16);
213        bytes[off + 1] = (byte) (i >> 8);
214        bytes[off] = (byte) i;
215        return bytes;
216    }
217
218    public static byte[] tagToBytes(int i, byte[] bytes, int off,
219            boolean bigEndian) {
220        return bigEndian ? tagToBytesBE(i, bytes, off)
221                         : tagToBytesLE(i, bytes, off);
222    }
223
224    public static byte[] tagToBytesBE(int i, byte[] bytes, int off) {
225        return intToBytesBE(i, bytes, off);
226    }
227
228    public static byte[] tagToBytesLE(int i, byte[] bytes, int off) {
229        bytes[off + 1] = (byte) (i >> 24);
230        bytes[off] = (byte) (i >> 16);
231        bytes[off + 3] = (byte) (i >> 8);
232        bytes[off + 2] = (byte) i;
233        return bytes;
234    }
235
236    public static byte[] floatToBytes(float f, byte[] bytes, int off,
237            boolean bigEndian) {
238        return bigEndian ? floatToBytesBE(f, bytes, off)
239                         : floatToBytesLE(f, bytes, off);
240    }
241
242   public static byte[] floatToBytesBE(float f, byte[] bytes, int off) {
243        return intToBytesBE(Float.floatToIntBits(f), bytes, off);
244    }
245
246    public static byte[] floatToBytesLE(float f, byte[] bytes, int off) {
247        return intToBytesLE(Float.floatToIntBits(f), bytes, off);
248    }
249
250    public static byte[] doubleToBytes(double d, byte[] bytes, int off,
251            boolean bigEndian) {
252        return bigEndian ? doubleToBytesBE(d, bytes, off)
253                         : doubleToBytesLE(d, bytes, off);
254    }
255
256    public static byte[] doubleToBytesBE(double d, byte[] bytes, int off) {
257        return longToBytesBE(Double.doubleToLongBits(d), bytes, off);
258    }
259
260    public static byte[] doubleToBytesLE(double d, byte[] bytes, int off) {
261        return longToBytesLE(Double.doubleToLongBits(d), bytes, off);
262    }
263
264    public static byte[] longToBytes(long l, byte[] bytes, int off,
265            boolean bigEndian) {
266        return bigEndian ? longToBytesBE(l, bytes, off)
267                         : longToBytesLE(l, bytes, off);
268    }
269
270    public static byte[] longToBytesBE(long l, byte[] bytes, int off) {
271        bytes[off] = (byte) (l >> 56);
272        bytes[off + 1] = (byte) (l >> 48);
273        bytes[off + 2] = (byte) (l >> 40);
274        bytes[off + 3] = (byte) (l >> 32);
275        bytes[off + 4] = (byte) (l >> 24);
276        bytes[off + 5] = (byte) (l >> 16);
277        bytes[off + 6] = (byte) (l >> 8);
278        bytes[off + 7] = (byte) l;
279        return bytes;
280    }
281
282    public static byte[] longToBytesLE(long l, byte[] bytes, int off) {
283        bytes[off + 7] = (byte) (l >> 56);
284        bytes[off + 6] = (byte) (l >> 48);
285        bytes[off + 5] = (byte) (l >> 40);
286        bytes[off + 4] = (byte) (l >> 32);
287        bytes[off + 3] = (byte) (l >> 24);
288        bytes[off + 2] = (byte) (l >> 16);
289        bytes[off + 1] = (byte) (l >> 8);
290        bytes[off] = (byte) l;
291        return bytes;
292    }
293
294    public static byte[][] swapShorts(byte bs[][]) {
295        int carry =  0;
296        for (int i = 0; i < bs.length; i++) {
297            byte[] b = bs[i];
298            if (carry != 0)
299                swapLastFirst(bs[i-1], b);
300            int len = b.length - carry;
301            swapShorts(b, carry, len & ~1);
302            carry = len & 1;
303         }
304        return bs;
305    }
306
307    public static byte[] swapShorts(byte b[], int off, int len) {
308        checkLength(len, 2);
309        for (int i = off, n = off + len; i < n; i += 2)
310            swap(b, i, i+1);
311        return b;
312    }
313
314    public static byte[] swapInts(byte b[], int off, int len) {
315        checkLength(len, 4);
316        for (int i = off, n = off + len; i < n; i += 4) {
317            swap(b, i, i+3);
318            swap(b, i+1, i+2);
319        }
320        return b;
321    }
322
323    public static byte[] swapLongs(byte b[], int off, int len) {
324        checkLength(len, 8);
325        for (int i = off, n = off + len; i < n; i += 8) {
326            swap(b, i, i+7);
327            swap(b, i+1, i+6);
328            swap(b, i+2, i+5);
329            swap(b, i+3, i+4);
330        }
331        return b;
332    }
333
334    private static void checkLength(int len, int numBytes) {
335        if (len < 0 || (len % numBytes) != 0)
336            throw new IllegalArgumentException("length: " + len);
337    }
338
339    private static void swap(byte[] bytes, int a, int b) {
340        byte t = bytes[a];
341        bytes[a] = bytes[b];
342        bytes[b] = t;
343    }
344
345    private static void swapLastFirst(byte[] b1, byte[] b2) {
346        int last = b1.length - 1;
347        byte t = b2[0];
348        b2[0] = b1[last];
349        b1[last] = t;
350    }
351
352}