github.com/kaydxh/golang@v0.0.131/go/strings/strings.go (about) 1 /* 2 *Copyright (c) 2022, kaydxh 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining a copy 5 *of this software and associated documentation files (the "Software"), to deal 6 *in the Software without restriction, including without limitation the rights 7 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 *copies of the Software, and to permit persons to whom the Software is 9 *furnished to do so, subject to the following conditions: 10 * 11 *The above copyright notice and this permission notice shall be included in all 12 *copies or substantial portions of the Software. 13 * 14 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 *SOFTWARE. 21 */ 22 package strings 23 24 import ( 25 "fmt" 26 "strings" 27 "unicode/utf8" 28 29 strconv_ "github.com/kaydxh/golang/go/strconv" 30 ) 31 32 func GetStringOrFallback(values ...string) string { 33 for _, v := range values { 34 if v != "" { 35 return v 36 } 37 } 38 39 return "" 40 } 41 42 /* 43 func Replace(s string, old string, news []string, n int) string { 44 if len(news) == 0 || n == 0 { 45 return s 46 } 47 48 if m := strings.Count(s, old); m == 0 { 49 return s // avoid allocation 50 } else if n < 0 || m < n { 51 n = m 52 } 53 // if len(news) < n , padding news use last element in news 54 for i := 0; i < n-len(news); i++ { 55 news = append(news, news[len(news)-1]) 56 } 57 58 incLen := 0 59 for i := 0; i < n; i++ { 60 incLen += len(news[i]) - len(old) 61 } 62 63 // Apply replacements to buffer. 64 var b strings.Builder 65 b.Grow(len(s) + incLen) 66 start := 0 67 for i := 0; i < n; i++ { 68 j := start 69 if len(old) == 0 { 70 if i > 0 { 71 _, wid := utf8.DecodeRuneInString(s[start:]) 72 j += wid 73 } 74 } else { 75 j += strings.Index(s[start:], old) 76 } 77 b.WriteString(s[start:j]) 78 b.WriteString(news[i]) 79 start = j + len(old) 80 } 81 b.WriteString(s[start:]) 82 return b.String() 83 84 } 85 */ 86 87 /* 88 func ReplaceAll(s, old string, news []string) string { 89 return Replace(s, old, news, -1) 90 } 91 */ 92 93 func Replace(s string, old string, news []interface{}, useQuote bool, n int) string { 94 if len(news) == 0 || n == 0 { 95 return s 96 } 97 98 if m := strings.Count(s, old); m == 0 { 99 return s // avoid allocation 100 } else if n < 0 || m < n { 101 n = m 102 } 103 // if len(news) < n , padding news use last element in news 104 for i := 0; i < n-len(news); i++ { 105 news = append(news, news[len(news)-1]) 106 } 107 108 var b strings.Builder 109 start := 0 110 for i := 0; i < n; i++ { 111 j := start 112 if len(old) == 0 { 113 if i > 0 { 114 _, wid := utf8.DecodeRuneInString(s[start:]) 115 j += wid 116 } 117 } else { 118 j += strings.Index(s[start:], old) 119 } 120 b.WriteString(s[start:j]) 121 if useQuote { 122 b.WriteString(fmt.Sprintf(`"%v"`, news[i])) 123 } else { 124 b.WriteString(fmt.Sprintf("%v", news[i])) 125 } 126 start = j + len(old) 127 } 128 b.WriteString(s[start:]) 129 return b.String() 130 131 } 132 133 func ReplaceAll(s, old string, news []interface{}, useQuote bool) string { 134 return Replace(s, old, news, useQuote, -1) 135 } 136 137 // Split slices s into all substrings separated by sep and returns a slice of 138 // the substrings between those separators. 139 // 140 // If s does not contain sep and sep is not empty, Split returns a 141 // slice of length 0. 142 // 143 // If sep is empty, Split splits after each UTF-8 sequence. If both s 144 // and sep are empty, Split returns an empty slice. 145 // 146 // It is equivalent to SplitN with a count of -1. 147 func SplitOmitEmpty(s, sep string) []string { 148 var res []string 149 a := strings.Split(s, sep) 150 for _, v := range a { 151 if v != "" { 152 res = append(res, v) 153 } 154 } 155 156 return res 157 } 158 159 // Split2 returns the values from strings.SplitN(s, sep, 2). 160 // If sep is not found, it returns ("", "", false) instead. 161 func Split2(s, sep string) (string, string, bool) { 162 spl := strings.SplitN(s, sep, 2) 163 if len(spl) < 2 { 164 return "", "", false 165 } 166 return spl[0], spl[1], true 167 } 168 169 func SplitToNums[T any](s, sep string, convert func(string) (T, error)) ([]T, error) { 170 ss := SplitOmitEmpty(s, sep) 171 return strconv_.ParseNums(ss, convert) 172 } 173 174 func EqualCaseInsensitive(src, dst string) bool { 175 return strings.ToLower(src) == strings.ToLower(dst) 176 } 177 178 func EmptyString(str string) bool { 179 return strings.TrimSpace(str) == "" 180 }