diff options
Diffstat (limited to 'vendor/codeberg.org/gruf/go-kv')
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/field.go | 2 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/field_fmt.go | 4 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/field_format.go | 2 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/format/format.go | 74 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/format/util.go | 47 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/util.go | 148 |
6 files changed, 174 insertions, 103 deletions
diff --git a/vendor/codeberg.org/gruf/go-kv/field.go b/vendor/codeberg.org/gruf/go-kv/field.go index 86a53b173..79c43822a 100644 --- a/vendor/codeberg.org/gruf/go-kv/field.go +++ b/vendor/codeberg.org/gruf/go-kv/field.go @@ -75,7 +75,7 @@ type Field struct { // Key returns the formatted key string of this Field. func (f Field) Key() string { buf := byteutil.Buffer{B: make([]byte, 0, bufsize/2)} - AppendQuoteKey(&buf, f.K) + AppendQuote(&buf, f.K) return buf.String() } diff --git a/vendor/codeberg.org/gruf/go-kv/field_fmt.go b/vendor/codeberg.org/gruf/go-kv/field_fmt.go index fcdcc5e17..33cec482b 100644 --- a/vendor/codeberg.org/gruf/go-kv/field_fmt.go +++ b/vendor/codeberg.org/gruf/go-kv/field_fmt.go @@ -25,7 +25,7 @@ func (f Field) AppendFormat(buf *byteutil.Buffer, vbose bool) { } else /* regular */ { fmtstr = `%+v` } - AppendQuoteKey(buf, f.K) + AppendQuote(buf, f.K) buf.WriteByte('=') appendValuef(buf, fmtstr, f.V) } @@ -50,7 +50,7 @@ func appendValuef(buf *byteutil.Buffer, format string, args ...interface{}) { fmtbuf.B = fmt.Appendf(fmtbuf.B, format, args...) // Append quoted value to dst buffer - AppendQuoteValue(buf, fmtbuf.String()) + AppendQuote(buf, fmtbuf.String()) // Drop overly large capacity buffers if fmtbuf.Cap() > int(^uint16(0)) { diff --git a/vendor/codeberg.org/gruf/go-kv/field_format.go b/vendor/codeberg.org/gruf/go-kv/field_format.go index 4fa7a8dcf..18f35a6b9 100644 --- a/vendor/codeberg.org/gruf/go-kv/field_format.go +++ b/vendor/codeberg.org/gruf/go-kv/field_format.go @@ -16,7 +16,7 @@ func (f Field) AppendFormat(buf *byteutil.Buffer, vbose bool) { } else /* regular */ { fmtstr = "{:v}" } - AppendQuoteKey(buf, f.K) + AppendQuote(buf, f.K) buf.WriteByte('=') format.Appendf(buf, fmtstr, f.V) } diff --git a/vendor/codeberg.org/gruf/go-kv/format/format.go b/vendor/codeberg.org/gruf/go-kv/format/format.go index 7edc4475f..ab20e01f4 100644 --- a/vendor/codeberg.org/gruf/go-kv/format/format.go +++ b/vendor/codeberg.org/gruf/go-kv/format/format.go @@ -166,21 +166,21 @@ func (f format) AppendByte(b byte) { // Always quoted case f.Key(): f.Buffer.B = append(f.Buffer.B, '\'') - f.Buffer.B = append(f.Buffer.B, byte2str(b)...) + f.Buffer.B = append(f.Buffer.B, Byte2Str(b)...) f.Buffer.B = append(f.Buffer.B, '\'') // Always quoted ASCII with type case f.Verbose(): f._AppendPrimitiveTyped(func(f format) { f.Buffer.B = append(f.Buffer.B, '\'') - f.Buffer.B = append(f.Buffer.B, byte2str(b)...) + f.Buffer.B = append(f.Buffer.B, Byte2Str(b)...) f.Buffer.B = append(f.Buffer.B, '\'') }) // Always quoted case f.Value(): f.Buffer.B = append(f.Buffer.B, '\'') - f.Buffer.B = append(f.Buffer.B, byte2str(b)...) + f.Buffer.B = append(f.Buffer.B, Byte2Str(b)...) f.Buffer.B = append(f.Buffer.B, '\'') // Append as raw byte @@ -195,16 +195,16 @@ func (f format) AppendBytes(b []byte) { case b == nil: f.AppendNil() - // Handle bytes as string key + // Quoted only if spaces/requires escaping case f.Key(): - f.AppendStringKey(b2s(b)) + f.AppendStringSafe(b2s(b)) // Append as separate ASCII quoted bytes in slice case f.Verbose(): f._AppendArrayTyped(func(f format) { for i := 0; i < len(b); i++ { f.Buffer.B = append(f.Buffer.B, '\'') - f.Buffer.B = append(f.Buffer.B, byte2str(b[i])...) + f.Buffer.B = append(f.Buffer.B, Byte2Str(b[i])...) f.Buffer.B = append(f.Buffer.B, `',`...) } if len(b) > 0 { @@ -212,9 +212,9 @@ func (f format) AppendBytes(b []byte) { } }) - // Append as quoted string + // Quoted only if spaces/requires escaping case f.Value(): - f.AppendStringQuoted(b2s(b)) + f.AppendStringSafe(b2s(b)) // Append as raw bytes default: @@ -260,9 +260,9 @@ func (f format) AppendRunes(r []rune) { case r == nil: f.AppendNil() - // Handle bytes as string key + // Quoted only if spaces/requires escaping case f.Key(): - f.AppendStringKey(string(r)) + f.AppendStringSafe(string(r)) // Append as separate ASCII quoted bytes in slice case f.Verbose(): @@ -276,9 +276,9 @@ func (f format) AppendRunes(r []rune) { } }) - // Append as quoted string + // Quoted only if spaces/requires escaping case f.Value(): - f.AppendStringQuoted(string(r)) + f.AppendStringSafe(string(r)) // Append as raw bytes default: @@ -292,7 +292,7 @@ func (f format) AppendString(s string) { switch { // Quoted only if spaces/requires escaping case f.Key(): - f.AppendStringKey(s) + f.AppendStringSafe(s) // Always quoted with type case f.Verbose(): @@ -300,9 +300,9 @@ func (f format) AppendString(s string) { f.AppendStringQuoted(s) }) - // Always quoted string + // Quoted only if spaces/requires escaping case f.Value(): - f.AppendStringQuoted(s) + f.AppendStringSafe(s) // All else default: @@ -310,15 +310,15 @@ func (f format) AppendString(s string) { } } -func (f format) AppendStringKey(s string) { - if len(s) > SingleTermLine || !strconv.CanBackquote(s) { +func (f format) AppendStringSafe(s string) { + if len(s) > SingleTermLine || !IsSafeASCII(s) { // Requires quoting AND escaping f.Buffer.B = strconv.AppendQuote(f.Buffer.B, s) } else if ContainsDoubleQuote(s) { // Contains double quotes, needs escaping f.Buffer.B = AppendEscape(f.Buffer.B, s) - } else if len(s) < 1 || ContainsSpaceOrTab(s) { - // Contains space, needs quotes + } else if len(s) == 0 || ContainsSpaceOrTab(s) { + // Contains space / empty, needs quotes f.Buffer.B = append(f.Buffer.B, '"') f.Buffer.B = append(f.Buffer.B, s...) f.Buffer.B = append(f.Buffer.B, '"') @@ -329,7 +329,7 @@ func (f format) AppendStringKey(s string) { } func (f format) AppendStringQuoted(s string) { - if len(s) > SingleTermLine || !strconv.CanBackquote(s) { + if len(s) > SingleTermLine || !IsSafeASCII(s) { // Requires quoting AND escaping f.Buffer.B = strconv.AppendQuote(f.Buffer.B, s) } else if ContainsDoubleQuote(s) { @@ -760,7 +760,7 @@ func (f format) AppendStructFields(v reflect.Value, t reflect.Type) { tfield := t.Field(i) // Append field name - f.AppendStringKey(tfield.Name) + f.AppendStringSafe(tfield.Name) f.Buffer.B = append(f.Buffer.B, '=') f.SetValue().AppendInterfaceOrReflectNext(vfield, tfield.Type) @@ -811,7 +811,7 @@ func (f format) _AppendMethodType(method func() string, i interface{}) (ok bool) switch { // Append as key formatted case f.Key(): - f.AppendStringKey(result) + f.AppendStringSafe(result) // Append as always quoted case f.Value(): @@ -890,33 +890,3 @@ func (f format) _AppendFieldType(appendFields func(format)) { appendFields(f) f.Buffer.B = append(f.Buffer.B, '}') } - -// byte2str returns 'c' as a string, escaping if necessary. -func byte2str(c byte) string { - switch c { - case '\a': - return `\a` - case '\b': - return `\b` - case '\f': - return `\f` - case '\n': - return `\n` - case '\r': - return `\r` - case '\t': - return `\t` - case '\v': - return `\v` - case '\'': - return `\\` - default: - if c < ' ' { - const hex = "0123456789abcdef" - return `\x` + - string(hex[c>>4]) + - string(hex[c&0xF]) - } - return string(c) - } -} diff --git a/vendor/codeberg.org/gruf/go-kv/format/util.go b/vendor/codeberg.org/gruf/go-kv/format/util.go index 674f81be5..b5c672ecb 100644 --- a/vendor/codeberg.org/gruf/go-kv/format/util.go +++ b/vendor/codeberg.org/gruf/go-kv/format/util.go @@ -18,11 +18,22 @@ const ( SingleTermLine = 256 ) +// IsSafeASCII checks whether string is printable (i.e. non-control char) ASCII text. +func IsSafeASCII(str string) bool { + for _, r := range str { + if (r < ' ' && r != '\t') || + r >= 0x7f { + return false + } + } + return true +} + // ContainsSpaceOrTab checks if "s" contains space or tabs. func ContainsSpaceOrTab(s string) bool { - if i := strings.IndexByte(s, ' '); i != -1 { + if i := strings.IndexByte(s, ' '); i >= 0 { return true // note using indexbyte as it is ASM. - } else if i := strings.IndexByte(s, '\t'); i != -1 { + } else if i := strings.IndexByte(s, '\t'); i >= 0 { return true } return false @@ -30,7 +41,7 @@ func ContainsSpaceOrTab(s string) bool { // ContainsDoubleQuote checks if "s" contains a double quote. func ContainsDoubleQuote(s string) bool { - return (strings.IndexByte(s, '"') != -1) + return (strings.IndexByte(s, '"') >= 0) } // AppendEscape will append 's' to 'dst' and escape any double quotes. @@ -57,6 +68,36 @@ func AppendEscape(dst []byte, str string) []byte { return dst } +// Byte2Str returns 'c' as a string, escaping if necessary. +func Byte2Str(c byte) string { + switch c { + case '\a': + return `\a` + case '\b': + return `\b` + case '\f': + return `\f` + case '\n': + return `\n` + case '\r': + return `\r` + case '\t': + return `\t` + case '\v': + return `\v` + case '\'': + return `\\` + default: + if c < ' ' { + const hex = "0123456789abcdef" + return `\x` + + string(hex[c>>4]) + + string(hex[c&0xF]) + } + return string(c) + } +} + // isNil will safely check if 'v' is nil without dealing with weird Go interface nil bullshit. func isNil(i interface{}) bool { type eface struct{ _type, data unsafe.Pointer } //nolint diff --git a/vendor/codeberg.org/gruf/go-kv/util.go b/vendor/codeberg.org/gruf/go-kv/util.go index 3d249e5d4..dfd91ad9d 100644 --- a/vendor/codeberg.org/gruf/go-kv/util.go +++ b/vendor/codeberg.org/gruf/go-kv/util.go @@ -2,70 +2,130 @@ package kv import ( "strconv" + "strings" "codeberg.org/gruf/go-byteutil" "codeberg.org/gruf/go-kv/format" ) -// AppendQuoteKey will append and escape/quote a formatted key string. -func AppendQuoteKey(buf *byteutil.Buffer, str string) { +// AppendQuote will append (and escape/quote where necessary) a formatted field string. +func AppendQuote(buf *byteutil.Buffer, str string) { switch { - case len(str) > format.SingleTermLine || !strconv.CanBackquote(str): - // Append quoted and escaped string - buf.B = strconv.AppendQuote(buf.B, str) - case format.ContainsDoubleQuote(str): - // Double quote and escape string - buf.B = append(buf.B, '"') - buf.B = format.AppendEscape(buf.B, str) - buf.B = append(buf.B, '"') - case len(str) < 1 || format.ContainsSpaceOrTab(str): - // Double quote this string as-is - buf.WriteString(`"` + str + `"`) - default: - // Append string as-is - buf.WriteString(str) - } -} + case len(str) == 0: + // Append empty quotes. + buf.B = append(buf.B, `""`...) + return -// AppendQuoteValue will append and escape/quote a formatted value string. -func AppendQuoteValue(buf *byteutil.Buffer, str string) { - switch { - case len(str) > format.SingleTermLine || !strconv.CanBackquote(str): - // Append quoted and escaped string + case len(str) == 1: + // Append quote single byte. + appendQuoteByte(buf, str[0]) + return + + case len(str) > format.SingleTermLine || !format.IsSafeASCII(str): + // Long line or contains non-ascii chars. buf.B = strconv.AppendQuote(buf.B, str) return - case !doubleQuoted(str): + + case !isQuoted(str): + // Single/double quoted already. + + // Get space / tab indices (if any). + s := strings.IndexByte(str, ' ') + t := strings.IndexByte(str, '\t') + + // Find first whitespace. + sp0 := smallest(s, t) + if sp0 < 0 { + break + } + + // Check if str is enclosed by braces. + // (but without any key-value separator). + if (enclosedBy(str, sp0, '{', '}') || + enclosedBy(str, sp0, '[', ']') || + enclosedBy(str, sp0, '(', ')')) && + strings.IndexByte(str, '=') < 0 { + break + } + if format.ContainsDoubleQuote(str) { - // Double quote and escape string + // Contains double quote, double quote + // and append escaped existing. buf.B = append(buf.B, '"') buf.B = format.AppendEscape(buf.B, str) buf.B = append(buf.B, '"') return - } else if format.ContainsSpaceOrTab(str) { - // Double quote this string as-is - buf.WriteString(`"` + str + `"`) - return } + + // Quote un-enclosed spaces. + buf.B = append(buf.B, '"') + buf.B = append(buf.B, str...) + buf.B = append(buf.B, '"') + return + } + + // Double quoted, enclosed in braces, or + // literally anything else: append as-is. + buf.B = append(buf.B, str...) + return +} + +// appendEscapeByte will append byte to buffer, quoting and escaping where necessary. +func appendQuoteByte(buf *byteutil.Buffer, c byte) { + switch c { + // Double quote space. + case ' ': + buf.B = append(buf.B, '"', c, '"') + + // Escape + double quote. + case '\a': + buf.B = append(buf.B, '"', '\\', 'a', '"') + case '\b': + buf.B = append(buf.B, '"', '\\', 'b', '"') + case '\f': + buf.B = append(buf.B, '"', '\\', 'f', '"') + case '\n': + buf.B = append(buf.B, '"', '\\', 'n', '"') + case '\r': + buf.B = append(buf.B, '"', '\\', 'r', '"') + case '\t': + buf.B = append(buf.B, '"', '\\', 't', '"') + case '\v': + buf.B = append(buf.B, '"', '\\', 'v', '"') + + // Append as-is. + default: + buf.B = append(buf.B, c) } +} - // Append string as-is - buf.WriteString(str) +// isQuoted checks if string is single or double quoted. +func isQuoted(str string) bool { + return (str[0] == '"' && str[len(str)-1] == '"') || + (str[0] == '\'' && str[len(str)-1] == '\'') +} + +// smallest attempts to return the smallest positive value of those given. +func smallest(i1, i2 int) int { + if i1 >= 0 && (i2 < 0 || i1 < i2) { + return i1 + } + return i2 } -// doubleQuoted will return whether 'str' is double quoted. -func doubleQuoted(str string) bool { - if len(str) < 2 || - str[0] != '"' || str[len(str)-1] != '"' { +// enclosedBy will check if given string is enclosed by end, and at least non-whitespace up to start. +func enclosedBy(str string, sp int, start, end byte) bool { + // Check for ending char in string. + if str[len(str)-1] != end { return false } - var delim bool - for i := len(str) - 2; i >= 0; i-- { - switch str[i] { - case '\\': - delim = !delim - default: - return !delim - } + + // Check for starting char in string. + i := strings.IndexByte(str, start) + if i < 0 { + return false } - return !delim + + // Check before space. + return i < sp } |