• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.apache.commons.io;
18 
19 import java.io.EOFException;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 
24 /**
25  * Utility code for dealing with different endian systems.
26  * <p>
27  * Different computer architectures adopt different conventions for
28  * byte ordering. In so-called "Little Endian" architectures (eg Intel),
29  * the low-order byte is stored in memory at the lowest address, and
30  * subsequent bytes at higher addresses. For "Big Endian" architectures
31  * (eg Motorola), the situation is reversed.
32  * This class helps you solve this incompatability.
33  * <p>
34  * Origin of code: Excalibur
35  *
36  * @author <a href="mailto:peter@apache.org">Peter Donald</a>
37  * @version $Id: EndianUtils.java 539632 2007-05-18 23:37:59Z bayard $
38  * @see org.apache.commons.io.input.SwappedDataInputStream
39  */
40 public class EndianUtils {
41 
42     /**
43      * Instances should NOT be constructed in standard programming.
44      */
EndianUtils()45     public EndianUtils() {
46         super();
47     }
48 
49     // ========================================== Swapping routines
50 
51     /**
52      * Converts a "short" value between endian systems.
53      * @param value value to convert
54      * @return the converted value
55      */
swapShort(short value)56     public static short swapShort(short value) {
57         return (short) ( ( ( ( value >> 0 ) & 0xff ) << 8 ) +
58             ( ( ( value >> 8 ) & 0xff ) << 0 ) );
59     }
60 
61     /**
62      * Converts a "int" value between endian systems.
63      * @param value value to convert
64      * @return the converted value
65      */
swapInteger(int value)66     public static int swapInteger(int value) {
67         return
68             ( ( ( value >> 0 ) & 0xff ) << 24 ) +
69             ( ( ( value >> 8 ) & 0xff ) << 16 ) +
70             ( ( ( value >> 16 ) & 0xff ) << 8 ) +
71             ( ( ( value >> 24 ) & 0xff ) << 0 );
72     }
73 
74     /**
75      * Converts a "long" value between endian systems.
76      * @param value value to convert
77      * @return the converted value
78      */
swapLong(long value)79     public static long swapLong(long value) {
80         return
81             ( ( ( value >> 0 ) & 0xff ) << 56 ) +
82             ( ( ( value >> 8 ) & 0xff ) << 48 ) +
83             ( ( ( value >> 16 ) & 0xff ) << 40 ) +
84             ( ( ( value >> 24 ) & 0xff ) << 32 ) +
85             ( ( ( value >> 32 ) & 0xff ) << 24 ) +
86             ( ( ( value >> 40 ) & 0xff ) << 16 ) +
87             ( ( ( value >> 48 ) & 0xff ) << 8 ) +
88             ( ( ( value >> 56 ) & 0xff ) << 0 );
89     }
90 
91     /**
92      * Converts a "float" value between endian systems.
93      * @param value value to convert
94      * @return the converted value
95      */
swapFloat(float value)96     public static float swapFloat(float value) {
97         return Float.intBitsToFloat( swapInteger( Float.floatToIntBits( value ) ) );
98     }
99 
100     /**
101      * Converts a "double" value between endian systems.
102      * @param value value to convert
103      * @return the converted value
104      */
swapDouble(double value)105     public static double swapDouble(double value) {
106         return Double.longBitsToDouble( swapLong( Double.doubleToLongBits( value ) ) );
107     }
108 
109     // ========================================== Swapping read/write routines
110 
111     /**
112      * Writes a "short" value to a byte array at a given offset. The value is
113      * converted to the opposed endian system while writing.
114      * @param data target byte array
115      * @param offset starting offset in the byte array
116      * @param value value to write
117      */
writeSwappedShort(byte[] data, int offset, short value)118     public static void writeSwappedShort(byte[] data, int offset, short value) {
119         data[ offset + 0 ] = (byte)( ( value >> 0 ) & 0xff );
120         data[ offset + 1 ] = (byte)( ( value >> 8 ) & 0xff );
121     }
122 
123     /**
124      * Reads a "short" value from a byte array at a given offset. The value is
125      * converted to the opposed endian system while reading.
126      * @param data source byte array
127      * @param offset starting offset in the byte array
128      * @return the value read
129      */
readSwappedShort(byte[] data, int offset)130     public static short readSwappedShort(byte[] data, int offset) {
131         return (short)( ( ( data[ offset + 0 ] & 0xff ) << 0 ) +
132             ( ( data[ offset + 1 ] & 0xff ) << 8 ) );
133     }
134 
135     /**
136      * Reads an unsigned short (16-bit) value from a byte array at a given
137      * offset. The value is converted to the opposed endian system while
138      * reading.
139      * @param data source byte array
140      * @param offset starting offset in the byte array
141      * @return the value read
142      */
readSwappedUnsignedShort(byte[] data, int offset)143     public static int readSwappedUnsignedShort(byte[] data, int offset) {
144         return ( ( ( data[ offset + 0 ] & 0xff ) << 0 ) +
145             ( ( data[ offset + 1 ] & 0xff ) << 8 ) );
146     }
147 
148     /**
149      * Writes a "int" value to a byte array at a given offset. The value is
150      * converted to the opposed endian system while writing.
151      * @param data target byte array
152      * @param offset starting offset in the byte array
153      * @param value value to write
154      */
writeSwappedInteger(byte[] data, int offset, int value)155     public static void writeSwappedInteger(byte[] data, int offset, int value) {
156         data[ offset + 0 ] = (byte)( ( value >> 0 ) & 0xff );
157         data[ offset + 1 ] = (byte)( ( value >> 8 ) & 0xff );
158         data[ offset + 2 ] = (byte)( ( value >> 16 ) & 0xff );
159         data[ offset + 3 ] = (byte)( ( value >> 24 ) & 0xff );
160     }
161 
162     /**
163      * Reads a "int" value from a byte array at a given offset. The value is
164      * converted to the opposed endian system while reading.
165      * @param data source byte array
166      * @param offset starting offset in the byte array
167      * @return the value read
168      */
readSwappedInteger(byte[] data, int offset)169     public static int readSwappedInteger(byte[] data, int offset) {
170         return ( ( ( data[ offset + 0 ] & 0xff ) << 0 ) +
171             ( ( data[ offset + 1 ] & 0xff ) << 8 ) +
172             ( ( data[ offset + 2 ] & 0xff ) << 16 ) +
173             ( ( data[ offset + 3 ] & 0xff ) << 24 ) );
174     }
175 
176     /**
177      * Reads an unsigned integer (32-bit) value from a byte array at a given
178      * offset. The value is converted to the opposed endian system while
179      * reading.
180      * @param data source byte array
181      * @param offset starting offset in the byte array
182      * @return the value read
183      */
readSwappedUnsignedInteger(byte[] data, int offset)184     public static long readSwappedUnsignedInteger(byte[] data, int offset) {
185         long low = ( ( ( data[ offset + 0 ] & 0xff ) << 0 ) +
186                      ( ( data[ offset + 1 ] & 0xff ) << 8 ) +
187                      ( ( data[ offset + 2 ] & 0xff ) << 16 ) );
188 
189         long high = data[ offset + 3 ] & 0xff;
190 
191         return (high << 24) + (0xffffffffL & low);
192     }
193 
194     /**
195      * Writes a "long" value to a byte array at a given offset. The value is
196      * converted to the opposed endian system while writing.
197      * @param data target byte array
198      * @param offset starting offset in the byte array
199      * @param value value to write
200      */
writeSwappedLong(byte[] data, int offset, long value)201     public static void writeSwappedLong(byte[] data, int offset, long value) {
202         data[ offset + 0 ] = (byte)( ( value >> 0 ) & 0xff );
203         data[ offset + 1 ] = (byte)( ( value >> 8 ) & 0xff );
204         data[ offset + 2 ] = (byte)( ( value >> 16 ) & 0xff );
205         data[ offset + 3 ] = (byte)( ( value >> 24 ) & 0xff );
206         data[ offset + 4 ] = (byte)( ( value >> 32 ) & 0xff );
207         data[ offset + 5 ] = (byte)( ( value >> 40 ) & 0xff );
208         data[ offset + 6 ] = (byte)( ( value >> 48 ) & 0xff );
209         data[ offset + 7 ] = (byte)( ( value >> 56 ) & 0xff );
210     }
211 
212     /**
213      * Reads a "long" value from a byte array at a given offset. The value is
214      * converted to the opposed endian system while reading.
215      * @param data source byte array
216      * @param offset starting offset in the byte array
217      * @return the value read
218      */
readSwappedLong(byte[] data, int offset)219     public static long readSwappedLong(byte[] data, int offset) {
220         long low =
221             ( ( data[ offset + 0 ] & 0xff ) << 0 ) +
222             ( ( data[ offset + 1 ] & 0xff ) << 8 ) +
223             ( ( data[ offset + 2 ] & 0xff ) << 16 ) +
224             ( ( data[ offset + 3 ] & 0xff ) << 24 );
225         long high =
226             ( ( data[ offset + 4 ] & 0xff ) << 0 ) +
227             ( ( data[ offset + 5 ] & 0xff ) << 8 ) +
228             ( ( data[ offset + 6 ] & 0xff ) << 16 ) +
229             ( ( data[ offset + 7 ] & 0xff ) << 24 );
230         return (high << 32) + (0xffffffffL & low);
231     }
232 
233     /**
234      * Writes a "float" value to a byte array at a given offset. The value is
235      * converted to the opposed endian system while writing.
236      * @param data target byte array
237      * @param offset starting offset in the byte array
238      * @param value value to write
239      */
writeSwappedFloat(byte[] data, int offset, float value)240     public static void writeSwappedFloat(byte[] data, int offset, float value) {
241         writeSwappedInteger( data, offset, Float.floatToIntBits( value ) );
242     }
243 
244     /**
245      * Reads a "float" value from a byte array at a given offset. The value is
246      * converted to the opposed endian system while reading.
247      * @param data source byte array
248      * @param offset starting offset in the byte array
249      * @return the value read
250      */
readSwappedFloat(byte[] data, int offset)251     public static float readSwappedFloat(byte[] data, int offset) {
252         return Float.intBitsToFloat( readSwappedInteger( data, offset ) );
253     }
254 
255     /**
256      * Writes a "double" value to a byte array at a given offset. The value is
257      * converted to the opposed endian system while writing.
258      * @param data target byte array
259      * @param offset starting offset in the byte array
260      * @param value value to write
261      */
writeSwappedDouble(byte[] data, int offset, double value)262     public static void writeSwappedDouble(byte[] data, int offset, double value) {
263         writeSwappedLong( data, offset, Double.doubleToLongBits( value ) );
264     }
265 
266     /**
267      * Reads a "double" value from a byte array at a given offset. The value is
268      * converted to the opposed endian system while reading.
269      * @param data source byte array
270      * @param offset starting offset in the byte array
271      * @return the value read
272      */
readSwappedDouble(byte[] data, int offset)273     public static double readSwappedDouble(byte[] data, int offset) {
274         return Double.longBitsToDouble( readSwappedLong( data, offset ) );
275     }
276 
277     /**
278      * Writes a "short" value to an OutputStream. The value is
279      * converted to the opposed endian system while writing.
280      * @param output target OutputStream
281      * @param value value to write
282      * @throws IOException in case of an I/O problem
283      */
writeSwappedShort(OutputStream output, short value)284     public static void writeSwappedShort(OutputStream output, short value)
285         throws IOException
286     {
287         output.write( (byte)( ( value >> 0 ) & 0xff ) );
288         output.write( (byte)( ( value >> 8 ) & 0xff ) );
289     }
290 
291     /**
292      * Reads a "short" value from an InputStream. The value is
293      * converted to the opposed endian system while reading.
294      * @param input source InputStream
295      * @return the value just read
296      * @throws IOException in case of an I/O problem
297      */
readSwappedShort(InputStream input)298     public static short readSwappedShort(InputStream input)
299         throws IOException
300     {
301         return (short)( ( ( read( input ) & 0xff ) << 0 ) +
302             ( ( read( input ) & 0xff ) << 8 ) );
303     }
304 
305     /**
306      * Reads a unsigned short (16-bit) from an InputStream. The value is
307      * converted to the opposed endian system while reading.
308      * @param input source InputStream
309      * @return the value just read
310      * @throws IOException in case of an I/O problem
311      */
readSwappedUnsignedShort(InputStream input)312     public static int readSwappedUnsignedShort(InputStream input)
313         throws IOException
314     {
315         int value1 = read( input );
316         int value2 = read( input );
317 
318         return ( ( ( value1 & 0xff ) << 0 ) +
319             ( ( value2 & 0xff ) << 8 ) );
320     }
321 
322     /**
323      * Writes a "int" value to an OutputStream. The value is
324      * converted to the opposed endian system while writing.
325      * @param output target OutputStream
326      * @param value value to write
327      * @throws IOException in case of an I/O problem
328      */
writeSwappedInteger(OutputStream output, int value)329     public static void writeSwappedInteger(OutputStream output, int value)
330         throws IOException
331     {
332         output.write( (byte)( ( value >> 0 ) & 0xff ) );
333         output.write( (byte)( ( value >> 8 ) & 0xff ) );
334         output.write( (byte)( ( value >> 16 ) & 0xff ) );
335         output.write( (byte)( ( value >> 24 ) & 0xff ) );
336     }
337 
338     /**
339      * Reads a "int" value from an InputStream. The value is
340      * converted to the opposed endian system while reading.
341      * @param input source InputStream
342      * @return the value just read
343      * @throws IOException in case of an I/O problem
344      */
readSwappedInteger(InputStream input)345     public static int readSwappedInteger(InputStream input)
346         throws IOException
347     {
348         int value1 = read( input );
349         int value2 = read( input );
350         int value3 = read( input );
351         int value4 = read( input );
352 
353         return ( ( value1 & 0xff ) << 0 ) +
354             ( ( value2 & 0xff ) << 8 ) +
355             ( ( value3 & 0xff ) << 16 ) +
356             ( ( value4 & 0xff ) << 24 );
357     }
358 
359     /**
360      * Reads a unsigned integer (32-bit) from an InputStream. The value is
361      * converted to the opposed endian system while reading.
362      * @param input source InputStream
363      * @return the value just read
364      * @throws IOException in case of an I/O problem
365      */
readSwappedUnsignedInteger(InputStream input)366     public static long readSwappedUnsignedInteger(InputStream input)
367         throws IOException
368     {
369         int value1 = read( input );
370         int value2 = read( input );
371         int value3 = read( input );
372         int value4 = read( input );
373 
374         long low = ( ( ( value1 & 0xff ) << 0 ) +
375                      ( ( value2 & 0xff ) << 8 ) +
376                      ( ( value3 & 0xff ) << 16 ) );
377 
378         long high = value4 & 0xff;
379 
380         return (high << 24) + (0xffffffffL & low);
381     }
382 
383     /**
384      * Writes a "long" value to an OutputStream. The value is
385      * converted to the opposed endian system while writing.
386      * @param output target OutputStream
387      * @param value value to write
388      * @throws IOException in case of an I/O problem
389      */
writeSwappedLong(OutputStream output, long value)390     public static void writeSwappedLong(OutputStream output, long value)
391         throws IOException
392     {
393         output.write( (byte)( ( value >> 0 ) & 0xff ) );
394         output.write( (byte)( ( value >> 8 ) & 0xff ) );
395         output.write( (byte)( ( value >> 16 ) & 0xff ) );
396         output.write( (byte)( ( value >> 24 ) & 0xff ) );
397         output.write( (byte)( ( value >> 32 ) & 0xff ) );
398         output.write( (byte)( ( value >> 40 ) & 0xff ) );
399         output.write( (byte)( ( value >> 48 ) & 0xff ) );
400         output.write( (byte)( ( value >> 56 ) & 0xff ) );
401     }
402 
403     /**
404      * Reads a "long" value from an InputStream. The value is
405      * converted to the opposed endian system while reading.
406      * @param input source InputStream
407      * @return the value just read
408      * @throws IOException in case of an I/O problem
409      */
readSwappedLong(InputStream input)410     public static long readSwappedLong(InputStream input)
411         throws IOException
412     {
413         byte[] bytes = new byte[8];
414         for ( int i=0; i<8; i++ ) {
415             bytes[i] = (byte) read( input );
416         }
417         return readSwappedLong( bytes, 0 );
418     }
419 
420     /**
421      * Writes a "float" value to an OutputStream. The value is
422      * converted to the opposed endian system while writing.
423      * @param output target OutputStream
424      * @param value value to write
425      * @throws IOException in case of an I/O problem
426      */
writeSwappedFloat(OutputStream output, float value)427     public static void writeSwappedFloat(OutputStream output, float value)
428         throws IOException
429     {
430         writeSwappedInteger( output, Float.floatToIntBits( value ) );
431     }
432 
433     /**
434      * Reads a "float" value from an InputStream. The value is
435      * converted to the opposed endian system while reading.
436      * @param input source InputStream
437      * @return the value just read
438      * @throws IOException in case of an I/O problem
439      */
readSwappedFloat(InputStream input)440     public static float readSwappedFloat(InputStream input)
441         throws IOException
442     {
443         return Float.intBitsToFloat( readSwappedInteger( input ) );
444     }
445 
446     /**
447      * Writes a "double" value to an OutputStream. The value is
448      * converted to the opposed endian system while writing.
449      * @param output target OutputStream
450      * @param value value to write
451      * @throws IOException in case of an I/O problem
452      */
writeSwappedDouble(OutputStream output, double value)453     public static void writeSwappedDouble(OutputStream output, double value)
454         throws IOException
455     {
456         writeSwappedLong( output, Double.doubleToLongBits( value ) );
457     }
458 
459     /**
460      * Reads a "double" value from an InputStream. The value is
461      * converted to the opposed endian system while reading.
462      * @param input source InputStream
463      * @return the value just read
464      * @throws IOException in case of an I/O problem
465      */
readSwappedDouble(InputStream input)466     public static double readSwappedDouble(InputStream input)
467         throws IOException
468     {
469         return Double.longBitsToDouble( readSwappedLong( input ) );
470     }
471 
472     /**
473      * Reads the next byte from the input stream.
474      * @param input  the stream
475      * @return the byte
476      * @throws IOException if the end of file is reached
477      */
read(InputStream input)478     private static int read(InputStream input)
479         throws IOException
480     {
481         int value = input.read();
482 
483         if( -1 == value ) {
484             throw new EOFException( "Unexpected EOF reached" );
485         }
486 
487         return value;
488     }
489 }
490