
org.opalj.br.CompactLineNumberTable.scala Maven / Gradle / Ivy
The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package br
import java.util.{Arrays => JArrays}
import scala.collection.immutable.ArraySeq
/**
* A method's line number table.
*
* @param rawLineNumbers
*
* LineNumberTable_attribute {
* DATA:
* { u2 start_pc;
* u2 line_number;
* }
* }
*
* The array must not be mutated by callers!
*
* @author Michael Eichberg
*/
case class CompactLineNumberTable(rawLineNumbers: Array[Byte]) extends LineNumberTable {
def lineNumbers: LineNumbers = {
val lineNumbersBuilder = ArraySeq.newBuilder[LineNumber]
var e = 0
val entries = rawLineNumbers.length / 4
while (e < entries) {
val index = e * 4
val startPC = asUnsignedShort(rawLineNumbers(index), rawLineNumbers(index + 1))
val lineNumber = asUnsignedShort(rawLineNumbers(index + 2), rawLineNumbers(index + 3))
lineNumbersBuilder += LineNumber(startPC, lineNumber)
e += 1
}
lineNumbersBuilder.result()
}
def asUnsignedShort(hb: Byte, lb: Byte): Int = {
((hb & 0xFF) << 8) | (lb & 0xFF) // cf. DataInput.readUnsignedShort
}
def lookupLineNumber(pc: PC): Option[Int] = {
var lastLineNumber = -1
var e = 0
val entries = rawLineNumbers.length / 4
while (e < entries) {
val index = e * 4
val startPC = asUnsignedShort(rawLineNumbers(index), rawLineNumbers(index + 1))
if (startPC <= pc) {
lastLineNumber = asUnsignedShort(rawLineNumbers(index + 2), rawLineNumbers(index + 3))
} else if (lastLineNumber == -1) {
return None;
} else {
return Some(lastLineNumber);
}
e += 1
}
if (lastLineNumber == -1) None else Some(lastLineNumber)
}
def firstLineNumber(): Option[Int] = {
if (rawLineNumbers.length == 0)
return None;
val raw_pc_lns = rawLineNumbers.grouped(2).zipWithIndex.filter(_._2 % 2 == 1)
val raw_lns = raw_pc_lns.map(_._1)
val lns =
raw_lns map { bytes =>
val hb = bytes(0); val lb = bytes(1); asUnsignedShort(hb, lb)
}
Some(lns.min)
}
override def equals(other: Any): Boolean = {
other match {
case that: CompactLineNumberTable =>
JArrays.equals(this.rawLineNumbers, that.rawLineNumbers)
case _ =>
false
}
}
override def hashCode(): Opcode = JArrays.hashCode(rawLineNumbers)
override def toString: String = lineNumbers.mkString("CompactLineNumber({ ", ", ", " })")
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy