1 package org.simantics.databoard.util.binary;
\r
3 import java.io.DataInput;
\r
4 import java.io.DataOutput;
\r
5 import java.io.IOException;
\r
8 * DataInput and DataOutput serialize primitive numbers with big endian byte
\r
9 * order. This utility gives little endian read and write.
\r
11 * @author Toni Kalajainen <toni.kalajainen@iki.fi>
\r
13 public class LittleEndian {
\r
15 public static short readShort(DataInput in) throws IOException {
\r
16 return (short) (in.readUnsignedByte() | (in.readUnsignedByte() << 8));
\r
19 public static void writeShort(DataOutput out, int v) throws IOException {
\r
20 v = (((v & 0xFF00) >> 8) | (v << 8));
\r
21 out.writeShort( v );
\r
24 public static int readUnsignedShort(DataInput in) throws IOException {
\r
25 int v = in.readUnsignedShort();
\r
26 return (((v & 0xFF00) >> 8) | (v << 8));
\r
29 public static int readInt(DataInput in) throws IOException {
\r
30 return Integer.reverseBytes( in.readInt() );
\r
33 public static void writeInt(DataOutput out, int v) throws IOException {
\r
34 out.writeInt( Integer.reverseBytes( v ) );
\r
37 public static long readLong(DataInput in) throws IOException {
\r
38 return Long.reverseBytes( in.readLong() );
\r
41 public static void writeLong(DataOutput out, long v) throws IOException {
\r
42 out.writeLong( Long.reverseBytes(v) );
\r
45 public static double readDouble(DataInput in) throws IOException {
\r
46 return Double.longBitsToDouble( Long.reverseBytes( in.readLong() ) );
\r
49 public static void writeDouble(DataOutput out, double d) throws IOException {
\r
50 out.writeLong( Long.reverseBytes( Double.doubleToLongBits(d) ) );
\r
53 public static float readFloat(DataInput in) throws IOException {
\r
54 return Float.intBitsToFloat( Integer.reverseBytes( in.readInt() ) );
\r
57 public static void writeFloat(DataOutput out, float v) throws IOException {
\r
58 out.writeInt( Integer.reverseBytes( Float.floatToIntBits(v) ) );
\r
61 public static void writeUInt24(DataOutput out, int value) throws IOException {
\r
62 out.write((byte)value);
\r
63 out.write((byte)(value >> 8));
\r
64 out.write((byte)(value >> 16));
\r
67 public static int readUInt24(DataInput in) throws IOException {
\r
70 ( in.readByte() << 8) |
\r
71 ( in.readByte() << 16) ) & 0xffffff;
\r
77 * Write UInt32 with dynamic encoding (1-5 bytes).
\r
81 * @throws IOException
\r
83 public static void writeDynamicUInt32(DataOutput out, int length) throws IOException {
\r
85 out.write((byte)length);
\r
89 if(length < 0x4000) {
\r
90 out.write((byte)((length&0x3f) | 0x80));
\r
91 out.write((byte)(length>>>6));
\r
95 if(length < 0x200000) {
\r
96 out.write((byte)((length&0x1f) | 0xc0));
\r
97 out.write((byte)((length>>>5)&0xff));
\r
98 out.write((byte)((length>>>13)&0xff));
\r
101 length -= 0x200000;
\r
102 if(length < 0x10000000) {
\r
103 out.write((byte)((length&0x0f) | 0xe0));
\r
104 out.write((byte)((length>>>4)&0xff));
\r
105 out.write((byte)((length>>>12)&0xff));
\r
106 out.write((byte)((length>>>20)&0xff));
\r
109 length -= 0x10000000;
\r
110 out.write((byte)((length&0x07) | 0xf0));
\r
111 out.write((byte)((length>>>3)&0xff));
\r
112 out.write((byte)((length>>>11)&0xff));
\r
113 out.write((byte)((length>>>19)&0xff));
\r
114 out.write((byte)((length>>>27)&0xff));
\r
122 public static int readDynamicUInt32(DataInput in) throws IOException {
\r
123 int length = in.readByte()&0xff;
\r
124 if(length >= 0x80) {
\r
125 if(length >= 0xc0) {
\r
126 if(length >= 0xe0) {
\r
127 if(length >= 0xf0) {
\r
129 length += ((in.readByte()&0xff)<<3);
\r
130 length += ((in.readByte()&0xff)<<11);
\r
131 length += ((in.readByte()&0xff)<<19);
\r
132 length += 0x10204080;
\r
136 length += ((in.readByte()&0xff)<<4);
\r
137 length += ((in.readByte()&0xff)<<12);
\r
138 length += ((in.readByte()&0xff)<<20);
\r
139 length += 0x204080;
\r
144 length += ((in.readByte()&0xff)<<5);
\r
145 length += ((in.readByte()&0xff)<<13);
\r
151 length += ((in.readByte()&0xff)<<6);
\r
160 * Get number of bytes for dynamic encoding of UInt32 (1-5 bytes)
\r
162 * @param length length value
\r
163 * @return bytes required (1-5)
\r
165 public static int getDynamicUInt32Length(int length)
\r
167 if(length < 0x80) return 1;
\r
168 if(length < 0x4080) return 2;
\r
169 if(length < 0x204000) return 3;
\r
170 if(length < 0x10200000) return 4;
\r
176 * Decode an unsigned integer. The number of bytes read depends on maxValue.
\r
181 * @throws IOException
\r
183 public static int getUInt(DataInput in, int maxValue)
\r
186 if (maxValue==0) return 0;
\r
187 if (maxValue<0x100) {
\r
188 return in.readByte() & 0xFF;
\r
189 } else if (maxValue<0x10000) {
\r
190 return LittleEndian.readShort(in) & 0xFFFF;
\r
191 } else if (maxValue<0x1000000) {
\r
192 return LittleEndian.readUInt24(in) & 0xFFFFFF;
\r
194 return readInt(in);
\r
199 * Calculate unsigned integer encoding length.
\r
202 * @return 0-4 bytes
\r
204 public static int getUIntLength(int maxValue)
\r
208 } else if (maxValue<0x100) {
\r
210 } else if (maxValue<0x10000) {
\r
212 } else if (maxValue<0x1000000) {
\r
220 * Encode and write an unsigned integer. The number of bytes written
\r
221 * depends on the maxValue.
\r
226 * @throws IOException
\r
228 public static void putUInt(DataOutput out, int value, int maxValue)
\r
229 throws IOException {
\r
230 if (maxValue==0) {}
\r
231 else if (maxValue<0x100) {
\r
233 } else if (maxValue<0x10000) {
\r
234 LittleEndian.writeShort(out, value);
\r
235 } else if (maxValue<0x1000000) {
\r
236 LittleEndian.writeUInt24(out, value);
\r
238 out.writeInt(value);
\r