package main
import (
"bytes"
"runtime/cgo"
"sync"
"unsafe"
)
type Buffer struct {
mu sync.Mutex
closed bool
buf *bytes.Buffer
handle UintPtrT
}
func BufferFromPtr(id UintPtrT) *Buffer {
hnd := cgo.Handle(id)
buf := hnd.Value().(*Buffer)
return buf
}
func NewBuffer(initBuf []byte) *Buffer {
buf := new(Buffer)
if initBuf != nil {
buf.buf = bytes.NewBuffer(initBuf)
} else {
buf.buf = new(bytes.Buffer)
}
buf.handle = UintPtrT(cgo.NewHandle(buf))
return buf
}
func (buf *Buffer) FreeAlreadyLocked() {
if buf.closed {
return
}
buf.closed = true
(cgo.Handle)(buf.handle).Delete()
}
func CallBufferAlloc(
response_cb MessageCb,
response_usr unsafe.Pointer,
) {
buf := NewBuffer(nil)
MessageCbInvoke(
response_cb,
response_usr,
TyBufferAlloc,
buf.handle,
0,
0,
0,
)
}
func CallBufferFree(id UintPtrT) {
buf := BufferFromPtr(id)
buf.mu.Lock()
defer buf.mu.Unlock()
buf.FreeAlreadyLocked()
}
func CallBufferAccess(
id UintPtrT,
response_cb MessageCb,
response_usr unsafe.Pointer,
) {
buf := BufferFromPtr(id)
buf.mu.Lock()
defer buf.mu.Unlock()
if buf.closed {
panic("BufferClosed")
}
bytes := buf.buf.Bytes()
if bytes == nil || len(bytes) == 0 {
MessageCbInvoke(
response_cb,
response_usr,
TyBufferAccess,
buf.handle,
0,
0,
0,
)
return
}
MessageCbInvoke(
response_cb,
response_usr,
TyBufferAccess,
buf.handle,
VoidStarToPtrT(unsafe.Pointer(&(bytes)[0])),
UintPtrT(len(bytes)),
0,
)
}
func CallBufferReserve(
id UintPtrT,
add UintPtrT,
response_cb MessageCb,
response_usr unsafe.Pointer,
) {
buf := BufferFromPtr(id)
buf.mu.Lock()
defer buf.mu.Unlock()
if buf.closed {
panic("BufferClosed")
}
buf.buf.Grow(int(add))
MessageCbInvoke(
response_cb,
response_usr,
TyBufferReserve,
0,
0,
0,
0,
)
}
func CallBufferExtend(
id UintPtrT,
data UintPtrT,
data_len UintPtrT,
response_cb MessageCb,
response_usr unsafe.Pointer,
) {
buf := BufferFromPtr(id)
buf.mu.Lock()
defer buf.mu.Unlock()
if buf.closed {
panic("BufferClosed")
}
raw := unsafe.Slice(PtrToCharStar(data), data_len)
buf.buf.Write(raw)
MessageCbInvoke(
response_cb,
response_usr,
TyBufferExtend,
0,
0,
0,
0,
)
}
func CallBufferRead(
id UintPtrT,
cnt UintPtrT,
response_cb MessageCb,
response_usr unsafe.Pointer,
) {
buf := BufferFromPtr(id)
buf.mu.Lock()
defer buf.mu.Unlock()
if buf.closed {
panic("BufferClosed")
}
bytes := buf.buf.Next(int(cnt))
if bytes == nil || len(bytes) == 0 {
MessageCbInvoke(
response_cb,
response_usr,
TyBufferRead,
0,
0,
0,
0,
)
return
}
MessageCbInvoke(
response_cb,
response_usr,
TyBufferRead,
VoidStarToPtrT(unsafe.Pointer(&(bytes)[0])),
UintPtrT(len(bytes)),
0,
0,
)
}