85 lines
2.0 KiB
Go
85 lines
2.0 KiB
Go
package pcre
|
|
|
|
import (
|
|
"fmt"
|
|
"unsafe"
|
|
|
|
"go.elara.ws/pcre/lib"
|
|
|
|
"modernc.org/libc"
|
|
"modernc.org/libc/sys/types"
|
|
)
|
|
|
|
var pce pcreError
|
|
|
|
// pcreError is meant to be manually allocated
|
|
// for when pcre requires a pointer to store an error
|
|
// such as for Xpcre2_compile_8().
|
|
type pcreError struct {
|
|
errCode int32
|
|
errOffset lib.Tsize_t
|
|
}
|
|
|
|
// allocError manually allocates memory for the
|
|
// pcreError struct.
|
|
//
|
|
// libc.Xfree() should be called on the returned
|
|
// pointer once it is no longer needed.
|
|
func allocError(tls *libc.TLS) uintptr {
|
|
return libc.Xmalloc(tls, types.Size_t(unsafe.Sizeof(pce)))
|
|
}
|
|
|
|
// addErrCodeOffset adds the offset of the error code
|
|
// within the pcreError struct to a given pointer
|
|
func addErrCodeOffset(p uintptr) uintptr {
|
|
ptrOffset := unsafe.Offsetof(pce.errCode)
|
|
return p + ptrOffset
|
|
}
|
|
|
|
// addErrOffsetOffset adds the offset of the error
|
|
// offset within the pcreError struct to a given pointer
|
|
func addErrOffsetOffset(p uintptr) uintptr {
|
|
offsetOffset := unsafe.Offsetof(pce.errOffset)
|
|
return p + offsetOffset
|
|
}
|
|
|
|
// ptrToError converts the given pointer to a Go error
|
|
func ptrToError(tls *libc.TLS, pe uintptr) *PcreError {
|
|
eo := *(*pcreError)(unsafe.Pointer(pe))
|
|
|
|
err := codeToError(tls, eo.errCode)
|
|
err.offset = eo.errOffset
|
|
err.hasOffset = true
|
|
|
|
return err
|
|
}
|
|
|
|
// codeToError converts the given error code into a Go error
|
|
func codeToError(tls *libc.TLS, code int32) *PcreError {
|
|
errBuf := make([]byte, 256)
|
|
cErrBuf := uintptr(unsafe.Pointer(&errBuf[0]))
|
|
|
|
// Get the textual error message associated with the code,
|
|
// and store it in errBuf.
|
|
msgLen := lib.Xpcre2_get_error_message_8(tls, code, cErrBuf, 256)
|
|
|
|
return &PcreError{false, 0, string(errBuf[:msgLen])}
|
|
}
|
|
|
|
// PcreError represents errors returned
|
|
// by underlying pcre2 functions.
|
|
type PcreError struct {
|
|
hasOffset bool
|
|
offset lib.Tsize_t
|
|
errStr string
|
|
}
|
|
|
|
// Error returns the string within the error,
|
|
// prepending the offset if it exists.
|
|
func (pe *PcreError) Error() string {
|
|
if !pe.hasOffset {
|
|
return pe.errStr
|
|
}
|
|
return fmt.Sprintf("offset %d: %s", pe.offset, pe.errStr)
|
|
}
|