summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/symtab/classfile/PickleBuffer.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/symtab/classfile/PickleBuffer.scala')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/PickleBuffer.scala118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/PickleBuffer.scala b/src/compiler/scala/tools/nsc/symtab/classfile/PickleBuffer.scala
new file mode 100644
index 0000000000..aed16bf057
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/PickleBuffer.scala
@@ -0,0 +1,118 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id$
+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: unit = {
+ val bytes1 = new Array[byte](bytes.length * 2);
+ System.arraycopy(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): unit = {
+ if (writeIndex == bytes.length) dble;
+ bytes(writeIndex) = b.asInstanceOf[byte];
+ writeIndex = 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): unit = {
+ def writeNatPrefix(x: int): unit = {
+ 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 at `pos'
+ * If number is more than one byte, shift rest of array to make space. */
+ def patchNat(pos: int, x: int): unit = {
+ def patchNatPrefix(x: int): unit = {
+ writeByte(0);
+ System.arraycopy(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 in signed big endian format, base 256. */
+ def writeLong(x: long): unit = {
+ val y = x >> 8;
+ val z = x & 0xff;
+ if (-y != (z >> 7)) writeLong(y);
+ writeByte(z.asInstanceOf[int]);
+ }
+
+ // -- Basic input routines --------------------------------------------
+
+ /** Read a byte */
+ def readByte(): int = {
+ val x = bytes(readIndex); 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 = i + 1
+ }
+ val leading = 64 - (len << 3);
+ x << leading >> leading
+ }
+
+ /** Perform operation `op' until readIndex == end. Concatenate results into a list. */
+ def until[T](end: int, op: () => T): List[T] =
+ if (readIndex == end) List() else op() :: until(end, op);
+
+ /** Create an index */
+ def createIndex: Array[int] = {
+ val index = new Array[int](readNat());
+ for (val i <- Iterator.range(0, index.length)) {
+ index(i) = readIndex;
+ readByte();
+ readIndex = readNat() + readIndex
+ }
+ index
+ }
+}