From 97a8207dd7598847d105949757e85bc8560a85c7 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 18 Dec 2014 20:28:56 +0100 Subject: [PATCH] Added unsigned numbers to java. Added big endian/network byte order utils --- Dorkbox-Util/LICENSE | 7 + .../src/dorkbox/util/bytes/BigEndian.java | 493 ++++++++++++++++++ .../src/dorkbox/util/bytes/LittleEndian.java | 474 +++++++++++------ .../src/dorkbox/util/bytes/UByte.java | 304 +++++++++++ .../src/dorkbox/util/bytes/UInteger.java | 333 ++++++++++++ .../src/dorkbox/util/bytes/ULong.java | 203 ++++++++ .../src/dorkbox/util/bytes/UNumber.java | 64 +++ .../src/dorkbox/util/bytes/UShort.java | 181 +++++++ .../src/dorkbox/util/bytes/Unsigned.java | 208 ++++++++ Dorkbox-Util/test/dorkbox/util/UByteTest.java | 166 ++++++ .../test/dorkbox/util/UIntegerTest.java | 149 ++++++ .../test/dorkbox/util/UNumberTest.java | 290 +++++++++++ 12 files changed, 2708 insertions(+), 164 deletions(-) create mode 100644 Dorkbox-Util/src/dorkbox/util/bytes/BigEndian.java create mode 100644 Dorkbox-Util/src/dorkbox/util/bytes/UByte.java create mode 100644 Dorkbox-Util/src/dorkbox/util/bytes/UInteger.java create mode 100644 Dorkbox-Util/src/dorkbox/util/bytes/ULong.java create mode 100644 Dorkbox-Util/src/dorkbox/util/bytes/UNumber.java create mode 100644 Dorkbox-Util/src/dorkbox/util/bytes/UShort.java create mode 100644 Dorkbox-Util/src/dorkbox/util/bytes/Unsigned.java create mode 100644 Dorkbox-Util/test/dorkbox/util/UByteTest.java create mode 100644 Dorkbox-Util/test/dorkbox/util/UIntegerTest.java create mode 100644 Dorkbox-Util/test/dorkbox/util/UNumberTest.java 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 unsigned byte type + * + * @author Lukas Eder + * @author Ed Schaller + */ +public final class UByte extends UNumber implements Comparable { + + /** + * Generated UID + */ + private static final long serialVersionUID = -6821055240959745390L; + + /** + * Cached values + */ + private static final UByte[] VALUES = mkValues(); + + /** + * A constant holding the minimum value an unsigned 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 Comparable { + private static final Class CLASS = UInteger.class; + private static final String CLASS_NAME = CLASS.getName(); + + /** + * System property name for the property to set the size of the pre-cache. + */ + private static final String PRECACHE_PROPERTY = CLASS_NAME + ".precacheSize"; + + /** + * Default size for the value cache. + */ + private static final int DEFAULT_PRECACHE_SIZE = 256; + + /** + * Generated UID + */ + private static final long serialVersionUID = -6821055240959745390L; + + /** + * Cached values + */ + private static final UInteger[] VALUES = mkValues(); + + /** + * A constant holding the minimum value an unsigned 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 Comparable { + + /** + * Generated UID + */ + private static final long serialVersionUID = -6821055240959745390L; + + /** + * A constant holding the minimum value an unsigned 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 Comparable { + + /** + * Generated UID + */ + private static final long serialVersionUID = -6821055240959745390L; + + /** + * A constant holding the minimum value an unsigned 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. + *

+ * 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 + * + * @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 strings, UNumber... numbers) { + List list = new ArrayList(asList(numbers)); + Collections.sort((List) list); + + for (int i = 0; i < numbers.length; i++) { + assertEquals(strings.get(i), list.get(i).toString()); + } + } + + @SuppressWarnings("deprecation") + private void testCastable(short value, UByte u) { + assertEquals((byte) value, u.byteValue()); + assertEquals(value, u.shortValue()); + assertEquals(value, u.intValue()); + assertEquals(value, u.longValue()); + assertEquals((double) value, u.doubleValue()); + assertEquals((float) value, u.floatValue()); + assertEquals(new BigInteger("" + value), u.toBigInteger()); + } + + @SuppressWarnings("deprecation") + private void testCastable(int value, UShort u) { + assertEquals((byte) value, u.byteValue()); + assertEquals((short) value, u.shortValue()); + assertEquals(value, u.intValue()); + assertEquals(value, u.longValue()); + assertEquals((double) value, u.doubleValue()); + assertEquals((float) value, u.floatValue()); + assertEquals(new BigInteger("" + value), u.toBigInteger()); + } + + @SuppressWarnings("deprecation") + private void testCastable(long value, UInteger u) { + assertEquals((byte) value, u.byteValue()); + assertEquals((short) value, u.shortValue()); + assertEquals((int) value, u.intValue()); + assertEquals(value, u.longValue()); + assertEquals((double) value, u.doubleValue()); + assertEquals((float) value, u.floatValue()); + assertEquals(new BigInteger("" + value), u.toBigInteger()); + } + + @SuppressWarnings("deprecation") + private void testCastable(BigInteger value, ULong u) { + assertEquals(value.byteValue(), u.byteValue()); + assertEquals(value.shortValue(), u.shortValue()); + assertEquals(value.intValue(), u.intValue()); + assertEquals(value.longValue(), u.longValue()); + assertEquals(value.doubleValue(), u.doubleValue()); + assertEquals(value.floatValue(), u.floatValue()); + assertEquals(new BigInteger("" + value), u.toBigInteger()); + } +} \ No newline at end of file