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