package gosym
import "encoding/binary"
type LineTable struct {
Data []byte
PC uint64
Line int
}
const quantum = 1
func (t *LineTable) parse(targetPC uint64, targetLine int) (b []byte, pc uint64, line int) {
b, pc, line = t.Data, t.PC, t.Line
for pc <= targetPC && line != targetLine && len(b) > 0 {
code := b[0]
b = b[1:]
switch {
case code == 0:
if len(b) < 4 {
b = b[0:0]
break
}
val := binary.BigEndian.Uint32(b)
b = b[4:]
line += int(val)
case code <= 64:
line += int(code)
case code <= 128:
line -= int(code - 64)
default:
pc += quantum * uint64(code-128)
continue
}
pc += quantum
}
return b, pc, line
}
func (t *LineTable) slice(pc uint64) *LineTable {
data, pc, line := t.parse(pc, -1)
return &LineTable{data, pc, line}
}
func (t *LineTable) PCToLine(pc uint64) int {
_, _, line := t.parse(pc, -1)
return line
}
func (t *LineTable) LineToPC(line int, maxpc uint64) uint64 {
_, pc, line1 := t.parse(maxpc, line)
if line1 != line {
return 0
}
return pc - quantum
}
func NewLineTable(data []byte, text uint64) *LineTable {
return &LineTable{data, text, 0}
}