mirror of
https://github.com/soypat/lneto.git
synced 2026-08-12 02:43:44 +00:00
unexport kvBuffer
This commit is contained in:
@@ -7,11 +7,11 @@ import (
|
||||
// Cookie implements cookie key-value parsing. Methods function similarly to eponymous [Header] methods.
|
||||
// Cookie represents a single-line Cookie header value in a HTTP header, much like the standard library Cookie.
|
||||
type Cookie struct {
|
||||
kv KVBuffer
|
||||
kv kvBuffer
|
||||
}
|
||||
|
||||
// EnableBufferGrowth allows the cookie's buffer to grow past what [Cookie.Reset] was
|
||||
// handed. See [KVBuffer.EnableBufferGrowth].
|
||||
// handed. See [kvBuffer.EnableBufferGrowth].
|
||||
func (c *Cookie) EnableBufferGrowth(enableBufferGrowth bool) {
|
||||
c.kv.EnableBufferGrowth(enableBufferGrowth)
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ package httpraw
|
||||
// undecoded, until [Form.Decode] rewrites them in place. The caller bounds the
|
||||
// data: Form parses the buffer it is handed and reads nothing more.
|
||||
type Form struct {
|
||||
kv KVBuffer
|
||||
kv kvBuffer
|
||||
}
|
||||
|
||||
// EnableBufferGrowth allows the form's buffer to grow past what [Form.Reset] was
|
||||
// handed. See [KVBuffer.EnableBufferGrowth].
|
||||
// handed. See [kvBuffer.EnableBufferGrowth].
|
||||
func (f *Form) EnableBufferGrowth(enableGrowth bool) { f.kv.EnableBufferGrowth(enableGrowth) }
|
||||
|
||||
// Reset discards parsed pairs and sets the buffer to parse in place.
|
||||
|
||||
+51
-51
@@ -8,23 +8,23 @@ import (
|
||||
"github.com/soypat/lneto/internal"
|
||||
)
|
||||
|
||||
// KVBuffer is a common key-value store engine for Cookie, Form, Header and other HTTP abstractions that need
|
||||
// kvBuffer is a common key-value store engine for Cookie, Form, Header and other HTTP abstractions that need
|
||||
// a key-value store with underlying buffer memory.
|
||||
type KVBuffer struct {
|
||||
type kvBuffer struct {
|
||||
buf []byte
|
||||
kvs []argsKV
|
||||
flags Flags
|
||||
}
|
||||
|
||||
func (mb *KVBuffer) free() int { return cap(mb.buf) - len(mb.buf) }
|
||||
func (mb *kvBuffer) free() int { return cap(mb.buf) - len(mb.buf) }
|
||||
|
||||
// BufferRaw returns the underlying buffer, its length being the portion in use.
|
||||
// Stored pairs alias it, so writing to it mangles them.
|
||||
func (mb *KVBuffer) BufferRaw() []byte { return mb.buf }
|
||||
func (mb *kvBuffer) BufferRaw() []byte { return mb.buf }
|
||||
|
||||
// EnableBufferGrowth allows the buffer to grow past the memory [KVBuffer.Reset]
|
||||
// EnableBufferGrowth allows the buffer to grow past the memory [kvBuffer.Reset]
|
||||
// was handed. The setting outlives Reset; with growth off callers get [ErrBufferExhausted].
|
||||
func (mb *KVBuffer) EnableBufferGrowth(enableGrowth bool) {
|
||||
func (mb *kvBuffer) EnableBufferGrowth(enableGrowth bool) {
|
||||
if enableGrowth {
|
||||
mb.flags &^= flagNoBufferGrow
|
||||
} else {
|
||||
@@ -32,14 +32,14 @@ func (mb *KVBuffer) EnableBufferGrowth(enableGrowth bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (mb *KVBuffer) discardKVs() { mb.kvs = mb.kvs[:0] }
|
||||
func (mb *kvBuffer) discardKVs() { mb.kvs = mb.kvs[:0] }
|
||||
|
||||
// BufferGrowthEnabled reports whether the buffer may grow, see [KVBuffer.EnableBufferGrowth].
|
||||
func (mb *KVBuffer) BufferGrowthEnabled() bool { return !mb.flags.HasAny(flagNoBufferGrow) }
|
||||
// BufferGrowthEnabled reports whether the buffer may grow, see [kvBuffer.EnableBufferGrowth].
|
||||
func (mb *kvBuffer) BufferGrowthEnabled() bool { return !mb.flags.HasAny(flagNoBufferGrow) }
|
||||
|
||||
// ReadFromBytes appends buf to the underlying buffer, accumulating data to parse.
|
||||
// Returns [ErrBufferExhausted] when buf does not fit and growth is disabled.
|
||||
func (mb *KVBuffer) ReadFromBytes(buf []byte) error {
|
||||
func (mb *kvBuffer) ReadFromBytes(buf []byte) error {
|
||||
if len(buf) == 0 {
|
||||
return io.ErrNoProgress // Nothing handed over, not a buffer problem.
|
||||
} else if mb.flags.HasAny(flagMangledBuffer) {
|
||||
@@ -57,7 +57,7 @@ func (mb *KVBuffer) ReadFromBytes(buf []byte) error {
|
||||
|
||||
// ReadLimited appends at most limit bytes read from r to the underlying buffer.
|
||||
// A read returning data alongside [io.EOF] reports a nil error, later ones io.EOF.
|
||||
func (mb *KVBuffer) ReadLimited(r io.Reader, limit int) (int, error) {
|
||||
func (mb *kvBuffer) ReadLimited(r io.Reader, limit int) (int, error) {
|
||||
free := mb.free()
|
||||
growthEnabled := mb.BufferGrowthEnabled()
|
||||
if !growthEnabled && (free == 0 || free < limit) || len(mb.buf) >= maxBufLen {
|
||||
@@ -83,7 +83,7 @@ func (mb *KVBuffer) ReadLimited(r io.Reader, limit int) (int, error) {
|
||||
|
||||
// Reset discards all pairs and takes buf as the buffer to parse in place, nil
|
||||
// reusing the current one. kvCap sizes the pair table. Only the growth setting survives.
|
||||
func (mb *KVBuffer) Reset(buf []byte, kvCap int) {
|
||||
func (mb *kvBuffer) Reset(buf []byte, kvCap int) {
|
||||
if buf == nil {
|
||||
mb.buf = mb.buf[:0]
|
||||
} else {
|
||||
@@ -95,7 +95,7 @@ func (mb *KVBuffer) Reset(buf []byte, kvCap int) {
|
||||
|
||||
// CopyFrom replaces the receiver's contents with a copy of src, sharing no
|
||||
// memory with it afterwards.
|
||||
func (mb *KVBuffer) CopyFrom(src *KVBuffer) {
|
||||
func (mb *kvBuffer) CopyFrom(src *kvBuffer) {
|
||||
mb.buf = append(mb.buf[:0], src.buf...)
|
||||
mb.kvs = append(mb.kvs[:0], src.kvs...)
|
||||
}
|
||||
@@ -103,8 +103,8 @@ func (mb *KVBuffer) CopyFrom(src *KVBuffer) {
|
||||
// Get returns the value of the first pair matching key.
|
||||
// Bytes are compared as stored, so if using a Form call [Form.Decode] first when keys may be encoded.
|
||||
// Returns nil for an absent key and for a valueless pair alike, so use
|
||||
// [KVBuffer.Present] to tell the two apart.
|
||||
func (mb *KVBuffer) Get(key string) []byte {
|
||||
// [kvBuffer.Present] to tell the two apart.
|
||||
func (mb *kvBuffer) Get(key string) []byte {
|
||||
i := mb.getIdx(key)
|
||||
if i < 0 {
|
||||
return nil
|
||||
@@ -113,7 +113,7 @@ func (mb *KVBuffer) Get(key string) []byte {
|
||||
}
|
||||
|
||||
// ForEach iterates over the cookie's key-value pairs as stored until cb returns false.
|
||||
func (c *KVBuffer) ForEach(cb func(key, value []byte) bool) {
|
||||
func (c *kvBuffer) ForEach(cb func(key, value []byte) bool) {
|
||||
nc := len(c.kvs)
|
||||
for i := range nc {
|
||||
if !c.kvs[i].isValid() {
|
||||
@@ -125,12 +125,12 @@ func (c *KVBuffer) ForEach(cb func(key, value []byte) bool) {
|
||||
}
|
||||
|
||||
// Has returns true if key is present, with or without a value.
|
||||
func (mb *KVBuffer) Present(key string) bool { // TODO: rename to Has.
|
||||
func (mb *kvBuffer) Present(key string) bool { // TODO: rename to Has.
|
||||
return mb.getIdx(key) >= 0
|
||||
}
|
||||
|
||||
// Has returns true if key is present, with or without a value.
|
||||
func (mb *KVBuffer) HasKeyValue(key, value string) bool {
|
||||
func (mb *kvBuffer) HasKeyValue(key, value string) bool {
|
||||
idx := mb.getIdx(key)
|
||||
if idx >= 0 {
|
||||
return b2s(mb.musttoken(mb.kvs[idx].value)) == value
|
||||
@@ -138,22 +138,22 @@ func (mb *KVBuffer) HasKeyValue(key, value string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Add appends a pair, keeping any already sharing the key: use [KVBuffer.Set]
|
||||
// Add appends a pair, keeping any already sharing the key: use [kvBuffer.Set]
|
||||
// to replace instead. Reports false if the buffer could not hold it.
|
||||
func (mb *KVBuffer) Add(key, value string) (enoughSpace bool) {
|
||||
func (mb *kvBuffer) Add(key, value string) (enoughSpace bool) {
|
||||
mb.appendPair(key, value)
|
||||
return mb.getIdx(key) >= 0
|
||||
}
|
||||
|
||||
// Set replaces key's value and invalidates every other pair sharing the key, so
|
||||
// a following [KVBuffer.Get] sees exactly one value.
|
||||
// a following [kvBuffer.Get] sees exactly one value.
|
||||
//
|
||||
// It rewrites in place when it can: of the pairs it would invalidate it keeps
|
||||
// the smallest whose key and value regions both still hold the new pair,
|
||||
// leaving the roomier regions for a later Set. When none fits the pair is
|
||||
// appended with [KVBuffer.Add] and the invalidated regions are stranded, since
|
||||
// appended with [kvBuffer.Add] and the invalidated regions are stranded, since
|
||||
// nothing here compacts the buffer.
|
||||
func (mb *KVBuffer) Set(key, value string) (enoughSpace bool) {
|
||||
func (mb *kvBuffer) Set(key, value string) (enoughSpace bool) {
|
||||
reuse := mb.takeReusableSlot(key, len(key), len(value))
|
||||
if reuse < 0 {
|
||||
return mb.Add(key, value)
|
||||
@@ -162,9 +162,9 @@ func (mb *KVBuffer) Set(key, value string) (enoughSpace bool) {
|
||||
return true
|
||||
}
|
||||
|
||||
// SetInt is [KVBuffer.Set]'s integer counterpart. It formats value straight into
|
||||
// SetInt is [kvBuffer.Set]'s integer counterpart. It formats value straight into
|
||||
// the slot it reuses, so overwriting a pair never allocates.
|
||||
func (mb *KVBuffer) SetInt(key string, value int64, base int) (enoughSpace bool) {
|
||||
func (mb *kvBuffer) SetInt(key string, value int64, base int) (enoughSpace bool) {
|
||||
reuse := mb.takeReusableSlot(key, len(key), internal.IntLen(value, base))
|
||||
if reuse < 0 {
|
||||
return mb.appendPairInt(key, value, base)
|
||||
@@ -184,7 +184,7 @@ func (mb *KVBuffer) SetInt(key string, value int64, base int) (enoughSpace bool)
|
||||
// whose key and value regions hold keyLen and valueLen bytes, whose index it
|
||||
// returns. It returns -1 when no surviving slot fits, meaning the caller must
|
||||
// append instead.
|
||||
func (mb *KVBuffer) takeReusableSlot(key string, keyLen, valueLen int) int {
|
||||
func (mb *kvBuffer) takeReusableSlot(key string, keyLen, valueLen int) int {
|
||||
reuse := -1
|
||||
for i := range mb.kvs {
|
||||
kv := &mb.kvs[i]
|
||||
@@ -210,7 +210,7 @@ func (mb *KVBuffer) takeReusableSlot(key string, keyLen, valueLen int) int {
|
||||
// overwriteAt writes key and value over the regions pair i already owns. The
|
||||
// caller must have checked both fit; the bytes freed by a shorter pair are
|
||||
// stranded, not reclaimed.
|
||||
func (mb *KVBuffer) overwriteAt(i int, key, value string) {
|
||||
func (mb *kvBuffer) overwriteAt(i int, key, value string) {
|
||||
mb.flags |= flagMangledBuffer
|
||||
kv := &mb.kvs[i]
|
||||
copy(mb.buf[kv.key.start:], key)
|
||||
@@ -219,7 +219,7 @@ func (mb *KVBuffer) overwriteAt(i int, key, value string) {
|
||||
kv.value.len = tokint(len(value))
|
||||
}
|
||||
|
||||
func (mb *KVBuffer) setInternal(key, value []byte) (enoughSpace bool) {
|
||||
func (mb *kvBuffer) setInternal(key, value []byte) (enoughSpace bool) {
|
||||
if !mb.canAddOneKV() {
|
||||
return false
|
||||
}
|
||||
@@ -231,19 +231,19 @@ func (mb *KVBuffer) setInternal(key, value []byte) (enoughSpace bool) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Len returns the number of slots stored, counting those [KVBuffer.Set] invalidated.
|
||||
func (mb *KVBuffer) Len() int { return len(mb.kvs) }
|
||||
// Len returns the number of slots stored, counting those [kvBuffer.Set] invalidated.
|
||||
func (mb *kvBuffer) Len() int { return len(mb.kvs) }
|
||||
|
||||
// At returns the i'th pair in wire order. value is nil for a pair holding none,
|
||||
// which is what tells a form's "ok" from "ok=".
|
||||
func (mb *KVBuffer) At(i int) (key, value []byte) {
|
||||
func (mb *kvBuffer) At(i int) (key, value []byte) {
|
||||
kv := mb.kvs[i]
|
||||
if !kv.HasValue() {
|
||||
return mb.musttoken(kv.key), nil
|
||||
}
|
||||
return mb.musttoken(kv.key), mb.musttoken(kv.value)
|
||||
}
|
||||
func (mb *KVBuffer) setAt(i int, k, v []byte) {
|
||||
func (mb *kvBuffer) setAt(i int, k, v []byte) {
|
||||
mb.flags |= flagMangledBuffer
|
||||
// Route through slice, not bytes2tok: a nil v is a pair with no '=' and must
|
||||
// stay absent rather than trip the alias check on a nil pointer.
|
||||
@@ -253,18 +253,18 @@ func (mb *KVBuffer) setAt(i int, k, v []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
// AtKey is [KVBuffer.At] limited to the i'th key.
|
||||
func (mb *KVBuffer) AtKey(i int) (key []byte) { return mb.musttoken(mb.kvs[i].key) }
|
||||
// AtKey is [kvBuffer.At] limited to the i'th key.
|
||||
func (mb *kvBuffer) AtKey(i int) (key []byte) { return mb.musttoken(mb.kvs[i].key) }
|
||||
|
||||
// AtValue is [KVBuffer.At] limited to the i'th value, nil when the pair holds none.
|
||||
func (mb *KVBuffer) AtValue(i int) (key []byte) {
|
||||
// AtValue is [kvBuffer.At] limited to the i'th value, nil when the pair holds none.
|
||||
func (mb *kvBuffer) AtValue(i int) (key []byte) {
|
||||
if !mb.kvs[i].HasValue() {
|
||||
return nil
|
||||
}
|
||||
return mb.musttoken(mb.kvs[i].value)
|
||||
}
|
||||
|
||||
func (mb *KVBuffer) getIdx(key string) int {
|
||||
func (mb *kvBuffer) getIdx(key string) int {
|
||||
for i, kv := range mb.kvs {
|
||||
if kv.isValid() && b2s(mb.musttoken(kv.key)) == key {
|
||||
return i
|
||||
@@ -278,7 +278,7 @@ func (mb *KVBuffer) getIdx(key string) int {
|
||||
// mustAppendSlice). It returns false and sets flagOOMReached when the space
|
||||
// cannot be guaranteed: a tokint offset overflow, or a full buffer with
|
||||
// flagNoBufferGrow set.
|
||||
func (mb *KVBuffer) reserve(need int) (enoughSpace bool) {
|
||||
func (mb *kvBuffer) reserve(need int) (enoughSpace bool) {
|
||||
if len(mb.buf) == 0 {
|
||||
need++ // mustAppend* reserves byte 0 on an empty buffer.
|
||||
}
|
||||
@@ -296,7 +296,7 @@ func (mb *KVBuffer) reserve(need int) (enoughSpace bool) {
|
||||
return true
|
||||
}
|
||||
|
||||
func (mb *KVBuffer) appendPair(key, value string) bool {
|
||||
func (mb *kvBuffer) appendPair(key, value string) bool {
|
||||
if !mb.canAddOneKV() || !mb.reserve(len(key)+len(value)) {
|
||||
return false
|
||||
}
|
||||
@@ -308,7 +308,7 @@ func (mb *KVBuffer) appendPair(key, value string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (mb *KVBuffer) appendPairInt(key string, value int64, base int) bool {
|
||||
func (mb *kvBuffer) appendPairInt(key string, value int64, base int) bool {
|
||||
vlen := internal.IntLen(value, base)
|
||||
if !mb.canAddOneKV() || !mb.reserve(len(key)+vlen) {
|
||||
return false
|
||||
@@ -321,11 +321,11 @@ func (mb *KVBuffer) appendPairInt(key string, value int64, base int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (mb *KVBuffer) canAddOneKV() (enoughSpace bool) {
|
||||
func (mb *kvBuffer) canAddOneKV() (enoughSpace bool) {
|
||||
return len(mb.kvs) < cap(mb.kvs) || mb.flags&flagNoBufferGrow == 0
|
||||
}
|
||||
|
||||
func (mb *KVBuffer) mustAppendSlice(value string) headerSlice {
|
||||
func (mb *kvBuffer) mustAppendSlice(value string) headerSlice {
|
||||
L := len(mb.buf)
|
||||
if L == 0 {
|
||||
L++ // Valid key-values start after 0.
|
||||
@@ -335,7 +335,7 @@ func (mb *KVBuffer) mustAppendSlice(value string) headerSlice {
|
||||
return mb.slice(mb.buf[L : L+len(value)])
|
||||
}
|
||||
|
||||
func (hb *KVBuffer) mustAppendInt(value int64, base int) headerSlice {
|
||||
func (hb *kvBuffer) mustAppendInt(value int64, base int) headerSlice {
|
||||
L := len(hb.buf)
|
||||
if L == 0 {
|
||||
L++ // Valid key-values start after byte 0.
|
||||
@@ -347,7 +347,7 @@ func (hb *KVBuffer) mustAppendInt(value int64, base int) headerSlice {
|
||||
|
||||
// reuseOrAppend writes value over tok's slot when it fits there, avoiding any
|
||||
// buffer growth; otherwise it appends a fresh slot.
|
||||
func (mb *KVBuffer) reuseOrAppend(tok headerSlice, value string) headerSlice {
|
||||
func (mb *kvBuffer) reuseOrAppend(tok headerSlice, value string) headerSlice {
|
||||
if tok.len > tokint(len(value)) {
|
||||
copy(mb.musttoken(tok), value)
|
||||
tok.len = tokint(len(value))
|
||||
@@ -358,7 +358,7 @@ func (mb *KVBuffer) reuseOrAppend(tok headerSlice, value string) headerSlice {
|
||||
|
||||
// appendSlice reserves space (growing or flagging OOM) and appends value as a
|
||||
// new slot.
|
||||
func (mb *KVBuffer) appendSlice(value string) headerSlice {
|
||||
func (mb *kvBuffer) appendSlice(value string) headerSlice {
|
||||
debuglog("http:appendslice:start")
|
||||
if !mb.reserve(len(value)) {
|
||||
return headerSlice{} // Drop and flag OOM; never panic.
|
||||
@@ -367,8 +367,8 @@ func (mb *KVBuffer) appendSlice(value string) headerSlice {
|
||||
return mb.mustAppendSlice(value)
|
||||
}
|
||||
|
||||
// reuseOrAppendInt is [KVBuffer.reuseOrAppend]'s integer counterpart.
|
||||
func (mb *KVBuffer) reuseOrAppendInt(tok headerSlice, value int64, base int) headerSlice {
|
||||
// reuseOrAppendInt is [kvBuffer.reuseOrAppend]'s integer counterpart.
|
||||
func (mb *kvBuffer) reuseOrAppendInt(tok headerSlice, value int64, base int) headerSlice {
|
||||
n := internal.IntLen(value, base)
|
||||
if int(tok.len) >= n {
|
||||
// Reuse: format directly over the existing slot. No free space needed
|
||||
@@ -382,7 +382,7 @@ func (mb *KVBuffer) reuseOrAppendInt(tok headerSlice, value int64, base int) hea
|
||||
}
|
||||
|
||||
// appendInt reserves space (growing or flagging OOM) and appends value as a new slot.
|
||||
func (mb *KVBuffer) appendInt(value int64, base, n int) headerSlice {
|
||||
func (mb *kvBuffer) appendInt(value int64, base, n int) headerSlice {
|
||||
if !mb.reserve(n) {
|
||||
return headerSlice{} // Drop and flag OOM; never panic.
|
||||
}
|
||||
@@ -390,17 +390,17 @@ func (mb *KVBuffer) appendInt(value int64, base, n int) headerSlice {
|
||||
return mb.mustAppendInt(value, base)
|
||||
}
|
||||
|
||||
func (mb *KVBuffer) slice(value []byte) headerSlice {
|
||||
func (mb *kvBuffer) slice(value []byte) headerSlice {
|
||||
if value == nil {
|
||||
return headerSlice{}
|
||||
}
|
||||
return bytes2tok(mb.buf, value)
|
||||
}
|
||||
|
||||
func (mb KVBuffer) musttoken(slice headerSlice) []byte {
|
||||
func (mb kvBuffer) musttoken(slice headerSlice) []byte {
|
||||
return tok2bytes(mb.buf, slice)
|
||||
}
|
||||
func (mb *KVBuffer) noKV() argsKV { return argsKV{} }
|
||||
func (mb *kvBuffer) noKV() argsKV { return argsKV{} }
|
||||
|
||||
type tokint = uint16
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ var (
|
||||
const maxBufLen = 0xffff
|
||||
|
||||
type headerBuf struct {
|
||||
kv KVBuffer
|
||||
kv kvBuffer
|
||||
// buf[:len] holds entire HTTP header data, which may be normalized by [flags]. buf[off:len] holds data not yet processed during parsing.
|
||||
// buf []byte
|
||||
// offset into buf for parsing.
|
||||
|
||||
Reference in New Issue
Block a user