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.
active/core/errs/stack_frame.go

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)
}

Powered by TurnKey Linux.