github.com/shadialtarsha/go-pcre@v0.0.0-20220904164957-b4f1834ceecc/error.go (about) 1 package pcre 2 3 import ( 4 "fmt" 5 "unsafe" 6 7 "github.com/shadialtarsha/go-pcre/lib" 8 9 "modernc.org/libc" 10 "modernc.org/libc/sys/types" 11 ) 12 13 var pce pcreError 14 15 // pcreError is meant to be manually allocated 16 // for when pcre requires a pointer to store an error 17 // such as for Xpcre2_compile_8(). 18 type pcreError struct { 19 errCode int32 20 errOffset lib.Tsize_t 21 } 22 23 // allocError manually allocates memory for the 24 // pcreError struct. 25 // 26 // libc.Xfree() should be called on the returned 27 // pointer once it is no longer needed. 28 func allocError(tls *libc.TLS) uintptr { 29 return libc.Xmalloc(tls, types.Size_t(unsafe.Sizeof(pce))) 30 } 31 32 // addErrCodeOffset adds the offset of the error code 33 // within the pcreError struct to a given pointer 34 func addErrCodeOffset(p uintptr) uintptr { 35 ptrOffset := unsafe.Offsetof(pce.errCode) 36 return p + ptrOffset 37 } 38 39 // addErrOffsetOffset adds the offset of the error 40 // offset within the pcreError struct to a given pointer 41 func addErrOffsetOffset(p uintptr) uintptr { 42 offsetOffset := unsafe.Offsetof(pce.errOffset) 43 return p + offsetOffset 44 } 45 46 // ptrToError converts the given pointer to a Go error 47 func ptrToError(tls *libc.TLS, pe uintptr) *PcreError { 48 eo := *(*pcreError)(unsafe.Pointer(pe)) 49 50 err := codeToError(tls, eo.errCode) 51 err.offset = eo.errOffset 52 err.hasOffset = true 53 54 return err 55 } 56 57 // codeToError converts the given error code into a Go error 58 func codeToError(tls *libc.TLS, code int32) *PcreError { 59 errBuf := make([]byte, 256) 60 cErrBuf := uintptr(unsafe.Pointer(&errBuf[0])) 61 62 // Get the textual error message associated with the code, 63 // and store it in errBuf. 64 msgLen := lib.Xpcre2_get_error_message_8(tls, code, cErrBuf, 256) 65 66 return &PcreError{false, 0, string(errBuf[:msgLen])} 67 } 68 69 // PcreError represents errors returned 70 // by underlying pcre2 functions. 71 type PcreError struct { 72 hasOffset bool 73 offset lib.Tsize_t 74 errStr string 75 } 76 77 // Error returns the string within the error, 78 // prepending the offset if it exists. 79 func (pe *PcreError) Error() string { 80 if !pe.hasOffset { 81 return pe.errStr 82 } 83 return fmt.Sprintf("offset %d: %s", pe.offset, pe.errStr) 84 }