go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/data/strpair/pair.go (about) 1 // Copyright 2017 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package strpair implements parsing and formatting of lists of 16 // colon-delimited key-value pair strings. 17 // 18 // Example of pairs: 19 // 20 // master:tryserver.chromium.linux 21 // builder:linux_chromium_rel_ng 22 // buildset:patch/gerrit/chromium-review.googlesource.com/677784/5 23 package strpair 24 25 import ( 26 "sort" 27 "strings" 28 ) 29 30 // Parse parses a colon-delimited key-value pair. 31 // 32 // If pair does not have ":", the whole string becomes the key with an empty 33 // value. 34 func Parse(pair string) (k, v string) { 35 parts := strings.SplitN(pair, ":", 2) 36 k = parts[0] 37 if len(parts) > 1 { 38 v = parts[1] 39 } else { 40 // this pair is invalid. This should not happen in practice. 41 // Do not panic because this function is used for externally-supplied 42 // data. 43 } 44 return 45 } 46 47 // Format formats a pair from a key and a value. 48 func Format(k, v string) string { 49 return k + ":" + v 50 } 51 52 // Map contains parsed string pairs. 53 type Map map[string][]string 54 55 // Get gets the first value associated with the given key. 56 // If there are no values associated with the key, Get returns 57 // the empty string. To access multiple values, use the map 58 // directly. 59 func (m Map) Get(key string) string { 60 if m == nil { 61 return "" 62 } 63 vs := m[key] 64 if len(vs) == 0 { 65 return "" 66 } 67 return vs[0] 68 } 69 70 // Set sets the key to value. It replaces any existing values. 71 func (m Map) Set(key, value string) { 72 m[key] = []string{value} 73 } 74 75 // Add adds the value to key. It appends to any existing 76 // values associated with key. 77 func (m Map) Add(key, value string) { 78 m[key] = append(m[key], value) 79 } 80 81 // Del deletes the values associated with key. 82 func (m Map) Del(key string) { 83 delete(m, key) 84 } 85 86 // ParseMap parses a list of colon-delimited key-value pair strings. 87 func ParseMap(raw []string) Map { 88 m := make(Map, len(raw)) 89 for _, t := range raw { 90 m.Add(Parse(t)) 91 } 92 return m 93 } 94 95 // Format converts m to a sorted list of strings. 96 func (m Map) Format() []string { 97 res := make([]string, 0, len(m)) 98 for k, values := range m { 99 for _, v := range values { 100 res = append(res, Format(k, v)) 101 } 102 } 103 sort.Strings(res) 104 return res 105 } 106 107 // Copy returns a deep copy of m. 108 func (m Map) Copy() Map { 109 cpy := make(Map, len(m)) 110 for k, vs := range m { 111 cpy[k] = append([]string(nil), vs...) 112 } 113 return cpy 114 } 115 116 // Contains returns true if m contains the key-value pair. 117 func (m Map) Contains(key, value string) bool { 118 for _, v := range m[key] { 119 if v == value { 120 return true 121 } 122 } 123 return false 124 }