delve/pkg/config/split.go
Alessandro Arzilli c412dcdc4f
*: run go1.19 'go fmt' on everything and fix problems (#3031)
Go 1.19 also formats doc comments according to the new godoc syntax.
Some of our comments, especially unexported symbols did not conform to
the godoc syntax and therefore are mangled by 'go fmt'.

This PR runs 'go fmt' from go1.19 on everything and manually fixes the
problems.

See also:
	https://github.com/golang/proposal/blob/master/design/51082-godocfmt.md
2022-06-17 10:08:11 -07:00

204 lines
4.2 KiB
Go

package config
import (
"bytes"
"fmt"
"io"
"reflect"
"strconv"
"strings"
"unicode"
)
// SplitQuotedFields is like strings.Fields but ignores spaces inside areas surrounded
// by the specified quote character.
// To specify a single quote use backslash to escape it: \'
func SplitQuotedFields(in string, quote rune) []string {
type stateEnum int
const (
inSpace stateEnum = iota
inField
inQuote
inQuoteEscaped
)
state := inSpace
r := []string{}
var buf bytes.Buffer
for _, ch := range in {
switch state {
case inSpace:
if ch == quote {
state = inQuote
} else if !unicode.IsSpace(ch) {
buf.WriteRune(ch)
state = inField
}
case inField:
if ch == quote {
state = inQuote
} else if unicode.IsSpace(ch) {
r = append(r, buf.String())
buf.Reset()
} else {
buf.WriteRune(ch)
}
case inQuote:
if ch == quote {
state = inField
} else if ch == '\\' {
state = inQuoteEscaped
} else {
buf.WriteRune(ch)
}
case inQuoteEscaped:
buf.WriteRune(ch)
state = inQuote
}
}
if buf.Len() != 0 {
r = append(r, buf.String())
}
return r
}
func ConfigureSetSimple(rest string, cfgname string, field reflect.Value) error {
simpleArg := func(typ reflect.Type) (reflect.Value, error) {
switch typ.Kind() {
case reflect.Int:
n, err := strconv.Atoi(rest)
if err != nil {
return reflect.ValueOf(nil), fmt.Errorf("argument to %q must be a number", cfgname)
}
if n < 0 {
return reflect.ValueOf(nil), fmt.Errorf("argument to %q must be a number greater than zero", cfgname)
}
return reflect.ValueOf(&n), nil
case reflect.Bool:
v := rest == "true"
return reflect.ValueOf(&v), nil
case reflect.String:
return reflect.ValueOf(&rest), nil
default:
return reflect.ValueOf(nil), fmt.Errorf("unsupported type for configuration key %q", cfgname)
}
}
if field.Kind() == reflect.Ptr {
val, err := simpleArg(field.Type().Elem())
if err != nil {
return err
}
field.Set(val)
} else {
val, err := simpleArg(field.Type())
if err != nil {
return err
}
field.Set(val.Elem())
}
return nil
}
func ConfigureList(w io.Writer, config interface{}, tag string) {
it := IterateConfiguration(config, tag)
for it.Next() {
fieldName, field := it.Field()
if fieldName == "" {
continue
}
writeField(w, field, fieldName)
}
}
func writeField(w io.Writer, field reflect.Value, fieldName string) {
switch field.Kind() {
case reflect.Interface:
switch field := field.Interface().(type) {
case string:
fmt.Fprintf(w, "%s\t%q\n", fieldName, field)
default:
fmt.Fprintf(w, "%s\t%v\n", fieldName, field)
}
case reflect.Ptr:
if !field.IsNil() {
fmt.Fprintf(w, "%s\t%v\n", fieldName, field.Elem())
} else {
fmt.Fprintf(w, "%s\t<not defined>\n", fieldName)
}
case reflect.String:
fmt.Fprintf(w, "%s\t%q\n", fieldName, field)
default:
fmt.Fprintf(w, "%s\t%v\n", fieldName, field)
}
}
type configureIterator struct {
cfgValue reflect.Value
cfgType reflect.Type
i int
tag string
}
func IterateConfiguration(conf interface{}, tag string) *configureIterator {
cfgValue := reflect.ValueOf(conf).Elem()
cfgType := cfgValue.Type()
return &configureIterator{cfgValue, cfgType, -1, tag}
}
func (it *configureIterator) Next() bool {
it.i++
return it.i < it.cfgValue.NumField()
}
func (it *configureIterator) Field() (name string, field reflect.Value) {
name = it.cfgType.Field(it.i).Tag.Get(it.tag)
if comma := strings.Index(name, ","); comma >= 0 {
name = name[:comma]
}
field = it.cfgValue.Field(it.i)
return
}
func ConfigureListByName(conf interface{}, name, tag string) string {
if name == "" {
return ""
}
it := IterateConfiguration(conf, tag)
for it.Next() {
fieldName, field := it.Field()
if fieldName == name {
var buf bytes.Buffer
writeField(&buf, field, fieldName)
return buf.String()
}
}
return ""
}
func ConfigureFindFieldByName(conf interface{}, name, tag string) reflect.Value {
it := IterateConfiguration(conf, tag)
for it.Next() {
fieldName, field := it.Field()
if fieldName == name {
return field
}
}
return reflect.ValueOf(nil)
}
func Split2PartsBySpace(s string) []string {
v := strings.SplitN(s, " ", 2)
for i := range v {
v[i] = strings.TrimSpace(v[i])
}
return v
}