1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-12-23 22:11:10 +02:00
Files
imgproxy/logger/buffer.go
2025-09-21 20:13:27 +06:00

224 lines
4.4 KiB
Go

package logger
import (
"strconv"
"sync"
"unicode/utf8"
)
var bufPool = sync.Pool{
New: func() interface{} {
// Reserve some capacity to not re-allocate on short logs.
buf := make(buffer, 0, 1024)
return &buf
},
}
// buffer is a slice of bytes with some additional convenience methods.
type buffer []byte
// newBuffer creates a new buffer from the pool.
func newBuffer() *buffer {
return bufPool.Get().(*buffer)
}
// free truncates the buffer and returns it to the pool.
func (b *buffer) free() {
// Don't keep large buffers around.
if len(*b) > 16*1024 {
return
}
*b = (*b)[:0]
bufPool.Put(b)
}
// Write writes data to the buffer.
func (b *buffer) Write(p []byte) (n int, err error) {
b.append(p...)
return len(p), nil
}
// String returns the contents of the buffer as a string.
func (b *buffer) String() string {
return string(*b)
}
// len returns the number of bytes written to the buffer.
func (b *buffer) len() int {
return len(*b)
}
// append appends data to the buffer.
func (b *buffer) append(data ...byte) {
*b = append(*b, data...)
}
// appendString appends a string value to the buffer.
// If the string does not require escaping, it is appended directly.
// Otherwise, it is escaped and quoted.
func (b *buffer) appendString(data string) {
if b.isStringQuoteSafe(data) {
b.appendStringRaw(data)
} else {
b.appendStringQuoted(data)
}
}
// appendStringRaw appends a string value to the buffer without escaping.
func (b *buffer) appendStringRaw(data string) {
*b = append(*b, data...)
}
// appendStringQuoted appends a string value to the buffer, escaping and quoting it as necessary.
func (b *buffer) appendStringQuoted(data string) {
*b = strconv.AppendQuote(*b, data)
}
// appendInt appends an integer value to the buffer.
func (b *buffer) appendInt(data int64) {
*b = strconv.AppendInt(*b, data, 10)
}
// appendUint appends an unsigned integer value to the buffer.
func (b *buffer) appendUint(data uint64) {
*b = strconv.AppendUint(*b, data, 10)
}
// appendFloat appends a float value to the buffer.
func (b *buffer) appendFloat(data float64) {
*b = strconv.AppendFloat(*b, data, 'g', -1, 64)
}
// appendBool appends a boolean value to the buffer.
func (b *buffer) appendBool(data bool) {
*b = strconv.AppendBool(*b, data)
}
// remove removes the last n bytes from the buffer.
func (b *buffer) remove(n int) {
n = max(0, n)
trimTo := max(0, len(*b)-n)
*b = (*b)[:trimTo]
}
// removeNewline removes the trailing newline character from the buffer, if present.
func (b *buffer) removeNewline() {
if len(*b) > 0 && (*b)[len(*b)-1] == '\n' {
*b = (*b)[:len(*b)-1]
}
}
// isStringQuoteSafe checks if a string is safe to append without quoting.
func (b *buffer) isStringQuoteSafe(val string) bool {
for i := 0; i < len(val); i++ {
if b := val[i]; b >= utf8.RuneSelf || !quoteSafeSet[b] {
return false
}
}
return true
}
// quoteSafeSet is a set of runes that are safe to append without quoting.
// Some runes here are explicitly marked as unsafe for clarity.
// The unlisted runes are considered unsafe by default.
// Shamesly stolen from https://github.com/golang/go/blob/master/src/encoding/json/tables.go
// and tuned for our needs.
var quoteSafeSet = [utf8.RuneSelf]bool{
' ': false,
'!': true,
'"': false,
'#': true,
'$': true,
'%': true,
'&': true,
'\'': false,
'(': true,
')': true,
'*': true,
'+': true,
',': true,
'-': true,
'.': true,
'/': true,
'0': true,
'1': true,
'2': true,
'3': true,
'4': true,
'5': true,
'6': true,
'7': true,
'8': true,
'9': true,
':': false,
';': true,
'<': true,
'=': false,
'>': true,
'?': true,
'@': true,
'A': true,
'B': true,
'C': true,
'D': true,
'E': true,
'F': true,
'G': true,
'H': true,
'I': true,
'J': true,
'K': true,
'L': true,
'M': true,
'N': true,
'O': true,
'P': true,
'Q': true,
'R': true,
'S': true,
'T': true,
'U': true,
'V': true,
'W': true,
'X': true,
'Y': true,
'Z': true,
'[': true,
'\\': false,
']': true,
'^': true,
'_': true,
'`': false,
'a': true,
'b': true,
'c': true,
'd': true,
'e': true,
'f': true,
'g': true,
'h': true,
'i': true,
'j': true,
'k': true,
'l': true,
'm': true,
'n': true,
'o': true,
'p': true,
'q': true,
'r': true,
's': true,
't': true,
'u': true,
'v': true,
'w': true,
'x': true,
'y': true,
'z': true,
'{': false,
'|': true,
'}': false,
'~': true,
}