From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- .../com/ericsson/otp/erlang/OtpErlangBitstr.java | 285 +++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangBitstr.java (limited to 'lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangBitstr.java') diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangBitstr.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangBitstr.java new file mode 100644 index 0000000000..97897fe182 --- /dev/null +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangBitstr.java @@ -0,0 +1,285 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2007-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.ByteArrayOutputStream; +import java.io.IOException; +import java.io.Serializable; + +/** + * Provides a Java representation of Erlang bitstrs. An Erlang bitstr is an + * Erlang binary with a length not an integral number of bytes (8-bit). Anything + * can be represented as a sequence of bytes can be made into an Erlang bitstr. + */ +public class OtpErlangBitstr extends OtpErlangObject implements Serializable, + Cloneable { + // don't change this! + static final long serialVersionUID = -3781009633593609217L; + + protected byte[] bin; + protected int pad_bits; + + /** + * Create a bitstr from a byte array + * + * @param bin + * the array of bytes from which to create the bitstr. + */ + public OtpErlangBitstr(final byte[] bin) { + this.bin = new byte[bin.length]; + System.arraycopy(bin, 0, this.bin, 0, bin.length); + pad_bits = 0; + } + + /** + * Create a bitstr with pad bits from a byte array. + * + * @param bin + * the array of bytes from which to create the bitstr. + * @param pad_bits + * the number of unused bits in the low end of the last byte. + */ + public OtpErlangBitstr(final byte[] bin, final int pad_bits) { + this.bin = new byte[bin.length]; + System.arraycopy(bin, 0, this.bin, 0, bin.length); + this.pad_bits = pad_bits; + + check_bitstr(this.bin, this.pad_bits); + } + + private void check_bitstr(final byte[] bin, final int pad_bits) { + if (pad_bits < 0 || 7 < pad_bits) { + throw new java.lang.IllegalArgumentException( + "Padding must be in range 0..7"); + } + if (pad_bits != 0 && bin.length == 0) { + throw new java.lang.IllegalArgumentException( + "Padding on zero length bitstr"); + } + if (bin.length != 0) { + // Make sure padding is zero + bin[bin.length - 1] &= ~((1 << pad_bits) - 1); + } + } + + /** + * Create a bitstr from a stream containing a bitstr encoded in Erlang + * external format. + * + * @param buf + * the stream containing the encoded bitstr. + * + * @exception OtpErlangDecodeException + * if the buffer does not contain a valid external + * representation of an Erlang bitstr. + */ + public OtpErlangBitstr(final OtpInputStream buf) + throws OtpErlangDecodeException { + final int pbs[] = { 0 }; // This is ugly just to get a value-result + // parameter + bin = buf.read_bitstr(pbs); + pad_bits = pbs[0]; + + check_bitstr(bin, pad_bits); + } + + /** + * Create a bitstr from an arbitrary Java Object. The object must implement + * java.io.Serializable or java.io.Externalizable. + * + * @param o + * the object to serialize and create this bitstr from. + */ + public OtpErlangBitstr(final Object o) { + try { + bin = toByteArray(o); + pad_bits = 0; + } catch (final IOException e) { + throw new java.lang.IllegalArgumentException( + "Object must implement Serializable"); + } + } + + private static byte[] toByteArray(final Object o) + throws java.io.IOException { + + if (o == null) { + return null; + } + + /* need to synchronize use of the shared baos */ + final java.io.ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream( + baos); + + oos.writeObject(o); + oos.flush(); + + return baos.toByteArray(); + } + + private static Object fromByteArray(final byte[] buf) { + if (buf == null) { + return null; + } + + try { + final java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream( + buf); + final java.io.ObjectInputStream ois = new java.io.ObjectInputStream( + bais); + return ois.readObject(); + } catch (final java.lang.ClassNotFoundException e) { + } catch (final java.io.IOException e) { + } + + return null; + } + + /** + * Get the byte array from a bitstr, padded with zero bits in the little end + * of the last byte. + * + * @return the byte array containing the bytes for this bitstr. + */ + public byte[] binaryValue() { + return bin; + } + + /** + * Get the size in whole bytes of the bitstr, rest bits in the last byte not + * counted. + * + * @return the number of bytes contained in the bintstr. + */ + public int size() { + if (pad_bits == 0) { + return bin.length; + } + if (bin.length == 0) { + throw new java.lang.IllegalStateException("Impossible length"); + } + return bin.length - 1; + } + + /** + * Get the number of pad bits in the last byte of the bitstr. The pad bits + * are zero and in the little end. + * + * @return the number of pad bits in the bitstr. + */ + public int pad_bits() { + return pad_bits; + } + + /** + * Get the java Object from the bitstr. If the bitstr contains a serialized + * Java object, then this method will recreate the object. + * + * + * @return the java Object represented by this bitstr, or null if the bitstr + * does not represent a Java Object. + */ + public Object getObject() { + if (pad_bits != 0) { + return null; + } + return fromByteArray(bin); + } + + /** + * Get the string representation of this bitstr object. A bitstr is printed + * as #Bin<N>, where N is the number of bytes contained in the object + * or #bin<N-M> if there are M pad bits. + * + * @return the Erlang string representation of this bitstr. + */ + @Override + public String toString() { + if (pad_bits == 0) { + return "#Bin<" + bin.length + ">"; + } + if (bin.length == 0) { + throw new java.lang.IllegalStateException("Impossible length"); + } + return "#Bin<" + bin.length + "-" + pad_bits + ">"; + } + + /** + * Convert this bitstr to the equivalent Erlang external representation. + * + * @param buf + * an output stream to which the encoded bitstr should be + * written. + */ + @Override + public void encode(final OtpOutputStream buf) { + buf.write_bitstr(bin, pad_bits); + } + + /** + * Determine if two bitstrs are equal. Bitstrs are equal if they have the + * same byte length and tail length, and the array of bytes is identical. + * + * @param o + * the bitstr to compare to. + * + * @return true if the bitstrs contain the same bits, false otherwise. + */ + @Override + public boolean equals(final Object o) { + if (!(o instanceof OtpErlangBitstr)) { + return false; + } + + final OtpErlangBitstr that = (OtpErlangBitstr) o; + if (pad_bits != that.pad_bits) { + return false; + } + + final int len = bin.length; + if (len != that.bin.length) { + return false; + } + + for (int i = 0; i < len; i++) { + if (bin[i] != that.bin[i]) { + return false; // early exit + } + } + + return true; + } + + @Override + protected int doHashCode() { + OtpErlangObject.Hash hash = new OtpErlangObject.Hash(15); + hash.combine(bin); + hash.combine(pad_bits); + return hash.valueOf(); + } + + @Override + public Object clone() { + final OtpErlangBitstr that = (OtpErlangBitstr) super.clone(); + that.bin = bin.clone(); + that.pad_bits = pad_bits; + return that; + } +} -- cgit v1.2.3