picklebuffer.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 149 行

SCALA
149
字号
/* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author  Martin Odersky */// $Id: PickleBuffer.scala 13032 2007-10-09 16:28:22Z michelou $package scala.tools.nsc.symtab.classfile/** Variable length byte arrays, with methods for basic pickling and unpickling. * *  @param data The initial buffer *  @param from The first index where defined data are found *  @param to   The first index where new data can be written */class PickleBuffer(data: Array[Byte], from: Int, to: Int) {  var bytes = data  var readIndex = from  var writeIndex = to  /** Double bytes array */  private def dble() {    val bytes1 = new Array[Byte](bytes.length * 2)    Array.copy(bytes, 0, bytes1, 0, writeIndex)    bytes = bytes1  }  def ensureCapacity(capacity: Int) =    while (bytes.length < writeIndex + capacity) dble()  // -- Basic output routines --------------------------------------------  /** Write a byte of data */  def writeByte(b: Int) {    if (writeIndex == bytes.length) dble()    bytes(writeIndex) = b.asInstanceOf[Byte]    writeIndex += 1  }  /** Write a natural number in big endian format, base 128.   *  All but the last digits have bit 0x80 set.   */  def writeNat(x: Int) {    def writeNatPrefix(x: Int) {      val y = x >>> 7      if (y != 0) writeNatPrefix(y)      writeByte((x & 0x7f) | 0x80)    }    val y = x >>> 7    if (y != 0) writeNatPrefix(y)    writeByte(x & 0x7f)  }  /** Write a natural number <code>x</code> at position <code>pos</code>.   *  If number is more than one byte, shift rest of array to make space.   *   *  @param pos ...   *  @param x   ...   */  def patchNat(pos: Int, x: Int) {    def patchNatPrefix(x: Int) {      writeByte(0)      Array.copy(bytes, pos, bytes, pos+1, writeIndex - (pos+1))      bytes(pos) = ((x & 0x7f) | 0x80).asInstanceOf[Byte]      val y = x >>> 7      if (y != 0) patchNatPrefix(y)    }    bytes(pos) = (x & 0x7f).asInstanceOf[Byte]    val y = x >>> 7    if (y != 0) patchNatPrefix(y)  }  /** Write a long number <code>x</code> in signed big endian format, base 256.   *   *  @param x The long number to be written.   */  def writeLong(x: Long) {    val y = x >> 8    val z = x & 0xff    if (-y != (z >> 7)) writeLong(y)    writeByte(z.asInstanceOf[Int])  }  // -- Basic input routines --------------------------------------------  /** Peek at the current byte without moving the read index */  def peekByte(): Int = bytes(readIndex)  /** Read a byte */  def readByte(): Int = {    val x = bytes(readIndex); readIndex += 1; x  }  /** Read a natural number in big endian format, base 128.   *  All but the last digits have bit 0x80 set.*/  def readNat(): Int = {    var b = 0    var x = 0    do {      b = readByte()      x = (x << 7) + (b & 0x7f)    } while ((b & 0x80) != 0);    x  }  /** Read a long number in signed big endian format, base 256. */  def readLong(len: Int): Long = {    var x = 0L    var i = 0    while (i < len) {      x = (x << 8) + (readByte() & 0xff)      i += 1    }    val leading = 64 - (len << 3)    x << leading >> leading  }  /** Perform operation <code>op</code> until the condition   *  <code>readIndex == end</code> is satisfied.   *  Concatenate results into a list.   *   *  @param end ...   *  @param op  ...   *  @return    ...   */  def until[T](end: Int, op: () => T): List[T] =    if (readIndex == end) List() else op() :: until(end, op);  /** Perform operation <code>op</code> the number of   *  times specified.  Concatenate the results into a list.   */  def times[T](n: Int, op: ()=>T): List[T] =    if (n == 0) List() else op() :: times(n-1, op)  /** Create an index.   *   *  @return ...   */  def createIndex: Array[Int] = {    val index = new Array[Int](readNat())    for (i <- 0 until index.length) {      index(i) = readIndex      readByte()      readIndex = readNat() + readIndex    }    index  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?