diff --git a/Dorkbox-Util/LICENSE b/Dorkbox-Util/LICENSE index 8c70a31..cef1190 100644 --- a/Dorkbox-Util/LICENSE +++ b/Dorkbox-Util/LICENSE @@ -90,3 +90,10 @@ http://www.cs.gmu.edu/~sean/research/mersenne/MersenneTwisterFast.java Copyright 2003 by Sean Luke Portions copyright 1993 by Michael Lecuyer + + + + - jOOU, Unsigned Numbers for Java - Apache 2.0 License + https://github.com/jOOQ/jOOU/tree/master/jOOU + Copyright 2011-2013, Lukas Eder, lukas.eder@gmail.com + diff --git a/Dorkbox-Util/src/dorkbox/util/bytes/BigEndian.java b/Dorkbox-Util/src/dorkbox/util/bytes/BigEndian.java new file mode 100644 index 0000000..d43d876 --- /dev/null +++ b/Dorkbox-Util/src/dorkbox/util/bytes/BigEndian.java @@ -0,0 +1,493 @@ +/* + * Copyright 2014 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.bytes; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.nio.ByteBuffer; + +/** + * This is (mostly) motorola, and is "network byte order". + * This is also the default for Java. + *
+ * arm is technically bi-endian + */ +public class BigEndian { + // the following are ALL in Bit-Endian (byte[0] is most significant) + // TODO: switch these to big endian. these are a copy of little endian + + /** CHAR to and from bytes */ + public static class Char_ { + @SuppressWarnings("fallthrough") + public static char from(byte[] bytes, int offset, int bytenum) { + char number = 0; + + switch (bytenum) { + case 2: number |= (bytes[offset+0] & 0xFF) << 8; + case 1: number |= (bytes[offset+1] & 0xFF) << 0; + } + + return number; + } + + @SuppressWarnings("fallthrough") + public static char from(byte[] bytes) { + char number = 0; + + switch (bytes.length) { + case 2: number |= (bytes[0] & 0xFF) << 8; + case 1: number |= (bytes[1] & 0xFF) << 0; + } + + return number; + } + + public static char from(byte b0, byte b1) { + return (char) ((b0 & 0xFF) << 8 | + (b1 & 0xFF) << 0); + } + + public static byte[] toBytes(char x) { + return new byte[] {(byte) (x >> 8), + (byte) (x >> 0) + }; + } + + public static char from(ByteBuffer buff) { + return from(buff.get(), buff.get()); + } + + public static char fromStream(InputStream inputStream) throws IOException { + byte[] b = new byte[2]; + if (inputStream.read(b) != 2) { + throw new EOFException(); + } + + return from(b[0], b[1]); + } + } + + /** UNSIGNED CHAR to and from bytes */ + public static class UChar_ { + @SuppressWarnings("fallthrough") + public static UShort from(byte[] bytes, int offset, int bytenum) { + char number = 0; + + switch (bytenum) { + case 2: number |= (bytes[offset+0] & 0xFF) << 8; + case 1: number |= (bytes[offset+1] & 0xFF) << 0; + } + + return UShort.valueOf(number); + } + + @SuppressWarnings("fallthrough") + public static UShort from(byte[] bytes) { + short number = 0; + + switch (bytes.length) { + case 2: number |= (bytes[0] & 0xFF) << 8; + case 1: number |= (bytes[1] & 0xFF) << 0; + } + + return UShort.valueOf(number); + } + + public static UShort from(byte b0, byte b1) { + return UShort.valueOf((short) + ((b0 & 0xFF) << 8) | + (b1 & 0xFF) << 0) ; + } + + + public static byte[] toBytes(UShort x) { + int num = x.intValue(); + + return new byte[] {(byte) ((num & 0xFF00) >> 8), + (byte) (num & 0x00FF >> 0), + }; + } + + public static UShort from(ByteBuffer buff) { + return from(buff.get(), buff.get()); + } + + public static UShort fromStream(InputStream inputStream) throws IOException { + byte[] b = new byte[2]; + if (inputStream.read(b) != 2) { + throw new EOFException(); + } + + return from(b[0], b[1]); + } + } + + /** SHORT to and from bytes */ + public static class Short_ { + @SuppressWarnings("fallthrough") + public static short from(byte[] bytes, int offset, int bytenum) { + short number = 0; + + switch (bytenum) { + case 2: number |= (bytes[offset+0] & 0xFF) << 8; + case 1: number |= (bytes[offset+1] & 0xFF) << 0; + } + + return number; + } + + @SuppressWarnings("fallthrough") + public static short from(byte[] bytes) { + short number = 0; + + switch (bytes.length) { + case 2: number |= (bytes[0] & 0xFF) << 8; + case 1: number |= (bytes[1] & 0xFF) << 0; + } + + return number; + } + + public static short from(byte b0, byte b1) { + return (short) ((b0 & 0xFF) << 8 | + (b1 & 0xFF) << 0); + } + + + public static byte[] toBytes(short x) { + return new byte[] {(byte) (x >> 8), + (byte) (x >> 0) + }; + } + + public static short from(ByteBuffer buff) { + return from(buff.get(), buff.get()); + } + + public static short fromStream(InputStream inputStream) throws IOException { + byte[] b = new byte[2]; + if (inputStream.read(b) != 2) { + throw new EOFException(); + } + + return from(b[0], b[1]); + } + } + + /** UNSIGNED SHORT to and from bytes */ + public static class UShort_ { + @SuppressWarnings("fallthrough") + public static UShort from(byte[] bytes, int offset, int bytenum) { + char number = 0; + + switch (bytenum) { + case 2: number |= (bytes[offset+0] & 0xFF) << 8; + case 1: number |= (bytes[offset+1] & 0xFF) << 0; + } + + return UShort.valueOf(number); + } + + @SuppressWarnings("fallthrough") + public static UShort from(byte[] bytes) { + short number = 0; + + switch (bytes.length) { + case 2: number |= (bytes[0] & 0xFF) << 8; + case 1: number |= (bytes[1] & 0xFF) << 0; + } + + return UShort.valueOf(number); + } + + public static UShort from(byte b0, byte b1) { + return UShort.valueOf((short) + ((b0 & 0xFF) << 8) | + (b1 & 0xFF) << 0) ; + } + + + public static byte[] toBytes(UShort x) { + int num = x.intValue(); + + return new byte[] {(byte) ((num & 0xFF00) >> 8), + (byte) (num & 0x00FF >> 0), + }; + } + + public static UShort from(ByteBuffer buff) { + return from(buff.get(), buff.get()); + } + + public static UShort fromStream(InputStream inputStream) throws IOException { + byte[] b = new byte[2]; + if (inputStream.read(b) != 2) { + throw new EOFException(); + } + + return from(b[0], b[1]); + } + } + + /** INT to and from bytes */ + public static class Int_ { + @SuppressWarnings("fallthrough") + public static int from(byte[] bytes, int offset, int bytenum) { + int number = 0; + + switch (bytenum) { + case 4: number |= (bytes[offset+0] & 0xFF) << 24; + case 3: number |= (bytes[offset+1] & 0xFF) << 16; + case 2: number |= (bytes[offset+2] & 0xFF) << 8; + case 1: number |= (bytes[offset+3] & 0xFF) << 0; + } + + return number; + } + + @SuppressWarnings("fallthrough") + public static int from(byte[] bytes) { + int number = 0; + + switch (bytes.length) { + case 4: number |= (bytes[0] & 0xFF) << 24; + case 3: number |= (bytes[1] & 0xFF) << 16; + case 2: number |= (bytes[2] & 0xFF) << 8; + case 1: number |= (bytes[3] & 0xFF) << 0; + } + + return number; + } + + public static int from(byte b0, byte b1, byte b2, byte b3) { + return (b0 & 0xFF) << 24 | + (b1 & 0xFF) << 16 | + (b2 & 0xFF) << 8 | + (b3 & 0xFF) << 0; + } + + public static byte[] toBytes(int x) { + return new byte[] {(byte) (x >> 24), + (byte) (x >> 16), + (byte) (x >> 8), + (byte) (x >> 0) + } ; + } + + public static int from(ByteBuffer buff) { + return from(buff.get(), buff.get(), buff.get(), buff.get()); + } + + public static int fromStream(InputStream inputStream) throws IOException { + byte[] b = new byte[4]; + if (inputStream.read(b) != 4) { + throw new EOFException(); + } + + return from(b[0], b[1], b[2], b[3]); + } + } + + /** UNSIGNED INT to and from bytes */ + public static class UInt_ { + @SuppressWarnings("fallthrough") + public static UInteger from(byte[] bytes, int offset, int bytenum) { + int number = 0; + + switch (bytenum) { + case 4: number |= (bytes[offset+0] & 0xFF) << 24; + case 3: number |= (bytes[offset+1] & 0xFF) << 16; + case 2: number |= (bytes[offset+2] & 0xFF) << 8; + case 1: number |= (bytes[offset+3] & 0xFF) << 0; + } + + return UInteger.valueOf(number); + } + + @SuppressWarnings("fallthrough") + public static UInteger from(byte[] bytes) { + int number = 0; + + switch (bytes.length) { + case 4: number |= (bytes[0] & 0xFF) << 24; + case 3: number |= (bytes[1] & 0xFF) << 16; + case 2: number |= (bytes[2] & 0xFF) << 8; + case 1: number |= (bytes[3] & 0xFF) << 0; + } + + return UInteger.valueOf(number); + } + + public static UInteger from(byte b0, byte b1, byte b2, byte b3) { + int number = (b0 & 0xFF) << 24 | + (b1 & 0xFF) << 16 | + (b2 & 0xFF) << 8 | + (b3 & 0xFF) << 0; + + return UInteger.valueOf(number); + } + + public static byte[] toBytes(UInteger x) { + long num = x.longValue(); + + return new byte[] {(byte) ((num & 0xFF000000L) >> 24), + (byte) ((num & 0x00FF0000L) >> 16), + (byte) ((num & 0x0000FF00L) >> 8), + (byte) (num & 0x000000FFL >> 0) + }; + } + + public static UInteger from(ByteBuffer buff) { + return from(buff.get(), buff.get(), buff.get(), buff.get()); + } + + public static UInteger fromStream(InputStream inputStream) throws IOException { + byte[] b = new byte[4]; + if (inputStream.read(b) != 4) { + throw new EOFException(); + } + + return from(b[0], b[1], b[2], b[3]); + } + } + + /** LONG to and from bytes */ + public static class Long_ { + @SuppressWarnings("fallthrough") + public static long from(byte[] bytes, int offset, int bytenum) { + long number = 0; + + switch (bytenum) { + case 8: number |= (long) (bytes[offset+0] & 0xFF) << 56; + case 7: number |= (long) (bytes[offset+1] & 0xFF) << 48; + case 6: number |= (long) (bytes[offset+2] & 0xFF) << 40; + case 5: number |= (long) (bytes[offset+3] & 0xFF) << 32; + case 4: number |= (long) (bytes[offset+4] & 0xFF) << 24; + case 3: number |= (long) (bytes[offset+5] & 0xFF) << 16; + case 2: number |= (long) (bytes[offset+6] & 0xFF) << 8; + case 1: number |= (long) (bytes[offset+7] & 0xFF) << 0; + } + + return number; + } + + @SuppressWarnings("fallthrough") + public static long from(byte[] bytes) { + long number = 0L; + + switch (bytes.length) { + case 8: number |= (long) (bytes[0] & 0xFF) << 56; + case 7: number |= (long) (bytes[1] & 0xFF) << 48; + case 6: number |= (long) (bytes[2] & 0xFF) << 40; + case 5: number |= (long) (bytes[3] & 0xFF) << 32; + case 4: number |= (long) (bytes[4] & 0xFF) << 24; + case 3: number |= (long) (bytes[5] & 0xFF) << 16; + case 2: number |= (long) (bytes[6] & 0xFF) << 8; + case 1: number |= (long) (bytes[7] & 0xFF) << 0; + } + + return number; + } + + public static long from(byte b0, byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7) { + return (long) (b0 & 0xFF) << 56 | + (long) (b1 & 0xFF) << 48 | + (long) (b2 & 0xFF) << 40 | + (long) (b3 & 0xFF) << 32 | + (long) (b4 & 0xFF) << 24 | + (long) (b5 & 0xFF) << 16 | + (long) (b6 & 0xFF) << 8 | + (long) (b7 & 0xFF) << 0; + } + + public static byte[] toBytes (long x) { + return new byte[] {(byte) (x >> 56), + (byte) (x >> 48), + (byte) (x >> 40), + (byte) (x >> 32), + (byte) (x >> 24), + (byte) (x >> 16), + (byte) (x >> 8), + (byte) (x >> 0) + }; + } + + public static long from(ByteBuffer buff) { + return from(buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get()); + } + + public static long fromStream(InputStream inputStream) throws IOException { + byte[] b = new byte[8]; + if (inputStream.read(b) != 8) { + throw new EOFException(); + } + + return from(b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + } + } + + /** UNSIGNED LONG to and from bytes */ + public static class ULong_ { + @SuppressWarnings("fallthrough") + public static ULong from(byte[] bytes, int offset, int bytenum) { + long number = 0; + + switch (bytenum) { + case 8: number |= (long) (bytes[offset+0] & 0xFF) << 56; + case 7: number |= (long) (bytes[offset+1] & 0xFF) << 48; + case 6: number |= (long) (bytes[offset+2] & 0xFF) << 40; + case 5: number |= (long) (bytes[offset+3] & 0xFF) << 32; + case 4: number |= (long) (bytes[offset+4] & 0xFF) << 24; + case 3: number |= (long) (bytes[offset+5] & 0xFF) << 16; + case 2: number |= (long) (bytes[offset+6] & 0xFF) << 8; + case 1: number |= (long) (bytes[offset+7] & 0xFF) << 0; + } + + return ULong.valueOf(number); + } + + public static ULong from(byte[] bytes) { + BigInteger ulong = new BigInteger(1, bytes); + return ULong.valueOf(ulong); + } + + public static ULong from(byte b0, byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7) { + byte[] bytes = new byte[] {b0, b1, b2, b3, b4, b5, b6, b7}; + BigInteger ulong = new BigInteger(1, bytes); + return ULong.valueOf(ulong); + } + + public static byte[] toBytes (ULong x) { + return x.toBigInteger().toByteArray(); + } + + public static ULong from(ByteBuffer buff) { + return from(buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get()); + } + + public static ULong from(InputStream inputStream) throws IOException { + byte[] b = new byte[8]; + if (inputStream.read(b) != 8) { + throw new EOFException(); + } + + return from(b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + } + } +} + diff --git a/Dorkbox-Util/src/dorkbox/util/bytes/LittleEndian.java b/Dorkbox-Util/src/dorkbox/util/bytes/LittleEndian.java index 7f3fd8e..e037dfa 100644 --- a/Dorkbox-Util/src/dorkbox/util/bytes/LittleEndian.java +++ b/Dorkbox-Util/src/dorkbox/util/bytes/LittleEndian.java @@ -15,175 +15,273 @@ */ package dorkbox.util.bytes; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; import java.nio.ByteBuffer; /** * This is intel/amd/arm arch! - * + *
* arm is technically bi-endian + *
+ * Network byte order IS big endian, as is Java.
*/
public class LittleEndian {
- // the following are ALL in Little-Endian (big is to the right, first byte is least significant, unsigned bytes)
+ // the following are ALL in Little-Endian (byte[0] is least significant)
/** CHAR to and from bytes */
public static class Char_ {
@SuppressWarnings("fallthrough")
- public static final char fromBytes(byte[] bytes) {
+ public static char from(byte[] bytes, int offset, int bytenum) {
char number = 0;
- switch (bytes.length) {
- case 2: number += (bytes[1] & 0xFF) << 8;
- case 1: number += (bytes[0] & 0xFF) << 0;
+ switch (bytenum) {
+ case 2: number |= (bytes[offset+1] & 0xFF) << 8;
+ case 1: number |= (bytes[offset+0] & 0xFF) << 0;
}
return number;
}
- public static final char fromBytes(byte b0, byte b1) {
+ @SuppressWarnings("fallthrough")
+ public static char from(byte[] bytes) {
+ char number = 0;
+
+ switch (bytes.length) {
+ case 2: number |= (bytes[1] & 0xFF) << 8;
+ case 1: number |= (bytes[0] & 0xFF) << 0;
+ }
+
+ return number;
+ }
+
+ public static char from(byte b0, byte b1) {
return (char) ((b1 & 0xFF) << 8 |
(b0 & 0xFF) << 0);
}
- public static final byte[] toBytes(char x) {
+ public static byte[] toBytes(char x) {
return new byte[] {(byte) (x >> 0),
(byte) (x >> 8)
};
}
- public static final int fromBytes(ByteBuffer buff) {
- return fromBytes(buff.get(), buff.get());
+ public static char from(ByteBuffer buff) {
+ return from(buff.get(), buff.get());
+ }
+
+ public static char from(InputStream inputStream) throws IOException {
+ byte[] b = new byte[2];
+ if (inputStream.read(b) != 2) {
+ throw new EOFException();
+ }
+
+ return from(b[0], b[1]);
}
}
- /** CHAR to and from bytes */
+ /** UNSIGNED CHAR to and from bytes */
public static class UChar_ {
@SuppressWarnings("fallthrough")
- public static final char fromBytes(byte[] bytes) {
+ public static UShort from(byte[] bytes, int offset, int bytenum) {
char number = 0;
- switch (bytes.length) {
- case 2: number += (bytes[1] & 0xFF) << 8;
- case 1: number += (bytes[0] & 0xFF) << 0;
+ switch (bytenum) {
+ case 2: number |= (bytes[offset+1] & 0xFF) << 8;
+ case 1: number |= (bytes[offset+0] & 0xFF) << 0;
}
- return number;
+ return UShort.valueOf(number);
}
- public static final char fromBytes(byte b0, byte b1) {
- return (char) ((b1 & 0xFF) << 8 |
- (b0 & 0xFF) << 0);
+ @SuppressWarnings("fallthrough")
+ public static UShort from(byte[] bytes) {
+ short number = 0;
+
+ switch (bytes.length) {
+ case 2: number |= (bytes[1] & 0xFF) << 8;
+ case 1: number |= (bytes[0] & 0xFF) << 0;
+ }
+
+ return UShort.valueOf(number);
+ }
+
+ public static UShort from(byte b0, byte b1) {
+ return UShort.valueOf((short)
+ ((b1 & 0xFF) << 8) |
+ (b0 & 0xFF) << 0) ;
}
- public static final byte[] toBytes(char x) {
- return new byte[] {(byte) (x >> 8),
- (byte) (x >> 0)
+ public static byte[] toBytes(UShort x) {
+ int num = x.intValue();
+
+ return new byte[] {(byte) (num & 0x00FF >> 0),
+ (byte) ((num & 0xFF00) >> 8)
};
}
- public static final int fromBytes(ByteBuffer buff) {
- return fromBytes(buff.get(), buff.get());
+ public static UShort from(ByteBuffer buff) {
+ return from(buff.get(), buff.get());
+ }
+
+ public static UShort from(InputStream inputStream) throws IOException {
+ byte[] b = new byte[2];
+ if (inputStream.read(b) != 2) {
+ throw new EOFException();
+ }
+
+ return from(b[0], b[1]);
}
}
/** SHORT to and from bytes */
public static class Short_ {
@SuppressWarnings("fallthrough")
- public static final short fromBytes(byte[] bytes) {
+ public static short from(byte[] bytes, int offset, int bytenum) {
short number = 0;
- switch (bytes.length) {
- case 2: number += (bytes[1] & 0xFF) << 8;
- case 1: number += (bytes[0] & 0xFF) << 0;
+ switch (bytenum) {
+ case 2: number |= (bytes[offset+1] & 0xFF) << 8;
+ case 1: number |= (bytes[offset+0] & 0xFF) << 0;
}
return number;
}
- public static final short fromBytes(byte b0, byte b1) {
+ @SuppressWarnings("fallthrough")
+ public static short from(byte[] bytes) {
+ short number = 0;
+
+ switch (bytes.length) {
+ case 2: number |= (bytes[1] & 0xFF) << 8;
+ case 1: number |= (bytes[0] & 0xFF) << 0;
+ }
+
+ return number;
+ }
+
+ public static short from(byte b0, byte b1) {
return (short) ((b1 & 0xFF) << 8 |
(b0 & 0xFF) << 0);
}
- public static final byte[] toBytes(short x) {
+ public static byte[] toBytes(short x) {
return new byte[] {(byte) (x >> 0),
(byte) (x >> 8)
};
}
- public static final int fromBytes(ByteBuffer buff) {
- return fromBytes(buff.get(), buff.get());
+ public static short from(ByteBuffer buff) {
+ return from(buff.get(), buff.get());
+ }
+
+ public static short from(InputStream inputStream) throws IOException {
+ byte[] b = new byte[2];
+ if (inputStream.read(b) != 2) {
+ throw new EOFException();
+ }
+
+ return from(b[0], b[1]);
}
}
- /** SHORT to and from bytes */
+ /** UNSIGNED SHORT to and from bytes */
public static class UShort_ {
@SuppressWarnings("fallthrough")
- public static final short fromBytes(byte[] bytes) {
- short number = 0;
-
- switch (bytes.length) {
- case 2: number += (bytes[1] & 0xFF) << 8;
- case 1: number += (bytes[0] & 0xFF) << 0;
- }
-
- return number;
- }
-
- @SuppressWarnings("fallthrough")
- public static short fromBytes(byte[] bytes, int offset, int bytenum) {
+ public static UShort from(byte[] bytes, int offset, int bytenum) {
short number = 0;
switch (bytenum) {
- case 2: number += (bytes[offset+1] & 0xFF) << 8;
- case 1: number += (bytes[offset+0] & 0xFF) << 0;
+ case 2: number |= (bytes[offset+1] & 0xFF) << 8;
+ case 1: number |= (bytes[offset+0] & 0xFF) << 0;
}
- return number;
+ return UShort.valueOf(number);
}
- public static final short fromBytes(byte b0, byte b1) {
- return (short) ((b1 & 0xFF) << 8 |
- (b0 & 0xFF) << 0);
+ @SuppressWarnings("fallthrough")
+ public static UShort from(byte[] bytes) {
+ short number = 0;
+
+ switch (bytes.length) {
+ case 2: number |= (bytes[1] & 0xFF) << 8;
+ case 1: number |= (bytes[0] & 0xFF) << 0;
+ }
+
+ return UShort.valueOf(number);
+ }
+
+ public static UShort from(byte b0, byte b1) {
+ return UShort.valueOf((short)
+ ((b1 & 0xFF) << 8 |
+ (b0 & 0xFF) << 0));
}
- public static final byte[] toBytes(short x) {
- return new byte[] {(byte) (x >> 0),
- (byte) (x >> 8)
+ public static byte[] toBytes(UShort x) {
+ int num = x.intValue();
+
+ return new byte[] {(byte) (num & 0x00FF >> 0),
+ (byte) ((num & 0xFF00) >> 8)
};
}
- public static final int fromBytes(ByteBuffer buff) {
- return fromBytes(buff.get(), buff.get());
+ public static UShort from(ByteBuffer buff) {
+ return from(buff.get(), buff.get());
+ }
+
+ public static UShort from(InputStream inputStream) throws IOException {
+ byte[] b = new byte[2];
+ if (inputStream.read(b) != 2) {
+ throw new EOFException();
+ }
+
+ return from(b[0], b[1]);
}
}
/** INT to and from bytes */
public static class Int_ {
@SuppressWarnings("fallthrough")
- public static final int fromBytes(byte[] bytes) {
+ public static int from(byte[] bytes, int offset, int bytenum) {
int number = 0;
- switch (bytes.length) {
- case 4: number += (bytes[3] & 0xFF) << 24;
- case 3: number += (bytes[2] & 0xFF) << 16;
- case 2: number += (bytes[1] & 0xFF) << 8;
- case 1: number += (bytes[0] & 0xFF) << 0;
+ switch (bytenum) {
+ case 4: number |= (bytes[offset+3] & 0xFF) << 24;
+ case 3: number |= (bytes[offset+2] & 0xFF) << 16;
+ case 2: number |= (bytes[offset+1] & 0xFF) << 8;
+ case 1: number |= (bytes[offset+0] & 0xFF) << 0;
}
return number;
}
- public static final int fromBytes(byte b0, byte b1, byte b2, byte b3) {
+ @SuppressWarnings("fallthrough")
+ public static int from(byte[] bytes) {
+ int number = 0;
+
+ switch (bytes.length) {
+ case 4: number |= (bytes[3] & 0xFF) << 24;
+ case 3: number |= (bytes[2] & 0xFF) << 16;
+ case 2: number |= (bytes[1] & 0xFF) << 8;
+ case 1: number |= (bytes[0] & 0xFF) << 0;
+ }
+
+ return number;
+ }
+
+ public static int from(byte b0, byte b1, byte b2, byte b3) {
return (b3 & 0xFF) << 24 |
(b2 & 0xFF) << 16 |
(b1 & 0xFF) << 8 |
(b0 & 0xFF) << 0;
}
- public static final byte[] toBytes(int x) {
+ public static byte[] toBytes(int x) {
return new byte[] {(byte) (x >> 0),
(byte) (x >> 8),
(byte) (x >> 16),
@@ -191,83 +289,122 @@ public class LittleEndian {
} ;
}
- public static final int fromBytes(ByteBuffer buff) {
- return fromBytes(buff.get(), buff.get(), buff.get(), buff.get());
+ public static int from(ByteBuffer buff) {
+ return from(buff.get(), buff.get(), buff.get(), buff.get());
+ }
+
+ public static int from(InputStream inputStream) throws IOException {
+ byte[] b = new byte[4];
+ if (inputStream.read(b) != 4) {
+ throw new EOFException();
+ }
+
+ return from(b[0], b[1], b[2], b[3]);
}
}
- /** INT to and from bytes */
+ /** UNSIGNED INT to and from bytes */
public static class UInt_ {
@SuppressWarnings("fallthrough")
- public static final int fromBytes(byte[] bytes) {
- int number = 0;
-
- switch (bytes.length) {
- case 4: number += (bytes[3] & 0xFF) << 24;
- case 3: number += (bytes[2] & 0xFF) << 16;
- case 2: number += (bytes[1] & 0xFF) << 8;
- case 1: number += (bytes[0] & 0xFF) << 0;
- }
-
- return number;
- }
-
- @SuppressWarnings("fallthrough")
- public static int fromBytes(byte[] bytes, int offset, int bytenum) {
+ public static UInteger from(byte[] bytes, int offset, int bytenum) {
int number = 0;
switch (bytenum) {
- case 4: number += (bytes[offset+3] & 0xFF) << 24;
- case 3: number += (bytes[offset+2] & 0xFF) << 16;
- case 2: number += (bytes[offset+1] & 0xFF) << 8;
- case 1: number += (bytes[offset+0] & 0xFF) << 0;
+ case 4: number |= (bytes[offset+3] & 0xFF) << 24;
+ case 3: number |= (bytes[offset+2] & 0xFF) << 16;
+ case 2: number |= (bytes[offset+1] & 0xFF) << 8;
+ case 1: number |= (bytes[offset+0] & 0xFF) << 0;
}
- return number;
+ return UInteger.valueOf(number);
}
- public static final int fromBytes(byte b0, byte b1, byte b2, byte b3) {
- return (b3 & 0xFF) << 24 |
- (b2 & 0xFF) << 16 |
- (b1 & 0xFF) << 8 |
- (b0 & 0xFF) << 0;
+ @SuppressWarnings("fallthrough")
+ public static UInteger from(byte[] bytes) {
+ int number = 0;
+
+ switch (bytes.length) {
+ case 4: number |= (bytes[3] & 0xFF) << 24;
+ case 3: number |= (bytes[2] & 0xFF) << 16;
+ case 2: number |= (bytes[1] & 0xFF) << 8;
+ case 1: number |= (bytes[0] & 0xFF) << 0;
+ }
+
+ return UInteger.valueOf(number);
}
- public static final byte[] toBytes(int x) {
- return new byte[] {(byte) (x >> 0),
- (byte) (x >> 8),
- (byte) (x >> 16),
- (byte) (x >> 24)
- } ;
+ public static UInteger from(byte b0, byte b1, byte b2, byte b3) {
+ int number = (b3 & 0xFF) << 24 |
+ (b2 & 0xFF) << 16 |
+ (b1 & 0xFF) << 8 |
+ (b0 & 0xFF) << 0;
+
+ return UInteger.valueOf(number);
}
- public static final int fromBytes(ByteBuffer buff) {
- return fromBytes(buff.get(), buff.get(), buff.get(), buff.get());
+ public static byte[] toBytes(UInteger x) {
+ long num = x.longValue();
+
+ return new byte[] {(byte) (num & 0x000000FFL >> 0),
+ (byte) ((num & 0x0000FF00L) >> 8),
+ (byte) ((num & 0x00FF0000L) >> 16),
+ (byte) ((num & 0xFF000000L) >> 24)
+ };
+ }
+
+ public static UInteger from(ByteBuffer buff) {
+ return from(buff.get(), buff.get(), buff.get(), buff.get());
+ }
+
+ public static UInteger from(InputStream inputStream) throws IOException {
+ byte[] b = new byte[4];
+ if (inputStream.read(b) != 4) {
+ throw new EOFException();
+ }
+
+ return from(b[0], b[1], b[2], b[3]);
}
}
/** LONG to and from bytes */
public static class Long_ {
-
@SuppressWarnings("fallthrough")
- public static final long fromBytes(byte[] bytes) {
- long number = 0L;
+ public static long from(byte[] bytes, int offset, int bytenum) {
+ long number = 0;
- switch (bytes.length) {
- case 8: number += (long) (bytes[7] & 0xFF) << 56;
- case 7: number += (long) (bytes[6] & 0xFF) << 48;
- case 6: number += (long) (bytes[5] & 0xFF) << 40;
- case 5: number += (long) (bytes[4] & 0xFF) << 32;
- case 4: number += (long) (bytes[3] & 0xFF) << 24;
- case 3: number += (long) (bytes[2] & 0xFF) << 16;
- case 2: number += (long) (bytes[1] & 0xFF) << 8;
- case 1: number += (long) (bytes[0] & 0xFF) << 0;
+ switch (bytenum) {
+ case 8: number |= (long) (bytes[offset+7] & 0xFF) << 56;
+ case 7: number |= (long) (bytes[offset+6] & 0xFF) << 48;
+ case 6: number |= (long) (bytes[offset+5] & 0xFF) << 40;
+ case 5: number |= (long) (bytes[offset+4] & 0xFF) << 32;
+ case 4: number |= (long) (bytes[offset+3] & 0xFF) << 24;
+ case 3: number |= (long) (bytes[offset+2] & 0xFF) << 16;
+ case 2: number |= (long) (bytes[offset+1] & 0xFF) << 8;
+ case 1: number |= (long) (bytes[offset+0] & 0xFF) << 0;
}
return number;
}
- public static final long fromBytes(byte b0, byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7) {
+ @SuppressWarnings("fallthrough")
+ public static long from(byte[] bytes) {
+ long number = 0L;
+
+ switch (bytes.length) {
+ case 8: number |= (long) (bytes[7] & 0xFF) << 56;
+ case 7: number |= (long) (bytes[6] & 0xFF) << 48;
+ case 6: number |= (long) (bytes[5] & 0xFF) << 40;
+ case 5: number |= (long) (bytes[4] & 0xFF) << 32;
+ case 4: number |= (long) (bytes[3] & 0xFF) << 24;
+ case 3: number |= (long) (bytes[2] & 0xFF) << 16;
+ case 2: number |= (long) (bytes[1] & 0xFF) << 8;
+ case 1: number |= (long) (bytes[0] & 0xFF) << 0;
+ }
+
+ return number;
+ }
+
+ public static long from(byte b0, byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7) {
return (long) (b7 & 0xFF) << 56 |
(long) (b6 & 0xFF) << 48 |
(long) (b5 & 0xFF) << 40 |
@@ -278,7 +415,7 @@ public class LittleEndian {
(long) (b0 & 0xFF) << 0;
}
- public static final byte[] toBytes (long x) {
+ public static byte[] toBytes (long x) {
return new byte[] {(byte) (x >> 0),
(byte) (x >> 8),
(byte) (x >> 16),
@@ -290,74 +427,83 @@ public class LittleEndian {
};
}
- public static final long fromBytes(ByteBuffer buff) {
- return fromBytes(buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get());
+ public static long from(ByteBuffer buff) {
+ return from(buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get());
+ }
+
+ public static long from(InputStream inputStream) throws IOException {
+ byte[] b = new byte[8];
+ if (inputStream.read(b) != 8) {
+ throw new EOFException();
+ }
+
+ return from(b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
}
}
- /** LONG to and from bytes */
+ /** UNSIGNED LONG to and from bytes */
public static class ULong_ {
@SuppressWarnings("fallthrough")
- public static int fromBytes(byte[] bytes, int offset, int bytenum) {
- int number = 0;
+ public static ULong from(byte[] bytes, int offset, int bytenum) {
+ long number = 0;
switch (bytenum) {
- case 8: number += (long) (bytes[offset+7] & 0xFF) << 56;
- case 7: number += (long) (bytes[offset+6] & 0xFF) << 48;
- case 6: number += (long) (bytes[offset+5] & 0xFF) << 40;
- case 5: number += (long) (bytes[offset+4] & 0xFF) << 32;
- case 4: number += (long) (bytes[offset+3] & 0xFF) << 24;
- case 3: number += (long) (bytes[offset+2] & 0xFF) << 16;
- case 2: number += (long) (bytes[offset+1] & 0xFF) << 8;
- case 1: number += (long) (bytes[offset+0] & 0xFF) << 0;
+ case 8: number |= (long) (bytes[offset+7] & 0xFF) << 56;
+ case 7: number |= (long) (bytes[offset+6] & 0xFF) << 48;
+ case 6: number |= (long) (bytes[offset+5] & 0xFF) << 40;
+ case 5: number |= (long) (bytes[offset+4] & 0xFF) << 32;
+ case 4: number |= (long) (bytes[offset+3] & 0xFF) << 24;
+ case 3: number |= (long) (bytes[offset+2] & 0xFF) << 16;
+ case 2: number |= (long) (bytes[offset+1] & 0xFF) << 8;
+ case 1: number |= (long) (bytes[offset+0] & 0xFF) << 0;
}
- return number;
+ return ULong.valueOf(number);
}
- @SuppressWarnings("fallthrough")
- public static final long fromBytes(byte[] bytes) {
- long number = 0L;
+ public static ULong from(byte[] bytes) {
+ BigInteger ulong = new BigInteger(1, bytes);
+ return ULong.valueOf(ulong);
+ }
- switch (bytes.length) {
- case 8: number += (long) (bytes[7] & 0xFF) << 56;
- case 7: number += (long) (bytes[6] & 0xFF) << 48;
- case 6: number += (long) (bytes[5] & 0xFF) << 40;
- case 5: number += (long) (bytes[4] & 0xFF) << 32;
- case 4: number += (long) (bytes[3] & 0xFF) << 24;
- case 3: number += (long) (bytes[2] & 0xFF) << 16;
- case 2: number += (long) (bytes[1] & 0xFF) << 8;
- case 1: number += (long) (bytes[0] & 0xFF) << 0;
+ public static ULong from(byte b0, byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7) {
+ byte[] bytes = new byte[] {b7, b6, b5, b4, b3, b2, b1, b0};
+ BigInteger ulong = new BigInteger(1, bytes);
+ return ULong.valueOf(ulong);
+ }
+
+ public static byte[] toBytes (ULong x) {
+ byte[] bytes = new byte[8];
+ int offset = 0;
+
+ byte temp_byte[] = x.toBigInteger().toByteArray();
+ int array_count = temp_byte.length-1;
+
+ for (int i=7;i>=0;i--) {
+ if (array_count >= 0) {
+ bytes[offset] = temp_byte[array_count];
+ } else {
+ bytes[offset] = (byte)00;
+ }
+
+ offset++;
+ array_count--;
}
- return number;
+ return bytes;
}
- public static final long fromBytes(byte b0, byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7) {
- return (long) (b7 & 0xFF) << 56 |
- (long) (b6 & 0xFF) << 48 |
- (long) (b5 & 0xFF) << 40 |
- (long) (b4 & 0xFF) << 32 |
- (long) (b3 & 0xFF) << 24 |
- (long) (b2 & 0xFF) << 16 |
- (long) (b1 & 0xFF) << 8 |
- (long) (b0 & 0xFF) << 0;
+ public static ULong from(ByteBuffer buff) {
+ return from(buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get());
}
- public static final byte[] toBytes (long x) {
- return new byte[] {(byte) (x >> 0),
- (byte) (x >> 8),
- (byte) (x >> 16),
- (byte) (x >> 24),
- (byte) (x >> 32),
- (byte) (x >> 40),
- (byte) (x >> 48),
- (byte) (x >> 56),
- };
- }
+ public static ULong from(InputStream inputStream) throws IOException {
+ byte[] b = new byte[8];
+ if (inputStream.read(b) != 8) {
+ throw new EOFException();
+ }
- public static final long fromBytes(ByteBuffer buff) {
- return fromBytes(buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get(), buff.get());
+ return from(b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
}
}
}
diff --git a/Dorkbox-Util/src/dorkbox/util/bytes/UByte.java b/Dorkbox-Util/src/dorkbox/util/bytes/UByte.java
new file mode 100644
index 0000000..c78ecd0
--- /dev/null
+++ b/Dorkbox-Util/src/dorkbox/util/bytes/UByte.java
@@ -0,0 +1,304 @@
+/**
+ * Copyright (c) 2011-2013, Lukas Eder, lukas.eder@gmail.com
+ * All rights reserved.
+ *
+ * This software is licensed to you under the Apache License, Version 2.0
+ * (the "License"); You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * . Neither the name "jOOU" nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package dorkbox.util.bytes;
+
+import java.io.ObjectStreamException;
+import java.math.BigInteger;
+
+/**
+ * The
+ * It essentially contains factory methods for unsigned number wrappers. In
+ * future versions, it will also contain some arithmetic methods, handling
+ * regular arithmetic and bitwise operations
+ *
+ * @author Lukas Eder
+ */
+public final class Unsigned {
+
+ /**
+ * Create an unsigned byte
type
+ *
+ * @author Lukas Eder
+ * @author Ed Schaller
+ */
+public final class UByte extends UNumber implements Comparableunsigned byte
can
+ * have, 0.
+ */
+ public static final short MIN_VALUE = 0x00;
+
+ /**
+ * A constant holding the maximum value an unsigned byte
can
+ * have, 28-1.
+ */
+ public static final short MAX_VALUE = 0xff;
+
+ /**
+ * The value modelling the content of this unsigned byte
+ */
+ private final short value;
+
+ /**
+ * Generate a cached value for each byte value.
+ *
+ * @return Array of cached values for UByte.
+ */
+ private static final UByte[] mkValues() {
+ UByte[] ret = new UByte[256];
+
+ for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
+ ret[i & MAX_VALUE] = new UByte((byte) i);
+ }
+ return ret;
+ }
+
+ /**
+ * Get an instance of an unsigned byte
+ *
+ * @throws NumberFormatException If value
does not contain a
+ * parsable unsigned byte
.
+ */
+ public static UByte valueOf(String value) throws NumberFormatException {
+ return valueOfUnchecked(rangeCheck(Short.parseShort(value)));
+ }
+
+ /**
+ * Get an instance of an unsigned byte
by masking it with
+ * 0xFF
i.e. (byte) -1
becomes
+ * (ubyte) 255
+ */
+ public static UByte valueOf(byte value) {
+ return valueOfUnchecked((short) (value & MAX_VALUE));
+ }
+
+ /**
+ * Get the value of a short without checking the value.
+ */
+ private static UByte valueOfUnchecked(short value) throws NumberFormatException {
+ return VALUES[value & MAX_VALUE];
+ }
+
+ /**
+ * Get an instance of an unsigned byte
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned byte
+ */
+ public static UByte valueOf(short value) throws NumberFormatException {
+ return valueOfUnchecked(rangeCheck(value));
+ }
+
+ /**
+ * Get an instance of an unsigned byte
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned byte
+ */
+ public static UByte valueOf(int value) throws NumberFormatException {
+ return valueOfUnchecked(rangeCheck(value));
+ }
+
+ /**
+ * Get an instance of an unsigned byte
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned byte
+ */
+ public static UByte valueOf(long value) throws NumberFormatException {
+ return valueOfUnchecked(rangeCheck(value));
+ }
+
+ /**
+ * Create an unsigned byte
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned byte
+ */
+ private UByte(long value) throws NumberFormatException {
+ this.value = rangeCheck(value);
+ }
+
+ /**
+ * Create an unsigned byte
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned byte
+ */
+ private UByte(int value) throws NumberFormatException {
+ this.value = rangeCheck(value);
+ }
+
+ /**
+ * Create an unsigned byte
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned byte
+ */
+ private UByte(short value) throws NumberFormatException {
+ this.value = rangeCheck(value);
+ }
+
+ /**
+ * Create an unsigned byte
by masking it with 0xFF
+ * i.e. (byte) -1
becomes (ubyte) 255
+ */
+ private UByte(byte value) {
+ this.value = (short) (value & MAX_VALUE);
+ }
+
+ /**
+ * Create an unsigned byte
+ *
+ * @throws NumberFormatException If value
does not contain a
+ * parsable unsigned byte
.
+ */
+ private UByte(String value) throws NumberFormatException {
+ this.value = rangeCheck(Short.parseShort(value));
+ }
+
+ /**
+ * Throw exception if value out of range (short version)
+ *
+ * @param value Value to check
+ * @return value if it is in range
+ * @throws NumberFormatException if value is out of range
+ */
+ private static short rangeCheck(short value) throws NumberFormatException {
+ if (value < MIN_VALUE || value > MAX_VALUE) {
+ throw new NumberFormatException("Value is out of range : " + value);
+ }
+ return value;
+ }
+
+ /**
+ * Throw exception if value out of range (int version)
+ *
+ * @param value Value to check
+ * @return value if it is in range
+ * @throws NumberFormatException if value is out of range
+ */
+ private static short rangeCheck(int value) throws NumberFormatException {
+ if (value < MIN_VALUE || value > MAX_VALUE) {
+ throw new NumberFormatException("Value is out of range : " + value);
+ }
+ return (short) value;
+ }
+
+ /**
+ * Throw exception if value out of range (long version)
+ *
+ * @param value Value to check
+ * @return value if it is in range
+ * @throws NumberFormatException if value is out of range
+ */
+ private static short rangeCheck(long value) throws NumberFormatException {
+ if (value < MIN_VALUE || value > MAX_VALUE) {
+ throw new NumberFormatException("Value is out of range : " + value);
+ }
+ return (short) value;
+ }
+
+ /**
+ * Replace version read through deserialization with cached version. Note
+ * that this does not use the {@link #valueOfUnchecked(short)} as we have no
+ * guarantee that the value from the stream is valid.
+ *
+ * @return cached instance of this object's value
+ * @throws ObjectStreamException
+ */
+ private Object readResolve() throws ObjectStreamException {
+ return valueOf(this.value);
+ }
+
+ @Override
+ public int intValue() {
+ return this.value;
+ }
+
+ @Override
+ public long longValue() {
+ return this.value;
+ }
+
+ @Override
+ public float floatValue() {
+ return this.value;
+ }
+
+ @Override
+ public double doubleValue() {
+ return this.value;
+ }
+
+ @Override
+ public int hashCode() {
+ return Short.valueOf(this.value).hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof UByte) {
+ return this.value == ((UByte) obj).value;
+ }
+
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return Short.valueOf(this.value).toString();
+ }
+
+ @Override
+ public String toHexString() {
+ return Integer.toHexString(this.value);
+ }
+
+ @Override
+ public int compareTo(UByte o) {
+ return this.value < o.value ? -1 : this.value == o.value ? 0 : 1;
+ }
+
+ @Override
+ public BigInteger toBigInteger() {
+ return BigInteger.valueOf(this.value);
+ }
+}
\ No newline at end of file
diff --git a/Dorkbox-Util/src/dorkbox/util/bytes/UInteger.java b/Dorkbox-Util/src/dorkbox/util/bytes/UInteger.java
new file mode 100644
index 0000000..75e29cc
--- /dev/null
+++ b/Dorkbox-Util/src/dorkbox/util/bytes/UInteger.java
@@ -0,0 +1,333 @@
+/**
+ * Copyright (c) 2011-2013, Lukas Eder, lukas.eder@gmail.com
+ * All rights reserved.
+ *
+ * This software is licensed to you under the Apache License, Version 2.0
+ * (the "License"); You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * . Neither the name "jOOU" nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package dorkbox.util.bytes;
+
+import java.io.ObjectStreamException;
+
+/**
+ * The unsigned int
type
+ *
+ * @author Lukas Eder
+ * @author Ed Schaller
+ */
+public final class UInteger extends UNumber implements Comparableunsigned int
can
+ * have, 0.
+ */
+ public static final long MIN_VALUE = 0x00000000;
+
+ /**
+ * A constant holding the maximum value an unsigned int
can
+ * have, 232-1.
+ */
+ public static final long MAX_VALUE = 0xffffffffL;
+
+ /**
+ * The value modelling the content of this unsigned int
+ */
+ private final long value;
+
+ /**
+ * Figure out the size of the precache.
+ *
+ * @return The parsed value of the system property
+ * {@link #PRECACHE_PROPERTY} or {@link #DEFAULT_PRECACHE_SIZE} if
+ * the property is not set, not a number or retrieving results in a
+ * {@link SecurityException}. If the parsed value is zero or
+ * negative no cache will be created. If the value is larger than
+ * {@link Integer#MAX_VALUE} then Integer#MAX_VALUE will be used.
+ */
+ private static final int getPrecacheSize() {
+ String prop = null;
+ long propParsed;
+
+ try {
+ prop = System.getProperty(PRECACHE_PROPERTY);
+ }
+ catch (SecurityException e) {
+ // security manager stopped us so use default
+ // FIXME: should we log this somewhere?
+ return DEFAULT_PRECACHE_SIZE;
+ }
+ if (prop == null) {
+ return DEFAULT_PRECACHE_SIZE;
+ }
+ if (prop.length() <= 0) {
+ // empty value
+ // FIXME: should we log this somewhere?
+ return DEFAULT_PRECACHE_SIZE;
+ }
+ try {
+ propParsed = Long.parseLong(prop);
+ }
+ catch (NumberFormatException e) {
+ // not a valid number
+ // FIXME: should we log this somewhere?
+ return DEFAULT_PRECACHE_SIZE;
+ }
+ // treat negative value as no cache...
+ if (propParsed < 0) {
+ return 0;
+ }
+ if (propParsed > Integer.MAX_VALUE) {
+ // FIXME: should we log this somewhere
+ return Integer.MAX_VALUE;
+ }
+ return (int) propParsed;
+ }
+
+ /**
+ * Generate a cached value for initial unsigned integer values.
+ *
+ * @return Array of cached values for UInteger
+ */
+ private static final UInteger[] mkValues() {
+ int precacheSize = getPrecacheSize();
+ UInteger[] ret;
+
+ if (precacheSize <= 0) {
+ return null;
+ }
+ ret = new UInteger[precacheSize];
+ for (int i = 0; i < precacheSize; i++) {
+ ret[i] = new UInteger(i);
+ }
+ return ret;
+ }
+
+ /**
+ * Unchecked internal constructor. This serves two purposes: first it allows
+ * {@link #UInteger(long)} to stay deprecated without warnings and second
+ * constructor without unnecessary value checks.
+ *
+ * @param value The value to wrap
+ * @param unused Unused paramater to distinguish between this and the
+ * deprecated public constructor.
+ */
+ private UInteger(long value, boolean unused) {
+ this.value = value;
+ }
+
+ /**
+ * Retrieve a cached value.
+ *
+ * @param value Cached value to retrieve
+ * @return Cached value if one exists. Null otherwise.
+ */
+ private static UInteger getCached(long value) {
+ if (VALUES != null && value < VALUES.length) {
+ return VALUES[(int) value];
+ }
+ return null;
+ }
+
+ /**
+ * Get the value of a long without checking the value.
+ */
+ private static UInteger valueOfUnchecked(long value) {
+ UInteger cached;
+
+ if ((cached = getCached(value)) != null) {
+ return cached;
+ }
+ return new UInteger(value, true);
+ }
+
+ /**
+ * Create an unsigned int
+ *
+ * @throws NumberFormatException If value
does not contain a
+ * parsable unsigned int
.
+ */
+ public static UInteger valueOf(String value) throws NumberFormatException {
+ return valueOfUnchecked(rangeCheck(Long.parseLong(value)));
+ }
+
+ /**
+ * Create an unsigned int
by masking it with
+ * 0xFFFFFFFF
i.e. (int) -1
becomes
+ * (uint) 4294967295
+ */
+ public static UInteger valueOf(int value) {
+ return valueOfUnchecked(value & MAX_VALUE);
+ }
+
+ /**
+ * Create an unsigned int
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned byte
+ */
+ public static UInteger valueOf(long value) throws NumberFormatException {
+ return valueOfUnchecked(rangeCheck(value));
+ }
+
+ /**
+ * Create an unsigned int
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned int
+ */
+ private UInteger(long value) throws NumberFormatException {
+ this.value = rangeCheck(value);
+ }
+
+ /**
+ * Create an unsigned int
by masking it with
+ * 0xFFFFFFFF
i.e. (int) -1
becomes
+ * (uint) 4294967295
+ */
+ private UInteger(int value) {
+ this.value = value & MAX_VALUE;
+ }
+
+ /**
+ * Create an unsigned int
+ *
+ * @throws NumberFormatException If value
does not contain a
+ * parsable unsigned int
.
+ */
+ private UInteger(String value) throws NumberFormatException {
+ this.value = rangeCheck(Long.parseLong(value));
+ }
+
+ /**
+ * Throw exception if value out of range (long version)
+ *
+ * @param value Value to check
+ * @return value if it is in range
+ * @throws NumberFormatException if value is out of range
+ */
+ private static long rangeCheck(long value) throws NumberFormatException {
+ if (value < MIN_VALUE || value > MAX_VALUE) {
+ throw new NumberFormatException("Value is out of range : " + value);
+ }
+ return value;
+ }
+
+ /**
+ * Replace version read through deserialization with cached version.
+ *
+ * @return cached instance of this object's value if one exists, otherwise
+ * this object
+ * @throws ObjectStreamException
+ */
+ private Object readResolve() throws ObjectStreamException {
+ UInteger cached;
+
+ // the value read could be invalid so check it
+ rangeCheck(this.value);
+ if ((cached = getCached(this.value)) != null) {
+ return cached;
+ }
+ return this;
+ }
+
+ @Override
+ public int intValue() {
+ return (int) this.value;
+ }
+
+ @Override
+ public long longValue() {
+ return this.value;
+ }
+
+ @Override
+ public float floatValue() {
+ return this.value;
+ }
+
+ @Override
+ public double doubleValue() {
+ return this.value;
+ }
+
+ @Override
+ public int hashCode() {
+ return Long.valueOf(this.value).hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof UInteger) {
+ return this.value == ((UInteger) obj).value;
+ }
+
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return Long.valueOf(this.value).toString();
+ }
+
+ public String toHexString() {
+ return Long.toHexString(this.value);
+ }
+
+ @Override
+ public int compareTo(UInteger o) {
+ return this.value < o.value ? -1 : this.value == o.value ? 0 : 1;
+ }
+}
\ No newline at end of file
diff --git a/Dorkbox-Util/src/dorkbox/util/bytes/ULong.java b/Dorkbox-Util/src/dorkbox/util/bytes/ULong.java
new file mode 100644
index 0000000..ff19636
--- /dev/null
+++ b/Dorkbox-Util/src/dorkbox/util/bytes/ULong.java
@@ -0,0 +1,203 @@
+/**
+ * Copyright (c) 2011-2013, Lukas Eder, lukas.eder@gmail.com
+ * All rights reserved.
+ *
+ * This software is licensed to you under the Apache License, Version 2.0
+ * (the "License"); You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * . Neither the name "jOOU" nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package dorkbox.util.bytes;
+
+import java.math.BigInteger;
+
+/**
+ * The unsigned long
type
+ *
+ * @author Lukas Eder
+ */
+public final class ULong extends UNumber implements Comparableunsigned long
can
+ * have, 0.
+ */
+ public static final BigInteger MIN_VALUE = BigInteger.ZERO;
+
+ /**
+ * A constant holding the maximum value an unsigned long
can
+ * have, 264-1.
+ */
+ public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615");
+
+ /**
+ * A constant holding the maximum value + 1 an signed long
can
+ * have, 263.
+ */
+ public static final BigInteger MAX_VALUE_LONG = new BigInteger("9223372036854775808");
+
+ /**
+ * The value modelling the content of this unsigned long
+ */
+ private final BigInteger value;
+
+ /**
+ * Create an unsigned long
+ *
+ * @throws NumberFormatException If value
does not contain a
+ * parsable unsigned long
.
+ */
+ public static ULong valueOf(String value) throws NumberFormatException {
+ return new ULong(value);
+ }
+
+ /**
+ * Create an unsigned long
by masking it with
+ * 0xFFFFFFFFFFFFFFFF
i.e. (long) -1
becomes
+ * (uint) 18446744073709551615
+ */
+ public static ULong valueOf(long value) {
+ return new ULong(value);
+ }
+
+ /**
+ * Create an unsigned long
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned long
+ */
+ public static ULong valueOf(BigInteger value) throws NumberFormatException {
+ return new ULong(value);
+ }
+
+ /**
+ * Create an unsigned long
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned long
+ */
+ private ULong(BigInteger value) throws NumberFormatException {
+ this.value = value;
+ rangeCheck();
+ }
+
+ /**
+ * Create an unsigned long
by masking it with
+ * 0xFFFFFFFFFFFFFFFF
i.e. (long) -1
becomes
+ * (uint) 18446744073709551615
+ */
+ private ULong(long value) {
+ if (value >= 0) {
+ this.value = BigInteger.valueOf(value);
+ }
+ else {
+ this.value = BigInteger.valueOf(value & Long.MAX_VALUE).add(MAX_VALUE_LONG);
+ }
+ }
+
+ /**
+ * Create an unsigned long
+ *
+ * @throws NumberFormatException If value
does not contain a
+ * parsable unsigned long
.
+ */
+ private ULong(String value) throws NumberFormatException {
+ this.value = new BigInteger(value);
+ rangeCheck();
+ }
+
+ private void rangeCheck() throws NumberFormatException {
+ if (this.value.compareTo(MIN_VALUE) < 0 || this.value.compareTo(MAX_VALUE) > 0) {
+ throw new NumberFormatException("Value is out of range : " + this.value);
+ }
+ }
+
+ @Override
+ public int intValue() {
+ return this.value.intValue();
+ }
+
+ @Override
+ public long longValue() {
+ return this.value.longValue();
+ }
+
+ @Override
+ public float floatValue() {
+ return this.value.floatValue();
+ }
+
+ @Override
+ public double doubleValue() {
+ return this.value.doubleValue();
+ }
+
+ @Override
+ public int hashCode() {
+ return this.value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ULong) {
+ return this.value.equals(((ULong) obj).value);
+ }
+
+ return false;
+ }
+
+ /**
+ * Get this number as a {@link BigInteger}. This is a convenience method for
+ * calling new BigInteger(toString())
+ */
+ @Override
+ public BigInteger toBigInteger() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ return this.value.toString();
+ }
+
+ @Override
+ public String toHexString() {
+ return this.value.toString(16);
+ }
+
+ @Override
+ public int compareTo(ULong o) {
+ return this.value.compareTo(o.value);
+ }
+}
\ No newline at end of file
diff --git a/Dorkbox-Util/src/dorkbox/util/bytes/UNumber.java b/Dorkbox-Util/src/dorkbox/util/bytes/UNumber.java
new file mode 100644
index 0000000..d0ea59b
--- /dev/null
+++ b/Dorkbox-Util/src/dorkbox/util/bytes/UNumber.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2011-2013, Lukas Eder, lukas.eder@gmail.com
+ * All rights reserved.
+ *
+ * This software is licensed to you under the Apache License, Version 2.0
+ * (the "License"); You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * . Neither the name "jOOU" nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package dorkbox.util.bytes;
+
+import java.math.BigInteger;
+
+/**
+ * A base type for unsigned numbers.
+ *
+ * @author Lukas Eder
+ */
+public abstract class UNumber extends Number {
+
+ /**
+ * Generated UID
+ */
+ private static final long serialVersionUID = -7666221938815339843L;
+
+ /**
+ * Converts this number to a hex string representation
+ */
+ public abstract String toHexString();
+
+ /**
+ * Get this number as a {@link BigInteger}. This is a convenience method for
+ * calling new BigInteger(toString())
+ */
+ public BigInteger toBigInteger() {
+ return new BigInteger(toString());
+ }
+}
\ No newline at end of file
diff --git a/Dorkbox-Util/src/dorkbox/util/bytes/UShort.java b/Dorkbox-Util/src/dorkbox/util/bytes/UShort.java
new file mode 100644
index 0000000..4175cbd
--- /dev/null
+++ b/Dorkbox-Util/src/dorkbox/util/bytes/UShort.java
@@ -0,0 +1,181 @@
+/**
+ * Copyright (c) 2011-2013, Lukas Eder, lukas.eder@gmail.com
+ * All rights reserved.
+ *
+ * This software is licensed to you under the Apache License, Version 2.0
+ * (the "License"); You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * . Neither the name "jOOU" nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package dorkbox.util.bytes;
+
+/**
+ * The unsigned short
type
+ *
+ * @author Lukas Eder
+ */
+public final class UShort extends UNumber implements Comparableunsigned short
can
+ * have, 0.
+ */
+ public static final int MIN_VALUE = 0x0000;
+
+ /**
+ * A constant holding the maximum value an unsigned short
can
+ * have, 216-1.
+ */
+ public static final int MAX_VALUE = 0xffff;
+
+ /**
+ * The value modelling the content of this unsigned short
+ */
+ private final int value;
+
+ /**
+ * Create an unsigned short
+ *
+ * @throws NumberFormatException If value
does not contain a
+ * parsable unsigned short
.
+ */
+ public static UShort valueOf(String value) throws NumberFormatException {
+ return new UShort(value);
+ }
+
+ /**
+ * Create an unsigned short
by masking it with
+ * 0xFFFF
i.e. (short) -1
becomes
+ * (ushort) 65535
+ */
+ public static UShort valueOf(short value) {
+ return new UShort(value);
+ }
+
+ /**
+ * Create an unsigned short
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned short
+ */
+ public static UShort valueOf(int value) throws NumberFormatException {
+ return new UShort(value);
+ }
+
+ /**
+ * Create an unsigned short
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned short
+ */
+ private UShort(int value) throws NumberFormatException {
+ this.value = value;
+ rangeCheck();
+ }
+
+ /**
+ * Create an unsigned short
by masking it with
+ * 0xFFFF
i.e. (short) -1
becomes
+ * (ushort) 65535
+ */
+ private UShort(short value) {
+ this.value = value & MAX_VALUE;
+ }
+
+ /**
+ * Create an unsigned short
+ *
+ * @throws NumberFormatException If value
does not contain a
+ * parsable unsigned short
.
+ */
+ private UShort(String value) throws NumberFormatException {
+ this.value = Integer.parseInt(value);
+ rangeCheck();
+ }
+
+ private void rangeCheck() throws NumberFormatException {
+ if (this.value < MIN_VALUE || this.value > MAX_VALUE) {
+ throw new NumberFormatException("Value is out of range : " + this.value);
+ }
+ }
+
+ @Override
+ public int intValue() {
+ return this.value;
+ }
+
+ @Override
+ public long longValue() {
+ return this.value;
+ }
+
+ @Override
+ public float floatValue() {
+ return this.value;
+ }
+
+ @Override
+ public double doubleValue() {
+ return this.value;
+ }
+
+ @Override
+ public int hashCode() {
+ return Integer.valueOf(this.value).hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof UShort) {
+ return this.value == ((UShort) obj).value;
+ }
+
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return Integer.valueOf(this.value).toString();
+ }
+
+ @Override
+ public String toHexString() {
+ return Integer.toHexString(this.value);
+ }
+
+ @Override
+ public int compareTo(UShort o) {
+ return this.value < o.value ? -1 : this.value == o.value ? 0 : 1;
+ }
+}
\ No newline at end of file
diff --git a/Dorkbox-Util/src/dorkbox/util/bytes/Unsigned.java b/Dorkbox-Util/src/dorkbox/util/bytes/Unsigned.java
new file mode 100644
index 0000000..dbce032
--- /dev/null
+++ b/Dorkbox-Util/src/dorkbox/util/bytes/Unsigned.java
@@ -0,0 +1,208 @@
+/**
+ * Copyright (c) 2011-2013, Lukas Eder, lukas.eder@gmail.com
+ * All rights reserved.
+ *
+ * This software is licensed to you under the Apache License, Version 2.0
+ * (the "License"); You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * . Neither the name "jOOU" nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package dorkbox.util.bytes;
+
+import java.math.BigInteger;
+
+/**
+ * A utility class for static access to unsigned number functionality.
+ * unsigned byte
+ *
+ * @throws NumberFormatException If value
does not contain a
+ * parsable unsigned byte
.
+ * @see UByte#valueOf(String)
+ */
+ public static UByte ubyte(String value) throws NumberFormatException {
+ return value == null ? null : UByte.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned byte
by masking it with 0xFF
+ * i.e. (byte) -1
becomes (ubyte) 255
+ *
+ * @see UByte#valueOf(byte)
+ */
+ public static UByte ubyte(byte value) {
+ return UByte.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned byte
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned byte
+ * @see UByte#valueOf(short)
+ */
+ public static UByte ubyte(short value) throws NumberFormatException {
+ return UByte.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned byte
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned byte
+ * @see UByte#valueOf(short)
+ */
+ public static UByte ubyte(int value) throws NumberFormatException {
+ return UByte.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned byte
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned byte
+ * @see UByte#valueOf(short)
+ */
+ public static UByte ubyte(long value) throws NumberFormatException {
+ return UByte.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned short
+ *
+ * @throws NumberFormatException If value
does not contain a
+ * parsable unsigned short
.
+ * @see UShort#valueOf(String)
+ */
+ public static UShort ushort(String value) throws NumberFormatException {
+ return value == null ? null : UShort.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned short
by masking it with
+ * 0xFFFF
i.e. (short) -1
becomes
+ * (ushort) 65535
+ *
+ * @see UShort#valueOf(short)
+ */
+ public static UShort ushort(short value) {
+ return UShort.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned short
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned short
+ * @see UShort#valueOf(int)
+ */
+ public static UShort ushort(int value) throws NumberFormatException {
+ return UShort.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned int
+ *
+ * @throws NumberFormatException If value
does not contain a
+ * parsable unsigned int
.
+ * @see UInteger#valueOf(String)
+ */
+ public static UInteger uint(String value) throws NumberFormatException {
+ return value == null ? null : UInteger.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned int
by masking it with
+ * 0xFFFFFFFF
i.e. (int) -1
becomes
+ * (uint) 4294967295
+ *
+ * @see UInteger#valueOf(int)
+ */
+ public static UInteger uint(int value) {
+ return UInteger.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned int
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned int
+ * @see UInteger#valueOf(long)
+ */
+ public static UInteger uint(long value) throws NumberFormatException {
+ return UInteger.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned long
+ *
+ * @throws NumberFormatException If value
does not contain a
+ * parsable unsigned long
.
+ * @see ULong#valueOf(String)
+ */
+ public static ULong ulong(String value) throws NumberFormatException {
+ return value == null ? null : ULong.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned long
by masking it with
+ * 0xFFFFFFFFFFFFFFFF
i.e. (long) -1
becomes
+ * (uint) 18446744073709551615
+ *
+ * @see ULong#valueOf(long)
+ */
+ public static ULong ulong(long value) {
+ return ULong.valueOf(value);
+ }
+
+ /**
+ * Create an unsigned long
+ *
+ * @throws NumberFormatException If value
is not in the range
+ * of an unsigned long
+ * @see ULong#valueOf(BigInteger)
+ */
+ public static ULong ulong(BigInteger value) throws NumberFormatException {
+ return ULong.valueOf(value);
+ }
+
+ /**
+ * No instances
+ */
+ private Unsigned() {}
+}
\ No newline at end of file
diff --git a/Dorkbox-Util/test/dorkbox/util/UByteTest.java b/Dorkbox-Util/test/dorkbox/util/UByteTest.java
new file mode 100644
index 0000000..682eb44
--- /dev/null
+++ b/Dorkbox-Util/test/dorkbox/util/UByteTest.java
@@ -0,0 +1,166 @@
+/**
+ * Copyright (c) 2011-2013, Lukas Eder, lukas.eder@gmail.com
+ * All rights reserved.
+ *
+ * This software is licensed to you under the Apache License, Version 2.0
+ * (the "License"); You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * . Neither the name "jOOU" nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package dorkbox.util;
+
+import static dorkbox.util.bytes.Unsigned.ubyte;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.junit.Test;
+
+import dorkbox.util.bytes.UByte;
+
+public class UByteTest {
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testValueOfByte() {
+ for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
+ assertEquals(i & 0xFF, ubyte((byte) i).intValue());
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testValueOfByteCaching() {
+ for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
+ UByte a = ubyte((byte) i);
+ UByte b = ubyte((byte) i);
+ assertTrue(a == b);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testValueOfShort() {
+ for (int i = UByte.MIN_VALUE; i <= UByte.MAX_VALUE; i++) {
+ assertEquals(i & 0xFF, ubyte((short) i).intValue());
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testValueOfShortInvalid() {
+ try {
+ ubyte((short) (UByte.MIN_VALUE - 1));
+ fail();
+ }
+ catch (NumberFormatException e) {}
+ try {
+ ubyte((short) (UByte.MAX_VALUE + 1));
+ fail();
+ }
+ catch (NumberFormatException e) {}
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testValueOfInt() {
+ for (int i = UByte.MIN_VALUE; i <= UByte.MAX_VALUE; i++) {
+ assertEquals(i & 0xFF, ubyte(i).intValue());
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testValueOfIntInvalid() {
+ try {
+ ubyte(UByte.MIN_VALUE - 1);
+ fail();
+ }
+ catch (NumberFormatException e) {}
+ try {
+ ubyte(UByte.MAX_VALUE + 1);
+ fail();
+ }
+ catch (NumberFormatException e) {}
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testValueOfLong() {
+ for (int i = UByte.MIN_VALUE; i <= UByte.MAX_VALUE; i++) {
+ assertEquals(i & 0xFF, ubyte((long) i).intValue());
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testValueOfLongInvalid() {
+ try {
+ ubyte((long) UByte.MIN_VALUE - 1);
+ fail();
+ }
+ catch (NumberFormatException e) {}
+ try {
+ ubyte((long) UByte.MAX_VALUE + 1);
+ fail();
+ }
+ catch (NumberFormatException e) {}
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testSerializeDeserialize() throws ClassNotFoundException, IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ ByteArrayInputStream bais;
+ ObjectInputStream ois;
+ UByte expected = ubyte(42);
+ UByte input = ubyte(42);
+ UByte actual;
+ Object o;
+
+ oos.writeObject(input);
+ oos.close();
+ bais = new ByteArrayInputStream(baos.toByteArray());
+ ois = new ObjectInputStream(bais);
+ o = ois.readObject();
+ if (!(o instanceof UByte)) {
+ fail();
+ }
+ actual = (UByte) o;
+ assertEquals(expected, actual); // same value
+ assertTrue(expected == actual); // identical objects
+ }
+}
\ No newline at end of file
diff --git a/Dorkbox-Util/test/dorkbox/util/UIntegerTest.java b/Dorkbox-Util/test/dorkbox/util/UIntegerTest.java
new file mode 100644
index 0000000..8ed0c1d
--- /dev/null
+++ b/Dorkbox-Util/test/dorkbox/util/UIntegerTest.java
@@ -0,0 +1,149 @@
+/**
+ * Copyright (c) 2011-2013, Lukas Eder, lukas.eder@gmail.com
+ * All rights reserved.
+ *
+ * This software is licensed to you under the Apache License, Version 2.0
+ * (the "License"); You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * . Neither the name "jOOU" nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package dorkbox.util;
+
+import static dorkbox.util.bytes.Unsigned.uint;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.junit.Test;
+
+import dorkbox.util.bytes.UInteger;
+
+public class UIntegerTest {
+ private static final int CACHE_SIZE=256;
+ private static final int NEAR_MISS_OFFSET=4;
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testValueOfLong() {
+ for(long l=01; l<=UInteger.MAX_VALUE; l<<=1) {
+ assertEquals(l , uint(l).longValue());
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testValueOfLongCachingShift() {
+ for(long l=01; l