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 + -
显示快捷键?