[agent/codex:gpt-5.3-codex-spark] Read docs/RFC.md fully. Find ONE feature described in the sp... #26
3 changed files with 42 additions and 39 deletions
23
buffer.go
23
buffer.go
|
|
@ -18,15 +18,16 @@ import (
|
|||
// n := buffer.CopyFrom([]byte("payload"))
|
||||
// _ = buffer.Bytes()[:n]
|
||||
type Buffer struct {
|
||||
data []byte
|
||||
length int
|
||||
pointer unsafe.Pointer
|
||||
freed atomic.Bool
|
||||
data []byte
|
||||
length int
|
||||
pointer unsafe.Pointer
|
||||
freed atomic.Bool
|
||||
}
|
||||
|
||||
// NewBuffer allocates a C-backed buffer that can be passed to C safely.
|
||||
// NewBuffer allocates a C-backed byte buffer for C interop.
|
||||
//
|
||||
// buffer := NewBuffer(32)
|
||||
// input := make([]byte, 32)
|
||||
// buffer := NewBuffer(len(input))
|
||||
// defer buffer.Free()
|
||||
func NewBuffer(size int) *Buffer {
|
||||
if size < 0 {
|
||||
|
|
@ -107,7 +108,7 @@ func (b *Buffer) Bytes() []byte {
|
|||
// Ptr returns the raw pointer to the buffer.
|
||||
//
|
||||
// buffer := NewBuffer(4)
|
||||
// call := buffer.Ptr()
|
||||
// _ = buffer.Ptr()
|
||||
func (b *Buffer) Ptr() unsafe.Pointer {
|
||||
b.assertNotFreed()
|
||||
return b.pointer
|
||||
|
|
@ -116,7 +117,9 @@ func (b *Buffer) Ptr() unsafe.Pointer {
|
|||
// Len returns the allocated byte length of the buffer.
|
||||
//
|
||||
// buffer := NewBuffer(4)
|
||||
// if buffer.Len() == 4 { ... }
|
||||
// if buffer.Len() == 4 {
|
||||
// // preallocated 4-byte buffer
|
||||
// }
|
||||
func (b *Buffer) Len() int {
|
||||
b.assertNotFreed()
|
||||
return b.length
|
||||
|
|
@ -125,7 +128,9 @@ func (b *Buffer) Len() int {
|
|||
// IsFreed reports whether Free has already been called.
|
||||
//
|
||||
// buffer := NewBuffer(4)
|
||||
// if buffer.IsFreed() { ... }
|
||||
// if buffer.IsFreed() {
|
||||
// return
|
||||
// }
|
||||
func (b *Buffer) IsFreed() bool {
|
||||
if b == nil {
|
||||
return true
|
||||
|
|
|
|||
28
scope.go
28
scope.go
|
|
@ -12,20 +12,20 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
// Scope tracks multiple allocations and releases them together.
|
||||
// Scope tracks multiple C allocations and releases them together.
|
||||
//
|
||||
// scope := cgo.NewScope()
|
||||
// defer scope.FreeAll()
|
||||
// buffer := scope.Buffer(32)
|
||||
// cString := scope.CString("hello")
|
||||
// scope := NewScope()
|
||||
// defer scope.FreeAll()
|
||||
// buffer := scope.Buffer(32)
|
||||
// cString := scope.CString("hello")
|
||||
type Scope struct {
|
||||
lock sync.Mutex
|
||||
buffers []*Buffer
|
||||
strings []unsafe.Pointer
|
||||
freed atomic.Bool
|
||||
lock sync.Mutex
|
||||
buffers []*Buffer
|
||||
strings []unsafe.Pointer
|
||||
freed atomic.Bool
|
||||
}
|
||||
|
||||
// NewScope creates a zero-value scope for grouped CGo allocations.
|
||||
// NewScope creates a grouped allocator for temporary C memory.
|
||||
//
|
||||
// scope := NewScope()
|
||||
// defer scope.FreeAll()
|
||||
|
|
@ -37,7 +37,7 @@ func NewScope() *Scope {
|
|||
return scope
|
||||
}
|
||||
|
||||
// Buffer allocates a managed buffer and registers it for scope cleanup.
|
||||
// Buffer allocates a managed buffer and registers it for cleanup.
|
||||
//
|
||||
// buffer := scope.Buffer(64)
|
||||
func (s *Scope) Buffer(size int) *Buffer {
|
||||
|
|
@ -53,7 +53,7 @@ func (s *Scope) Buffer(size int) *Buffer {
|
|||
return buffer
|
||||
}
|
||||
|
||||
// CString allocates a managed C string and registers it for scope cleanup.
|
||||
// CString allocates a managed C string and registers it for cleanup.
|
||||
//
|
||||
// cString := scope.CString("hello")
|
||||
func (s *Scope) CString(value string) *C.char {
|
||||
|
|
@ -102,7 +102,9 @@ func (s *Scope) FreeAll() {
|
|||
|
||||
// IsFreed reports whether FreeAll has been called.
|
||||
//
|
||||
// if scope.IsFreed() { return }
|
||||
// if scope.IsFreed() {
|
||||
// // scope is inactive
|
||||
// }
|
||||
func (s *Scope) IsFreed() bool {
|
||||
if s == nil {
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -100,9 +100,9 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
// SizeT converts a Go int into a C size_t for cgo calls.
|
||||
// SizeT converts a Go int into a C size_t for C APIs.
|
||||
//
|
||||
// size := cgo.SizeT(len(data))
|
||||
// bufferSize := SizeT(len(payload))
|
||||
func SizeT(value int) C.size_t {
|
||||
if value < 0 {
|
||||
panic("cgo.SizeT: negative values are not representable as C.size_t")
|
||||
|
|
@ -120,9 +120,9 @@ func SizeT(value int) C.size_t {
|
|||
return C.size_t(value)
|
||||
}
|
||||
|
||||
// Int converts a Go int into a C int for cgo calls.
|
||||
// Int converts a Go int into a C int for C APIs.
|
||||
//
|
||||
// rc := cgo.Int(returnCode)
|
||||
// remaining := Int(2)
|
||||
func Int(value int) C.int {
|
||||
cIntBits := cIntBitSize()
|
||||
if cIntBits < strconv.IntSize {
|
||||
|
|
@ -140,12 +140,10 @@ func cIntBitSize() int {
|
|||
return int(unsafe.Sizeof(C.int(0)) * 8)
|
||||
}
|
||||
|
||||
// Call invokes a C function pointer and maps a non-zero return into a Go error.
|
||||
// Call invokes a C function pointer and maps a non-zero return code to an error.
|
||||
//
|
||||
// err := Call(unsafe.Pointer(C.some_function), buffer.Ptr(), SizeT(len(data)))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// err := Call(unsafe.Pointer(C.some_function), buffer.Ptr(), SizeT(len(payload)))
|
||||
// if err != nil { return err }
|
||||
func Call(function unsafe.Pointer, args ...interface{}) error {
|
||||
if function == nil {
|
||||
panic("cgo.Call: function pointer is nil")
|
||||
|
|
@ -829,9 +827,7 @@ func toSyscallArg(value interface{}) (uintptr, bool) {
|
|||
|
||||
// GoString converts a null-terminated C string to a Go string.
|
||||
//
|
||||
// cString := CString("example")
|
||||
// result := GoString(cString)
|
||||
// Free(unsafe.Pointer(cString))
|
||||
// native := GoString(CString("hello"))
|
||||
func GoString(cs *C.char) string {
|
||||
if cs == nil {
|
||||
return ""
|
||||
|
|
@ -847,7 +843,7 @@ func CString(value string) *C.char {
|
|||
return C.CString(value)
|
||||
}
|
||||
|
||||
// Free releases memory previously returned by CString.
|
||||
// Free releases memory previously allocated by this package.
|
||||
//
|
||||
// cString := CString("hello")
|
||||
// Free(unsafe.Pointer(cString))
|
||||
|
|
@ -858,9 +854,9 @@ func Free(ptr unsafe.Pointer) {
|
|||
C.free(ptr)
|
||||
}
|
||||
|
||||
// Errno converts a C error number to a Go error.
|
||||
// Errno converts a C errno-like return value to a Go error.
|
||||
//
|
||||
// resultCode := Errno(-2)
|
||||
// err := Errno(C.int(13))
|
||||
func Errno(resultCode C.int) error {
|
||||
if resultCode == 0 {
|
||||
return nil
|
||||
|
|
@ -874,9 +870,9 @@ func Errno(resultCode C.int) error {
|
|||
return syscall.Errno(recordedCode)
|
||||
}
|
||||
|
||||
// WithErrno runs a function that returns C.int and maps the result to Go error.
|
||||
// WithErrno runs a C-style function and converts the C return value to (result, error).
|
||||
//
|
||||
// resultCode, err := WithErrno(func() C.int {
|
||||
// result, err := WithErrno(func() C.int {
|
||||
// return C.my_function()
|
||||
// })
|
||||
func WithErrno(fn func() C.int) (int, error) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue