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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 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
}