aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/tasty/TastyReader.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-04-29 10:36:16 +0200
committerMartin Odersky <odersky@gmail.com>2015-05-02 19:23:08 +0200
commit60ab9f8f525d319aa5b6d5052018c6781da036eb (patch)
treefbc5096a1f7193a4970226a7ad6f03fbf7670a4b /src/dotty/tools/dotc/core/tasty/TastyReader.scala
parentac46a0e4489bba4f76863cc1491bf2b8441ed1cb (diff)
downloaddotty-60ab9f8f525d319aa5b6d5052018c6781da036eb.tar.gz
dotty-60ab9f8f525d319aa5b6d5052018c6781da036eb.tar.bz2
dotty-60ab9f8f525d319aa5b6d5052018c6781da036eb.zip
Pickling modularization reorg
The pickling package got rather large and confusing with three separate tasks that each had their own conventions: read JVM classfiles, read Scala2 pickle info, read Tasty. The classes for each task are now in separate packages.
Diffstat (limited to 'src/dotty/tools/dotc/core/tasty/TastyReader.scala')
-rw-r--r--src/dotty/tools/dotc/core/tasty/TastyReader.scala141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/tasty/TastyReader.scala b/src/dotty/tools/dotc/core/tasty/TastyReader.scala
new file mode 100644
index 000000000..311097148
--- /dev/null
+++ b/src/dotty/tools/dotc/core/tasty/TastyReader.scala
@@ -0,0 +1,141 @@
+package dotty.tools
+package dotc
+package core
+package tasty
+
+import TastyBuffer._
+import TastyName.NameRef
+import collection.mutable
+
+/** A byte array buffer that can be filled with bytes or natural numbers in TASTY format,
+ * and that supports reading and patching addresses represented as natural numbers.
+ *
+ * @param bytes The array containing data
+ * @param from The position from which to read
+ * @param end The position one greater than the last byte to be read
+ * @param base The index referenced by the logical zero address Addr(0)
+ */
+class TastyReader(val bytes: Array[Byte], start: Int, end: Int, val base: Int = 0) {
+
+ def this(bytes: Array[Byte]) = this(bytes, 0, bytes.length)
+
+ private var bp: Int = start
+
+ def addr(idx: Int) = Addr(idx - base)
+ def index(addr: Addr) = addr.index + base
+
+ /** The address of the first byte to read, respectively byte that was read */
+ def startAddr: Addr = addr(start)
+
+ /** The address of the next byte to read */
+ def currentAddr: Addr = addr(bp)
+
+ /** the address one greater than the last brte to read */
+ def endAddr: Addr = addr(end)
+
+ /** Have all bytes been read? */
+ def isAtEnd: Boolean = bp == end
+
+ /** A new reader over the same array with the same address base, but with
+ * specified start and end positions
+ */
+ def subReader(start: Addr, end: Addr): TastyReader =
+ new TastyReader(bytes, index(start), index(end), base)
+
+ /** Read a byte of data. */
+ def readByte(): Int = {
+ val result = bytes(bp) & 0xff
+ bp += 1
+ result
+ }
+
+ /** Returns the next byte of data as a natural number without advancing the read position */
+ def nextByte: Int = bytes(bp) & 0xff
+
+ /** Read the next `n` bytes of `data`. */
+ def readBytes(n: Int): Array[Byte] = {
+ val result = new Array[Byte](n)
+ Array.copy(bytes, bp, result, 0, n)
+ bp += n
+ result
+ }
+
+ /** Read a natural number fitting in an Int in big endian format, base 128.
+ * All but the last digits have bit 0x80 set.
+ */
+ def readNat(): Int = readLongNat.toInt
+
+ /** Read an integer number in 2's complement big endian format, base 128.
+ * All but the last digits have bit 0x80 set.
+ */
+ def readInt(): Int = readLongInt.toInt
+
+ /** Read a natural number fitting in a Long in big endian format, base 128.
+ * All but the last digits have bit 0x80 set.
+ */
+ def readLongNat(): Long = {
+ var b = 0L
+ var x = 0L
+ do {
+ b = bytes(bp)
+ x = (x << 7) | (b & 0x7f)
+ bp += 1
+ } while ((b & 0x80) == 0)
+ x
+ }
+
+ /** Read a long integer number in 2's complement big endian format, base 128. */
+ def readLongInt(): Long = {
+ var b = bytes(bp)
+ var x: Long = (b << 1).toByte >> 1 // sign extend with bit 6.
+ bp += 1
+ while ((b & 0x80) == 0) {
+ b = bytes(bp)
+ x = (x << 7) | (b & 0x7f)
+ bp += 1
+ }
+ x
+ }
+
+ /** Read an uncompressed Long stored in 8 bytes in big endian format */
+ def readUncompressedLong(): Long = {
+ var x = 0
+ for (i <- 0 to 7)
+ x = (x << 8) | (readByte() & 0xff)
+ x
+ }
+
+ /** Read a natural number and return as a NameRef */
+ def readNameRef() = NameRef(readNat())
+
+ /** Read a natural number and return as an address */
+ def readAddr() = Addr(readNat())
+
+ /** Read a length number and return the absolute end address implied by it,
+ * given as <address following length field> + <length-value-read>.
+ */
+ def readEnd(): Addr = addr(readNat() + bp)
+
+ /** Set read position to the one pointed to by `addr` */
+ def goto(addr: Addr): Unit =
+ bp = index(addr)
+
+ /** Perform `op` until `end` address is reached and collect results in a list. */
+ def until[T](end: Addr)(op: => T): List[T] = {
+ val buf = new mutable.ListBuffer[T]
+ while (bp < index(end)) buf += op
+ assert(bp == index(end))
+ buf.toList
+ }
+
+ /** If before given `end` address, the result of `op`, otherwise `default` */
+ def ifBefore[T](end: Addr)(op: => T, default: T): T =
+ if (bp < index(end)) op else default
+
+ /** Perform `op` while cindition `cond` holds and collect results in a list. */
+ def collectWhile[T](cond: => Boolean)(op: => T): List[T] = {
+ val buf = new mutable.ListBuffer[T]
+ while (cond) buf += op
+ buf.toList
+ }
+}