package list import ( "fmt" "strings" ) // KeyValue represents a key-value attribute. type KeyValue struct { Key string Value string } // ParseKeyValue creates a new key-value attribute from a string. func ParseKeyValue(s string) *KeyValue { f := KeyValue{} return f.Parse(s) } // Key returns the sanitized attribute key. func Key(s string) string { var i = 0 // Remove non-alphanumeric characters. result := strings.Map(func(r rune) rune { switch r { case '.', '@', '-', '+', '_', '#': return r } if r >= '0' && r <= '9' { return r } else if (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') || r == 127 { return -1 } i++ return r }, s) if i == 0 { return "" } return result } // Value returns the sanitized attribute value. func Value(s string) string { // Remove control characters. return strings.Map(func(r rune) rune { if r <= 32 || r == 127 { return -1 } switch r { case '(', ')', '<', '>', '\'', '"': return r } return r }, s) } // Parse parses a string attribute into key and value. func (f *KeyValue) Parse(s string) *KeyValue { k, v, _ := strings.Cut(s, ":") // Set key. if k = Key(k); k == "" { return nil } else { f.Key = k } // Default? if v = Value(v); v == "" { f.Value = True return f } // Set value. if b := Bool[strings.ToLower(v)]; b != "" { f.Value = b } else { f.Value = v } return f } // String return the attribute as string. func (f *KeyValue) String() string { if f == nil { return "" } if Bool[strings.ToLower(f.Value)] == True { return f.Key } if s := fmt.Sprintf("%s:%s", f.Key, f.Value); len(s) < StringLengthLimit { return s } return "" }