aboutsummaryrefslogtreecommitdiffstats
path: root/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java
diff options
context:
space:
mode:
Diffstat (limited to 'lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java')
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java399
1 files changed, 399 insertions, 0 deletions
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java
new file mode 100644
index 0000000000..7e3e2a7296
--- /dev/null
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java
@@ -0,0 +1,399 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2000-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+package com.ericsson.otp.erlang;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+
+/**
+ * Provides a Java representation of Erlang integral types. Erlang does not
+ * distinguish between different integral types, however this class and its
+ * subclasses {@link OtpErlangByte}, {@link OtpErlangChar},
+ * {@link OtpErlangInt}, and {@link OtpErlangShort} attempt to map the Erlang
+ * types onto the various Java integral types. Two additional classes,
+ * {@link OtpErlangUInt} and {@link OtpErlangUShort} are provided for Corba
+ * compatibility. See the documentation for IC for more information.
+ */
+public class OtpErlangLong extends OtpErlangObject implements Serializable,
+ Cloneable {
+ // don't change this!
+ static final long serialVersionUID = 1610466859236755096L;
+
+ private long val;
+ private BigInteger bigVal = null;
+
+ /**
+ * Create an Erlang integer from the given value.
+ *
+ * @param l
+ * the long value to use.
+ */
+ public OtpErlangLong(final long l) {
+ val = l;
+ }
+
+ /**
+ * Create an Erlang integer from the given value.
+ *
+ * @param val
+ * the long value to use.
+ */
+ public OtpErlangLong(final BigInteger v) {
+ if (v == null) {
+ throw new java.lang.NullPointerException();
+ }
+ if (v.bitLength() < 64) {
+ val = v.longValue();
+ } else {
+ bigVal = v;
+ }
+ }
+
+ /**
+ * Create an Erlang integer from a stream containing an integer encoded in
+ * Erlang external format.
+ *
+ * @param buf
+ * the stream containing the encoded value.
+ *
+ * @exception OtpErlangDecodeException
+ * if the buffer does not contain a valid external
+ * representation of an Erlang integer.
+ */
+ public OtpErlangLong(final OtpInputStream buf)
+ throws OtpErlangDecodeException {
+ final byte[] b = buf.read_integer_byte_array();
+ try {
+ val = OtpInputStream.byte_array_to_long(b, false);
+ } catch (final OtpErlangDecodeException e) {
+ bigVal = new BigInteger(b);
+ }
+ }
+
+ /**
+ * Get this number as a BigInteger.
+ *
+ * @return the value of this number, as a BigInteger.
+ */
+ public BigInteger bigIntegerValue() {
+ if (bigVal != null) {
+ return bigVal;
+ } else {
+ return BigInteger.valueOf(val);
+ }
+ }
+
+ /**
+ * Get this number as a long, or rather truncate all but the least
+ * significant 64 bits from the 2's complement representation of this number
+ * and return them as a long.
+ *
+ * @return the value of this number, as a long.
+ */
+ public long longValue() {
+ if (bigVal != null) {
+ return bigVal.longValue();
+ } else {
+ return val;
+ }
+ }
+
+ /**
+ * Determine if this value can be represented as a long without truncation.
+ *
+ * @return true if this value fits in a long, false otherwise.
+ */
+ public boolean isLong() {
+ // To just chech this.bigVal is a wee bit to simple, since
+ // there just might have be a mean bignum that arrived on
+ // a stream, and was a long disguised as more than 8 byte integer.
+ if (bigVal != null) {
+ return bigVal.bitLength() < 64;
+ }
+ return true;
+ }
+
+ /**
+ * Determine if this value can be represented as an unsigned long without
+ * truncation, that is if the value is non-negative and its bit pattern
+ * completely fits in a long.
+ *
+ * @return true if this value is non-negative and fits in a long false
+ * otherwise.
+ */
+ public boolean isULong() {
+ // Here we have the same problem as for isLong(), plus
+ // the whole range 1<<63 .. (1<<64-1) is allowed.
+ if (bigVal != null) {
+ return bigVal.signum() >= 0 && bigVal.bitLength() <= 64;
+ }
+ return val >= 0;
+ }
+
+ /**
+ * Returns the number of bits in the minimal two's-complement representation
+ * of this BigInteger, excluding a sign bit.
+ *
+ * @return number of bits in the minimal two's-complement representation of
+ * this BigInteger, excluding a sign bit.
+ */
+ public int bitLength() {
+ if (bigVal != null) {
+ return bigVal.bitLength();
+ }
+ if (val == 0 || val == -1) {
+ return 0;
+ } else {
+ // Binary search for bit length
+ int i = 32; // mask length
+ long m = (1L << i) - 1; // AND mask with ones in little end
+ if (val < 0) {
+ m = ~m; // OR mask with ones in big end
+ for (int j = i >> 1; j > 0; j >>= 1) { // mask delta
+ if ((val | m) == val) { // mask >= enough
+ i -= j;
+ m >>= j; // try less bits
+ } else {
+ i += j;
+ m <<= j; // try more bits
+ }
+ }
+ if ((val | m) != val) {
+ i++; // mask < enough
+ }
+ } else {
+ for (int j = i >> 1; j > 0; j >>= 1) { // mask delta
+ if ((val & m) == val) { // mask >= enough
+ i -= j;
+ m >>= j; // try less bits
+ } else {
+ i += j;
+ m = m << j | m; // try more bits
+ }
+ }
+ if ((val & m) != val) {
+ i++; // mask < enough
+ }
+ }
+ return i;
+ }
+ }
+
+ /**
+ * Return the signum function of this object.
+ *
+ * @return -1, 0 or 1 as the value is negative, zero or positive.
+ */
+ public int signum() {
+ if (bigVal != null) {
+ return bigVal.signum();
+ } else {
+ return val > 0 ? 1 : val < 0 ? -1 : 0;
+ }
+ }
+
+ /**
+ * Get this number as an int.
+ *
+ * @return the value of this number, as an int.
+ *
+ * @exception OtpErlangRangeException
+ * if the value is too large to be represented as an int.
+ */
+ public int intValue() throws OtpErlangRangeException {
+ final long l = longValue();
+ final int i = (int) l;
+
+ if (i != l) {
+ throw new OtpErlangRangeException("Value too large for int: " + val);
+ }
+
+ return i;
+ }
+
+ /**
+ * Get this number as a non-negative int.
+ *
+ * @return the value of this number, as an int.
+ *
+ * @exception OtpErlangRangeException
+ * if the value is too large to be represented as an int,
+ * or if the value is negative.
+ */
+ public int uIntValue() throws OtpErlangRangeException {
+ final long l = longValue();
+ final int i = (int) l;
+
+ if (i != l) {
+ throw new OtpErlangRangeException("Value too large for int: " + val);
+ } else if (i < 0) {
+ throw new OtpErlangRangeException("Value not positive: " + val);
+ }
+
+ return i;
+ }
+
+ /**
+ * Get this number as a short.
+ *
+ * @return the value of this number, as a short.
+ *
+ * @exception OtpErlangRangeException
+ * if the value is too large to be represented as a
+ * short.
+ */
+ public short shortValue() throws OtpErlangRangeException {
+ final long l = longValue();
+ final short i = (short) l;
+
+ if (i != l) {
+ throw new OtpErlangRangeException("Value too large for short: "
+ + val);
+ }
+
+ return i;
+ }
+
+ /**
+ * Get this number as a non-negative short.
+ *
+ * @return the value of this number, as a short.
+ *
+ * @exception OtpErlangRangeException
+ * if the value is too large to be represented as a
+ * short, or if the value is negative.
+ */
+ public short uShortValue() throws OtpErlangRangeException {
+ final long l = longValue();
+ final short i = (short) l;
+
+ if (i != l) {
+ throw new OtpErlangRangeException("Value too large for short: "
+ + val);
+ } else if (i < 0) {
+ throw new OtpErlangRangeException("Value not positive: " + val);
+ }
+
+ return i;
+ }
+
+ /**
+ * Get this number as a char.
+ *
+ * @return the char value of this number.
+ *
+ * @exception OtpErlangRangeException
+ * if the value is too large to be represented as a char.
+ */
+ public char charValue() throws OtpErlangRangeException {
+ final long l = longValue();
+ final char i = (char) l;
+
+ if (i != l) {
+ throw new OtpErlangRangeException("Value too large for char: "
+ + val);
+ }
+
+ return i;
+ }
+
+ /**
+ * Get this number as a byte.
+ *
+ * @return the byte value of this number.
+ *
+ * @exception OtpErlangRangeException
+ * if the value is too large to be represented as a byte.
+ */
+ public byte byteValue() throws OtpErlangRangeException {
+ final long l = longValue();
+ final byte i = (byte) l;
+
+ if (i != l) {
+ throw new OtpErlangRangeException("Value too large for byte: "
+ + val);
+ }
+
+ return i;
+ }
+
+ /**
+ * Get the string representation of this number.
+ *
+ * @return the string representation of this number.
+ */
+ @Override
+ public String toString() {
+ if (bigVal != null) {
+ return "" + bigVal;
+ } else {
+ return "" + val;
+ }
+ }
+
+ /**
+ * Convert this number to the equivalent Erlang external representation.
+ *
+ * @param buf
+ * an output stream to which the encoded number should be
+ * written.
+ */
+ @Override
+ public void encode(final OtpOutputStream buf) {
+ if (bigVal != null) {
+ buf.write_big_integer(bigVal);
+ } else {
+ buf.write_long(val);
+ }
+ }
+
+ /**
+ * Determine if two numbers are equal. Numbers are equal if they contain the
+ * same value.
+ *
+ * @param o
+ * the number to compare to.
+ *
+ * @return true if the numbers have the same value.
+ */
+ @Override
+ public boolean equals(final Object o) {
+ if (!(o instanceof OtpErlangLong)) {
+ return false;
+ }
+
+ final OtpErlangLong that = (OtpErlangLong) o;
+
+ if (bigVal != null && that.bigVal != null) {
+ return bigVal.equals(that.bigVal);
+ } else if (bigVal == null && that.bigVal == null) {
+ return val == that.val;
+ }
+ return false;
+ }
+
+ @Override
+ protected int doHashCode() {
+ if (bigVal != null) {
+ return bigVal.hashCode();
+ } else {
+ return BigInteger.valueOf(val).hashCode();
+ }
+ }
+}