github.com/haraldrudell/parl@v0.4.176/pruntime/pruntimelib/parse-file-line.go (about)

     1  /*
     2  © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package pruntimelib
     7  
     8  import (
     9  	"bytes"
    10  	"fmt"
    11  	"strconv"
    12  )
    13  
    14  const (
    15  	fileLineTabRune = '\t'
    16  )
    17  
    18  // ParseFileLine parses a line of a tab character then absolue file path,
    19  // followed by a colon and line number, then a space character and
    20  // a byte offset.
    21  //
    22  //	"\t/gp-debug-stack/debug-stack.go:29 +0x44"
    23  //	"\t/opt/sw/parl/g0/waiterr.go:49"
    24  func ParseFileLine(fileLine []byte) (file string, line int) {
    25  	var hasTab bool
    26  	var lastColon = -1
    27  	var spaceAfterColon = -1
    28  	if len(fileLine) > 0 {
    29  		hasTab = fileLine[0] == fileLineTabRune
    30  		lastColon = bytes.LastIndexByte(fileLine, ':')
    31  		if spaceAfterColon = bytes.LastIndexByte(fileLine, '\x20'); spaceAfterColon == -1 {
    32  			spaceAfterColon = len(fileLine)
    33  		}
    34  	}
    35  	if !hasTab || lastColon == -1 || spaceAfterColon < lastColon {
    36  		panic(fmt.Errorf("bad debug.Stack: file line: %q", string(fileLine)))
    37  	}
    38  
    39  	var err error
    40  	if line, err = strconv.Atoi(string(fileLine[lastColon+1 : spaceAfterColon])); err != nil {
    41  		panic(fmt.Errorf("bad debug.Stack file line number: %w %q", err, string(fileLine)))
    42  	} else if line < 1 {
    43  		panic(fmt.Errorf("bad debug.Stack file line number <1: %q", string(fileLine)))
    44  	}
    45  
    46  	// absolute filename
    47  	file = string(fileLine[1:lastColon])
    48  
    49  	return
    50  }