Merge pull request '[agent/codex:gpt-5.3-codex-spark] Read docs/RFC.md fully. Find ONE feature described in the sp...' (#15) from main into dev
This commit is contained in:
commit
8705a6be8b
3 changed files with 63 additions and 24 deletions
36
buffer.go
36
buffer.go
|
|
@ -8,10 +8,10 @@ import (
|
|||
|
||||
// Buffer owns byte memory that can be passed safely to C.
|
||||
//
|
||||
// buffer := NewBuffer(16)
|
||||
// defer buffer.Free()
|
||||
// n := buffer.CopyFrom([]byte("payload"))
|
||||
// _ = buffer.Bytes()[:n]
|
||||
// buffer := NewBuffer(16)
|
||||
// defer buffer.Free()
|
||||
// n := buffer.CopyFrom([]byte("payload"))
|
||||
// _ = buffer.Bytes()[:n]
|
||||
type Buffer struct {
|
||||
data []byte
|
||||
length int
|
||||
|
|
@ -21,7 +21,10 @@ type Buffer struct {
|
|||
pinner runtime.Pinner
|
||||
}
|
||||
|
||||
// NewBuffer allocates memory and pins it so Ptr can be used across C boundaries.
|
||||
// NewBuffer allocates memory and pins it so Ptr can be safely shared with C.
|
||||
//
|
||||
// buffer := NewBuffer(32)
|
||||
// defer buffer.Free()
|
||||
func NewBuffer(size int) *Buffer {
|
||||
if size < 0 {
|
||||
panic("cgo.NewBuffer: size must be non-negative")
|
||||
|
|
@ -43,6 +46,9 @@ func NewBuffer(size int) *Buffer {
|
|||
}
|
||||
|
||||
// Free releases the pinned memory backing slice and marks the buffer as freed.
|
||||
//
|
||||
// buffer := NewBuffer(8)
|
||||
// defer buffer.Free()
|
||||
func (b *Buffer) Free() {
|
||||
if b == nil {
|
||||
return
|
||||
|
|
@ -62,6 +68,9 @@ func (b *Buffer) Free() {
|
|||
}
|
||||
|
||||
// CopyFrom copies bytes from src into the buffer and returns bytes copied.
|
||||
//
|
||||
// buffer := NewBuffer(3)
|
||||
// buffer.CopyFrom([]byte("abc"))
|
||||
func (b *Buffer) CopyFrom(src []byte) int {
|
||||
b.assertNotFreed()
|
||||
if len(src) == 0 || b.length == 0 {
|
||||
|
|
@ -77,25 +86,38 @@ func (b *Buffer) CopyFrom(src []byte) int {
|
|||
return copied
|
||||
}
|
||||
|
||||
// Bytes returns a mutable byte slice backed by the buffer memory.
|
||||
// Bytes returns the mutable byte slice backed by the buffer memory.
|
||||
//
|
||||
// buffer := NewBuffer(4)
|
||||
// n := buffer.CopyFrom([]byte("go"))
|
||||
// _ = buffer.Bytes()[:n]
|
||||
func (b *Buffer) Bytes() []byte {
|
||||
b.assertNotFreed()
|
||||
return b.data
|
||||
}
|
||||
|
||||
// Ptr returns the raw pointer to the buffer.
|
||||
//
|
||||
// buffer := NewBuffer(4)
|
||||
// call := buffer.Ptr()
|
||||
func (b *Buffer) Ptr() unsafe.Pointer {
|
||||
b.assertNotFreed()
|
||||
return b.pointer
|
||||
}
|
||||
|
||||
// Len returns the current buffer length.
|
||||
// Len returns the allocated byte length of the buffer.
|
||||
//
|
||||
// buffer := NewBuffer(4)
|
||||
// if buffer.Len() == 4 { ... }
|
||||
func (b *Buffer) Len() int {
|
||||
b.assertNotFreed()
|
||||
return b.length
|
||||
}
|
||||
|
||||
// IsFreed reports whether Free has already been called.
|
||||
//
|
||||
// buffer := NewBuffer(4)
|
||||
// if buffer.IsFreed() { ... }
|
||||
func (b *Buffer) IsFreed() bool {
|
||||
return b.freed.Load()
|
||||
}
|
||||
|
|
|
|||
19
scope.go
19
scope.go
|
|
@ -25,11 +25,16 @@ type Scope struct {
|
|||
}
|
||||
|
||||
// NewScope creates a zero-value scope for grouped CGo allocations.
|
||||
//
|
||||
// scope := NewScope()
|
||||
// defer scope.FreeAll()
|
||||
func NewScope() *Scope {
|
||||
return &Scope{}
|
||||
}
|
||||
|
||||
// Buffer allocates a new managed buffer.
|
||||
// Buffer allocates a managed buffer and registers it for scope cleanup.
|
||||
//
|
||||
// buffer := scope.Buffer(64)
|
||||
func (s *Scope) Buffer(size int) *Buffer {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
|
@ -43,7 +48,9 @@ func (s *Scope) Buffer(size int) *Buffer {
|
|||
return buffer
|
||||
}
|
||||
|
||||
// CString allocates a managed C string.
|
||||
// CString allocates a managed C string and registers it for scope cleanup.
|
||||
//
|
||||
// cString := scope.CString("hello")
|
||||
func (s *Scope) CString(value string) *C.char {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
|
@ -58,6 +65,9 @@ func (s *Scope) CString(value string) *C.char {
|
|||
}
|
||||
|
||||
// FreeAll releases every allocation created under this scope.
|
||||
//
|
||||
// scope := NewScope()
|
||||
// defer scope.FreeAll()
|
||||
func (s *Scope) FreeAll() {
|
||||
if s == nil {
|
||||
return
|
||||
|
|
@ -86,6 +96,8 @@ func (s *Scope) FreeAll() {
|
|||
}
|
||||
|
||||
// IsFreed reports whether FreeAll has been called.
|
||||
//
|
||||
// if scope.IsFreed() { return }
|
||||
func (s *Scope) IsFreed() bool {
|
||||
if s == nil {
|
||||
return true
|
||||
|
|
@ -94,6 +106,9 @@ func (s *Scope) IsFreed() bool {
|
|||
}
|
||||
|
||||
// Close releases every allocation in the scope and implements io.Closer.
|
||||
//
|
||||
// scope := NewScope()
|
||||
// defer scope.Close()
|
||||
func (s *Scope) Close() error {
|
||||
s.FreeAll()
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -139,10 +139,12 @@ 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 using errno mapping.
|
||||
// Call invokes a C function pointer and maps a non-zero return into a Go error.
|
||||
//
|
||||
// err := cgo.Call(unsafe.Pointer(C.some_function), cgo.SizeT(len(data)))
|
||||
// err == nil indicates success.
|
||||
// err := Call(unsafe.Pointer(C.some_function), buffer.Ptr(), SizeT(len(data)))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
func Call(function unsafe.Pointer, args ...interface{}) error {
|
||||
if function == nil {
|
||||
panic("cgo.Call: function pointer is nil")
|
||||
|
|
@ -795,9 +797,9 @@ func toSyscallArg(value interface{}) (uintptr, bool) {
|
|||
|
||||
// GoString converts a null-terminated C string to a Go string.
|
||||
//
|
||||
// cStr := C.CString("example")
|
||||
// result := cgo.GoString(cStr)
|
||||
// cgo.Free(unsafe.Pointer(cStr))
|
||||
// cString := CString("example")
|
||||
// result := GoString(cString)
|
||||
// Free(unsafe.Pointer(cString))
|
||||
func GoString(cs *C.char) string {
|
||||
if cs == nil {
|
||||
return ""
|
||||
|
|
@ -807,16 +809,16 @@ func GoString(cs *C.char) string {
|
|||
|
||||
// CString converts a Go string to a C string.
|
||||
//
|
||||
// cStr := cgo.CString("hello")
|
||||
// defer cgo.Free(unsafe.Pointer(cStr))
|
||||
// cString := CString("hello")
|
||||
// defer Free(unsafe.Pointer(cString))
|
||||
func CString(value string) *C.char {
|
||||
return C.CString(value)
|
||||
}
|
||||
|
||||
// Free releases memory previously returned by CString.
|
||||
//
|
||||
// cStr := cgo.CString("hello")
|
||||
// cgo.Free(unsafe.Pointer(cStr))
|
||||
// cString := CString("hello")
|
||||
// Free(unsafe.Pointer(cString))
|
||||
func Free(ptr unsafe.Pointer) {
|
||||
if ptr == nil {
|
||||
return
|
||||
|
|
@ -826,17 +828,17 @@ func Free(ptr unsafe.Pointer) {
|
|||
|
||||
// Errno converts a C error number to a Go error.
|
||||
//
|
||||
// rc := cgo.Errno(-2)
|
||||
func Errno(rc C.int) error {
|
||||
if rc == 0 {
|
||||
// resultCode := Errno(-2)
|
||||
func Errno(resultCode C.int) error {
|
||||
if resultCode == 0 {
|
||||
return nil
|
||||
}
|
||||
return syscall.Errno(rc)
|
||||
return syscall.Errno(resultCode)
|
||||
}
|
||||
|
||||
// WithErrno runs a function that returns C.int and maps the result to Go error.
|
||||
//
|
||||
// result, err := cgo.WithErrno(func() C.int {
|
||||
// resultCode, 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