You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
2.6 KiB
111 lines
2.6 KiB
// ------------------------------------------------------------------------
|
|
// Project active2
|
|
// Active Thing (activething.com) git.activething.com/go
|
|
//
|
|
// File name stack_frame.go
|
|
// Created by DEV
|
|
// Modified 20/03/2024
|
|
//
|
|
// Copyright 2024 activething.com
|
|
// ------------------------------------------------------------------------
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// ------------------------------------------------------------------------
|
|
|
|
package errs
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
)
|
|
|
|
type (
|
|
|
|
StackFrame struct {
|
|
LineNumber int // Number line
|
|
File string // File FuncName
|
|
FuncName string // Function name
|
|
Package string // Package name
|
|
Counter uintptr
|
|
}
|
|
|
|
)
|
|
|
|
|
|
func NewStackFrame (counter uintptr) *StackFrame {
|
|
if counter == 0 {
|
|
return nil
|
|
}
|
|
sf := &StackFrame{
|
|
Counter: counter,
|
|
}
|
|
fn := runtime.FuncForPC(counter)
|
|
sf.Package, sf.FuncName = packageAndName(fn)
|
|
sf.File, sf.LineNumber = fn.FileLine(counter-1)
|
|
return sf
|
|
}
|
|
|
|
|
|
|
|
func (f StackFrame) SourceLine() (string, error) {
|
|
if f.LineNumber <= 0 {
|
|
return unknownInfo, nil
|
|
}
|
|
|
|
file, err := os.Open(f.File)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
currentLine := 1
|
|
for scanner.Scan() {
|
|
if currentLine == f.LineNumber {
|
|
return string(bytes.Trim(scanner.Bytes(), " \t")), nil
|
|
}
|
|
currentLine++
|
|
}
|
|
_ = file.Close()
|
|
if err := scanner.Err(); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return unknownInfo, nil
|
|
}
|
|
|
|
|
|
func (f StackFrame) String () string {
|
|
source, err := f.SourceLine()
|
|
if err != nil {
|
|
return fmt.Sprintf("%s:%d (0x%x)\n\t%s:%s\n", f.File, f.LineNumber, f.Counter, f.Package, f.FuncName)
|
|
}
|
|
return fmt.Sprintf("%s:%d (0x%x)\n\t%s:%s -> %s\n", f.File, f.LineNumber, f.Counter, f.Package, f.FuncName, source)
|
|
}
|
|
|
|
|
|
func packageAndName (fn *runtime.Func) (string,string) {
|
|
nm := fn.Name()
|
|
pg := ""
|
|
if ls := strings.LastIndex(nm,"/"); ls >= 0 {
|
|
pg = nm[:ls] + "/"
|
|
nm = nm[ls+1:]
|
|
}
|
|
if pd := strings.Index(nm,"."); pd >= 0 {
|
|
pg += nm[:pd]
|
|
nm = nm[pd+1:]
|
|
}
|
|
return pg,strings.Replace(nm,"·", ".",-1)
|
|
} |