You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lal/pkg/base/bufwriter.go

117 lines
2.2 KiB
Go

// Copyright 2021, Chef. All rights reserved.
// https://github.com/q191201771/lal
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package base
// 调用方场景/约定描述:
// - 内部实际写总是全量写成功
// - 外部写调用的内存块,永久有效,调用结束后,外部并不使用
// 内部实际写的内存块,调用结束后,实际写的实现可能还继续持有该内存块
//
// 与bufio.Writer表现不同的地方
// 数据超过缓存容量时bufio.Writer一般会切分成多个缓存容量大小的块实际写BufWriter则可能实际写大数据
type IBufWriter interface {
Write(p []byte)
Flush()
}
type WriterFunc func(p []byte)
func NewWriterFuncSize(wr WriterFunc, size int) IBufWriter {
if size <= 0 {
return &directWriter{
wr: wr,
}
}
b := &bufWriter{
wr: wr,
defaultSize: size,
}
b.mallocOnePiece(size)
return b
}
type bufWriter struct {
wr WriterFunc
defaultSize int // 缓存最大容量
buf []byte
n int // 当前已缓存大小
}
type directWriter struct {
wr WriterFunc
}
func (b *bufWriter) Write(p []byte) {
avail := b.available()
if len(p) > avail {
// 缓存剩余空间不够
if b.n == 0 {
// 缓存完全没有使用,依然空间不够
// 直接发送
b.wr(p)
return
}
// 填满当前缓存块,并发送
b.append(p[:avail])
b.Flush()
// 剩余数据
remain := len(p) - avail
if remain < b.defaultSize {
// 剩余数据较小
// 只追加进入缓存
b.append(p[avail:])
} else {
// 剩余数据较大
// 直接发送
b.wr(p[avail:])
}
return
}
// 缓存剩余空间足够
// 追加进入缓存
b.append(p)
}
func (b *bufWriter) Flush() {
if b.n == 0 {
return
}
b.wr(b.buf[:b.n])
b.mallocOnePiece(b.defaultSize)
}
// 缓存剩余空间
func (b *bufWriter) available() int {
return len(b.buf) - b.n
}
func (b *bufWriter) mallocOnePiece(size int) {
b.buf = make([]byte, size)
b.n = 0
}
func (b *bufWriter) append(p []byte) {
copy(b.buf[b.n:], p)
b.n += len(p)
}
func (dw *directWriter) Write(p []byte) {
dw.wr(p)
}
func (dw *directWriter) Flush() {
// noop
}