otpinputstream.java
来自「OTP是开放电信平台的简称」· Java 代码 · 共 952 行 · 第 1/2 页
JAVA
952 行
/* ``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 via the world wide web 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. * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' * * $Id$ */package com.ericsson.otp.erlang;import java.io.ByteArrayInputStream;import java.io.IOException;import java.text.DecimalFormat;import java.math.BigDecimal;/** * Provides a stream for decoding Erlang terms from external format. * * <p> Note that this class is not synchronized, if you need * synchronization you must provide it yourself. **/public class OtpInputStream extends ByteArrayInputStream { /** * Create a stream from a buffer containing encoded Erlang terms. **/ public OtpInputStream(byte[] buf) { super(buf); } /** * Create a stream from a buffer containing encoded * Erlang terms at the given offset and length. **/ public OtpInputStream(byte[] buf, int offset, int length) { super(buf,offset,length); } /** * Get the current position in the stream. * * @return the current position in the stream. **/ public int getPos() { return super.pos; } /** * Set the current position in the stream. * * @param pos the position to move to in the stream. If pos * indicates a position beyond the end of the stream, the position * is move to the end of the stream instead. If pos is negative, the * position is moved to the beginning of the stream instead. * * @return the previous position in the stream. **/ public int setPos(int pos) { int oldpos = super.pos; if (pos > super.count) pos = super.count; else if (pos < 0) pos = 0; super.pos = pos; return oldpos; } /** * Read an array of bytes from the stream. The method reads at most * buf.length bytes from the input stream. * * @return the number of bytes read. * * @exception OtpErlangDecodeException if the next byte cannot be * read. **/ public int readN(byte[] buf) throws OtpErlangDecodeException { try { return super.read(buf); } catch (IOException e) { throw new OtpErlangDecodeException("Cannot read from input stream"); } } /** * Look ahead one position in the stream without consuming the byte * found there. * * @return the next byte in the stream, as an integer. * * @exception OtpErlangDecodeException if the next byte cannot be * read. **/ public int peek() throws OtpErlangDecodeException { int i; try { i = super.buf[super.pos]; if (i<0) i+= 256; return i; } catch (Exception e) { throw new OtpErlangDecodeException("Cannot read from input stream"); } } /** * Read a one byte integer from the stream. * * @return the byte read, as an integer. * * @exception OtpErlangDecodeException if the next byte cannot be * read. **/ public int read1() throws OtpErlangDecodeException { int i; i = super.read(); if (i<0) { throw new OtpErlangDecodeException("Cannot read from input stream"); } return i; } /** * Read a two byte big endian integer from the stream. * * @return the bytes read, converted from big endian to an integer. * * @exception OtpErlangDecodeException if the next byte cannot be * read. **/ public int read2BE() throws OtpErlangDecodeException { byte[] b = new byte[2]; try { super.read(b); } catch (IOException e) { throw new OtpErlangDecodeException("Cannot read from input stream"); }; return ((( (int)b[0] << 8) & 0xff00) + (((int)b[1] ) & 0xff)); } /** * Read a four byte big endian integer from the stream. * * @return the bytes read, converted from big endian to an integer. * * @exception OtpErlangDecodeException if the next byte cannot be * read. **/ public int read4BE() throws OtpErlangDecodeException { byte[] b = new byte[4]; try { super.read(b); } catch (IOException e) { throw new OtpErlangDecodeException("Cannot read from input stream"); }; return ((( (int)b[0] << 24) & 0xff000000) + (((int)b[1] << 16) & 0xff0000) + (((int)b[2] << 8) & 0xff00) + (((int)b[3] ) & 0xff)); } /** * Read a two byte little endian integer from the stream. * * @return the bytes read, converted from little endian to an * integer. * * @exception OtpErlangDecodeException if the next byte cannot be * read. **/ public int read2LE() throws OtpErlangDecodeException { byte[] b = new byte[2]; try { super.read(b); } catch (IOException e) { throw new OtpErlangDecodeException("Cannot read from input stream"); }; return ((( (int)b[1] << 8) & 0xff00) + (((int)b[0] ) & 0xff)); } /** * Read a four byte little endian integer from the stream. * * @return the bytes read, converted from little endian to an * integer. * * @exception OtpErlangDecodeException if the next byte cannot be * read. **/ public int read4LE() throws OtpErlangDecodeException { byte[] b = new byte[4]; try { super.read(b); } catch (IOException e) { throw new OtpErlangDecodeException("Cannot read from input stream"); }; return ((( (int)b[3] << 24) & 0xff000000) + (((int)b[2] << 16) & 0xff0000) + (((int)b[1] << 8) & 0xff00) + (((int)b[0] ) & 0xff)); } /** * Read a little endian integer from the stream. * * @param n the number of bytes to read * * @return the bytes read, converted from little endian to an * integer. * * @exception OtpErlangDecodeException if the next byte cannot be * read. **/ public long readLE(int n) throws OtpErlangDecodeException { byte[] b = new byte[n]; try { super.read(b); } catch (IOException e) { throw new OtpErlangDecodeException("Cannot read from input stream"); }; long v = 0; for (int i = n-1; i >= 0; i--) { v = (v << 8) | ((long)b[i] & 0xff); } return v; } /** * Read an Erlang atom from the stream and interpret the value as a * boolean. * * @return true if the atom at the current position in the stream * contains the value 'true' (ignoring case), false otherwise. * * @exception OtpErlangDecodeException if the next term in the * stream is not an atom. **/ public boolean read_boolean() throws OtpErlangDecodeException { return Boolean.valueOf(this.read_atom()).booleanValue(); } /** * Read an Erlang atom from the stream. * * @return a String containing the value of the atom. * * @exception OtpErlangDecodeException if the next term in the * stream is not an atom. **/ public String read_atom() throws OtpErlangDecodeException { int tag; int len; byte[] strbuf; String atom; tag = this.read1(); if (tag == OtpExternal.versionTag) { tag = this.read1(); } if (tag != OtpExternal.atomTag) { throw new OtpErlangDecodeException("wrong tag encountered, expected " + OtpExternal.atomTag + ", got " + tag); } len = this.read2BE(); strbuf = new byte[len]; this.readN(strbuf); atom = new String(strbuf); if (atom.length() > OtpExternal.maxAtomLength) { atom = atom.substring(0,OtpExternal.maxAtomLength); } return atom; } /** * Read an Erlang binary from the stream. * * @return a byte array containing the value of the binary. * * @exception OtpErlangDecodeException if the next term in the * stream is not a binary. **/ public byte[] read_binary() throws OtpErlangDecodeException { int tag; int len; byte[] bin; tag = this.read1(); if (tag == OtpExternal.versionTag) { tag = this.read1(); } if (tag != OtpExternal.binTag) { throw new OtpErlangDecodeException("Wrong tag encountered, expected " + OtpExternal.binTag + ", got " + tag); } len = this.read4BE(); bin = new byte[len]; this.readN(bin); return bin; } /** * Read an Erlang float from the stream. * * @return the float value. * * @exception OtpErlangDecodeException if the next term in the * stream is not a float. **/ public float read_float() throws OtpErlangDecodeException { BigDecimal val = getFloatOrDouble(); return val.floatValue(); /* * * double d = this.read_double(); * float f = (float) d; * * if (java.lang.Math.abs(d - f) >= 1.0E-20) * throw new OtpErlangDecodeException("Value cannot be represented as float: " + d); * * return f; */ } /** * Read an Erlang float from the stream. * * @return the float value, as a double. * * @exception OtpErlangDecodeException if the next term in the * stream is not a float. **/ public double read_double() throws OtpErlangDecodeException { BigDecimal val = getFloatOrDouble(); return val.doubleValue(); } private BigDecimal getFloatOrDouble() throws OtpErlangDecodeException { BigDecimal val; int epos; int exp; byte[] strbuf = new byte[31]; String str; int tag; // parse the stream tag = this.read1(); if (tag == OtpExternal.versionTag) { tag = this.read1(); } if (tag != OtpExternal.floatTag) { throw new OtpErlangDecodeException("Wrong tag encountered, expected " + OtpExternal.floatTag + ", got " + tag); } // get the string this.readN(strbuf); str = new String(strbuf); // find the exponent prefix 'e' in the string epos = str.indexOf('e',0); if (epos < 0) { throw new OtpErlangDecodeException("Invalid float format: '" + str + "'"); } // remove the sign from the exponent, if positive String estr = str.substring(epos+1).trim(); if (estr.substring(0,1).equals("+")) { estr = estr.substring(1); } // now put the mantissa and exponent together exp = Integer.valueOf(estr).intValue(); val = new BigDecimal(str.substring(0,epos)).movePointRight(exp); return val; } /** * Read one byte from the stream. * * @return the byte read. * * @exception OtpErlangDecodeException if the next byte cannot be * read. **/ public byte read_byte() throws OtpErlangDecodeException { long l = this.read_long(false); byte i = (byte) l; if (l != i) { throw new OtpErlangDecodeException("Value does not fit in byte: " + l); } return i; } /** * Read a character from the stream. * * @return the character value. * * @exception OtpErlangDecodeException if the next term in the * stream is not an integer that can be represented as a char. **/ public char read_char() throws OtpErlangDecodeException { long l = this.read_long(true); char i = (char) l; if (l != ((long)i & 0xffffL)) { throw new OtpErlangDecodeException("Value does not fit in char: "+l); } return i; } /** * Read an unsigned integer from the stream. * * @return the integer value. * * @exception OtpErlangDecodeException if the next term in the * stream can not be represented as a positive integer. **/ public int read_uint() throws OtpErlangDecodeException {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?