mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
Reuse blob buffer.
This commit is contained in:
49
blob.go
49
blob.go
@@ -21,6 +21,8 @@ type Blob struct {
|
|||||||
bytes int64
|
bytes int64
|
||||||
offset int64
|
offset int64
|
||||||
handle uint32
|
handle uint32
|
||||||
|
bufptr uint32
|
||||||
|
buflen int64
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ io.ReadWriteSeeker = &Blob{}
|
var _ io.ReadWriteSeeker = &Blob{}
|
||||||
@@ -66,7 +68,7 @@ func (b *Blob) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
r := b.c.call("sqlite3_blob_close", uint64(b.handle))
|
r := b.c.call("sqlite3_blob_close", uint64(b.handle))
|
||||||
|
b.c.free(b.bufptr)
|
||||||
b.handle = 0
|
b.handle = 0
|
||||||
return b.c.error(r)
|
return b.c.error(r)
|
||||||
}
|
}
|
||||||
@@ -86,17 +88,18 @@ func (b *Blob) Read(p []byte) (n int, err error) {
|
|||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
avail := b.bytes - b.offset
|
|
||||||
want := int64(len(p))
|
want := int64(len(p))
|
||||||
|
avail := b.bytes - b.offset
|
||||||
if want > avail {
|
if want > avail {
|
||||||
want = avail
|
want = avail
|
||||||
}
|
}
|
||||||
|
if want > b.buflen {
|
||||||
defer b.c.arena.mark()()
|
b.bufptr = b.c.realloc(b.bufptr, uint64(want))
|
||||||
ptr := b.c.arena.new(uint64(want))
|
b.buflen = want
|
||||||
|
}
|
||||||
|
|
||||||
r := b.c.call("sqlite3_blob_read", uint64(b.handle),
|
r := b.c.call("sqlite3_blob_read", uint64(b.handle),
|
||||||
uint64(ptr), uint64(want), uint64(b.offset))
|
uint64(b.bufptr), uint64(want), uint64(b.offset))
|
||||||
err = b.c.error(r)
|
err = b.c.error(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -106,7 +109,7 @@ func (b *Blob) Read(p []byte) (n int, err error) {
|
|||||||
err = io.EOF
|
err = io.EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(p, util.View(b.c.mod, ptr, uint64(want)))
|
copy(p, util.View(b.c.mod, b.bufptr, uint64(want)))
|
||||||
return int(want), err
|
return int(want), err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,19 +126,20 @@ func (b *Blob) WriteTo(w io.Writer) (n int64, err error) {
|
|||||||
if want > avail {
|
if want > avail {
|
||||||
want = avail
|
want = avail
|
||||||
}
|
}
|
||||||
|
if want > b.buflen {
|
||||||
defer b.c.arena.mark()()
|
b.bufptr = b.c.realloc(b.bufptr, uint64(want))
|
||||||
ptr := b.c.arena.new(uint64(want))
|
b.buflen = want
|
||||||
|
}
|
||||||
|
|
||||||
for want > 0 {
|
for want > 0 {
|
||||||
r := b.c.call("sqlite3_blob_read", uint64(b.handle),
|
r := b.c.call("sqlite3_blob_read", uint64(b.handle),
|
||||||
uint64(ptr), uint64(want), uint64(b.offset))
|
uint64(b.bufptr), uint64(want), uint64(b.offset))
|
||||||
err = b.c.error(r)
|
err = b.c.error(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mem := util.View(b.c.mod, ptr, uint64(want))
|
mem := util.View(b.c.mod, b.bufptr, uint64(want))
|
||||||
m, err := w.Write(mem[:want])
|
m, err := w.Write(mem[:want])
|
||||||
b.offset += int64(m)
|
b.offset += int64(m)
|
||||||
n += int64(m)
|
n += int64(m)
|
||||||
@@ -159,11 +163,15 @@ func (b *Blob) WriteTo(w io.Writer) (n int64, err error) {
|
|||||||
//
|
//
|
||||||
// https://sqlite.org/c3ref/blob_write.html
|
// https://sqlite.org/c3ref/blob_write.html
|
||||||
func (b *Blob) Write(p []byte) (n int, err error) {
|
func (b *Blob) Write(p []byte) (n int, err error) {
|
||||||
defer b.c.arena.mark()()
|
want := int64(len(p))
|
||||||
ptr := b.c.arena.bytes(p)
|
if want > b.buflen {
|
||||||
|
b.bufptr = b.c.realloc(b.bufptr, uint64(want))
|
||||||
|
b.buflen = want
|
||||||
|
}
|
||||||
|
util.WriteBytes(b.c.mod, b.bufptr, p)
|
||||||
|
|
||||||
r := b.c.call("sqlite3_blob_write", uint64(b.handle),
|
r := b.c.call("sqlite3_blob_write", uint64(b.handle),
|
||||||
uint64(ptr), uint64(len(p)), uint64(b.offset))
|
uint64(b.bufptr), uint64(want), uint64(b.offset))
|
||||||
err = b.c.error(r)
|
err = b.c.error(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -187,16 +195,17 @@ func (b *Blob) ReadFrom(r io.Reader) (n int64, err error) {
|
|||||||
if want < 1 {
|
if want < 1 {
|
||||||
want = 1
|
want = 1
|
||||||
}
|
}
|
||||||
|
if want > b.buflen {
|
||||||
defer b.c.arena.mark()()
|
b.bufptr = b.c.realloc(b.bufptr, uint64(want))
|
||||||
ptr := b.c.arena.new(uint64(want))
|
b.buflen = want
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
mem := util.View(b.c.mod, ptr, uint64(want))
|
mem := util.View(b.c.mod, b.bufptr, uint64(want))
|
||||||
m, err := r.Read(mem[:want])
|
m, err := r.Read(mem[:want])
|
||||||
if m > 0 {
|
if m > 0 {
|
||||||
r := b.c.call("sqlite3_blob_write", uint64(b.handle),
|
r := b.c.call("sqlite3_blob_write", uint64(b.handle),
|
||||||
uint64(ptr), uint64(m), uint64(b.offset))
|
uint64(b.bufptr), uint64(m), uint64(b.offset))
|
||||||
err := b.c.error(r)
|
err := b.c.error(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
|
|||||||
19
sqlite.go
19
sqlite.go
@@ -192,11 +192,16 @@ func (sqlt *sqlite) free(ptr uint32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sqlt *sqlite) new(size uint64) uint32 {
|
func (sqlt *sqlite) new(size uint64) uint32 {
|
||||||
if size == 0 {
|
|
||||||
size = 1
|
|
||||||
}
|
|
||||||
ptr := uint32(sqlt.call("sqlite3_malloc64", size))
|
ptr := uint32(sqlt.call("sqlite3_malloc64", size))
|
||||||
if ptr == 0 {
|
if ptr == 0 && size != 0 {
|
||||||
|
panic(util.OOMErr)
|
||||||
|
}
|
||||||
|
return ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sqlt *sqlite) realloc(ptr uint32, size uint64) uint32 {
|
||||||
|
ptr = uint32(sqlt.call("sqlite3_realloc64", uint64(ptr), size))
|
||||||
|
if ptr == 0 && size != 0 {
|
||||||
panic(util.OOMErr)
|
panic(util.OOMErr)
|
||||||
}
|
}
|
||||||
return ptr
|
return ptr
|
||||||
@@ -206,7 +211,11 @@ func (sqlt *sqlite) newBytes(b []byte) uint32 {
|
|||||||
if (*[0]byte)(b) == nil {
|
if (*[0]byte)(b) == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
ptr := sqlt.new(uint64(len(b)))
|
size := len(b)
|
||||||
|
if size == 0 {
|
||||||
|
size = 1
|
||||||
|
}
|
||||||
|
ptr := sqlt.new(uint64(size))
|
||||||
util.WriteBytes(sqlt.mod, ptr, b)
|
util.WriteBytes(sqlt.mod, ptr, b)
|
||||||
return ptr
|
return ptr
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user