| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package stringutils2
- import (
- "crypto/md5"
- "encoding/hex"
- "fmt"
- "math/rand"
- "strconv"
- "strings"
- "time"
- )
- func GetMD5Hash(text string) string {
- hasher := md5.New()
- hasher.Write([]byte(text))
- return hex.EncodeToString(hasher.Sum(nil))
- }
- func EscapeString(str string, pairs [][]string) string {
- if len(pairs) == 0 {
- pairs = [][]string{
- {"\\", `\\`},
- {"\n", `\n`},
- {"\r", `\r`},
- {"\t", `\t`},
- {`"`, `\"`},
- {"'", `\'`},
- {"$", `\$`},
- }
- }
- for _, pair := range pairs {
- k, v := pair[0], pair[1]
- str = strings.Replace(str, k, v, -1)
- }
- return str
- }
- func EscapeEchoString(str string) (string, error) {
- pairs := [][]string{
- {"\\", `\\`},
- {"\n", `\n`},
- {"\r", `\r`},
- {"\t", `\t`},
- {`"`, `\"`},
- }
- innerPairs := [][]string{
- {"\\", `\\`},
- {"\n", `\n`},
- {"\r", `\r`},
- {"\t", `\t`},
- {`"`, `\"`},
- {"$", `\$`},
- }
- segs, err := SplitByQuotation(str)
- if err != nil {
- return "", err
- }
- ret := ""
- for idx := 0; idx < len(segs); idx++ {
- s := EscapeString(segs[idx], innerPairs)
- if idx%2 == 1 {
- s = EscapeString(segs[idx], pairs)
- s = `\"` + EscapeString(s, innerPairs) + `\"`
- }
- ret += s
- }
- return ret, nil
- }
- func findQuotationPos(line string, offset int) int {
- if offset > len(line) {
- return -1
- }
- subStr := line[offset:]
- pos := strings.Index(subStr, `"`)
- if pos < 0 {
- return pos
- }
- pos += offset
- if pos > 0 && line[pos-1] == '\\' {
- return findQuotationPos(line, pos+1)
- }
- return pos
- }
- func SplitByQuotation(line string) ([]string, error) {
- segs := []string{}
- offset := 0
- for offset < len(line) {
- pos := findQuotationPos(line, offset)
- if pos < 0 {
- segs = append(segs, line[offset:])
- offset = len(line)
- } else {
- if pos == offset {
- offset += 1
- } else {
- segs = append(segs, line[offset:pos])
- offset = pos + 1
- }
- pos = findQuotationPos(line, offset)
- if pos < 0 {
- return nil, fmt.Errorf("Unpaired quotations: %s", line[offset:])
- } else {
- segs = append(segs, line[offset:pos])
- offset = pos + 1
- }
- }
- }
- return segs, nil
- }
- func GetCharTypeCount(str string) int {
- digitIdx := 0
- lowerIdx := 1
- upperIdx := 2
- otherIdx := 3
- complexity := make([]int, 4)
- for _, b := range []byte(str) {
- if b >= '0' && b <= '9' {
- complexity[digitIdx] += 1
- } else if b >= 'a' && b <= 'z' {
- complexity[lowerIdx] += 1
- } else if b >= 'A' && b <= 'Z' {
- complexity[upperIdx] += 1
- } else {
- complexity[otherIdx] += 1
- }
- }
- ret := 0
- for i := range complexity {
- if complexity[i] > 0 {
- ret += 1
- }
- }
- return ret
- }
- // Qcloud: 1-128个英文字母、数字和+=,.@_-
- // Aws: 请使用字母数字和‘+=,.@-_’字符。 最长 64 个字符
- // Common: 1-64个字符, 数字字母或 +=,.@-_
- func GenerateRoleName(roleName string) string {
- ret := ""
- for _, s := range roleName {
- if (s >= '0' && s <= '9') || (s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || strings.Contains("+=,.@-_", string(s)) {
- ret += string(s)
- }
- }
- if len(ret) == 0 {
- return func(length int) string {
- bytes := []byte("23456789abcdefghijkmnpqrstuvwxyz")
- result := []byte{}
- r := rand.New(rand.NewSource(time.Now().UnixNano()))
- for i := 0; i < length; i++ {
- result = append(result, bytes[r.Intn(len(bytes))])
- }
- return "role-" + string(result)
- }(12)
- }
- if len(ret) > 64 {
- return ret[:64]
- }
- return ret
- }
- func FilterEmpty(input []string) []string {
- ret := make([]string, 0)
- for i := range input {
- if len(input[i]) > 0 {
- ret = append(ret, input[i])
- }
- }
- return ret
- }
- func PrettyFloat(f float64, precision int) string {
- fstr := strconv.FormatFloat(f, 'f', -1, 64)
- dotPos := strings.Index(fstr, ".")
- if dotPos < 0 {
- return fstr
- }
- neg := false
- if fstr[0] == '-' {
- neg = true
- fstr = fstr[1:]
- dotPos -= 1
- }
- numPart, _ := strconv.ParseInt(fstr[:dotPos], 10, 64)
- prePartStr := fstr[dotPos+1:]
- if numPart == 0 {
- nonZeroPos := 0
- for prePartStr[nonZeroPos] == '0' {
- nonZeroPos += 1
- }
- precision += nonZeroPos
- }
- if precision < len(prePartStr) {
- prePart, _ := strconv.ParseInt(prePartStr[:precision], 10, 64)
- if prePartStr[precision] > '4' {
- // rounding up
- prePart += 1
- }
- prePartStr = fmt.Sprintf(fmt.Sprintf("%%.%dd", precision), prePart)
- if len(prePartStr) > precision {
- prePartStr = prePartStr[1:]
- numPart += 1
- }
- }
- for len(prePartStr) > 0 && prePartStr[len(prePartStr)-1] == '0' {
- prePartStr = prePartStr[0 : len(prePartStr)-1]
- }
- ret := strconv.FormatInt(numPart, 10)
- if len(prePartStr) > 0 {
- ret += "." + prePartStr
- }
- if neg {
- ret = "-" + ret
- }
- return ret
- }
|