github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/utils/string.go (about)

     1  package utils
     2  
     3  import (
     4  	"math/rand"
     5  	"strconv"
     6  	"strings"
     7  	"unicode/utf8"
     8  	"unsafe"
     9  )
    10  
    11  func RandomString(len int) string {
    12  	return RandomStringRange(len, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
    13  }
    14  
    15  func RandomStringRange(length int, str string) string {
    16  	sb := strings.Builder{}
    17  	sb.Grow(length)
    18  	for i := 0; i < length; i++ {
    19  		sb.WriteByte(str[rand.Intn(len(str))])
    20  	}
    21  	return sb.String()
    22  }
    23  
    24  func ChunkString(s string, chunkSize int) []string {
    25  	runes := []rune(s)
    26  	if len(runes) == 0 || len(runes) <= chunkSize {
    27  		return []string{s}
    28  	}
    29  
    30  	chunkLen := len(runes) / chunkSize
    31  	if len(runes)%chunkSize != 0 {
    32  		chunkLen++
    33  	}
    34  
    35  	chunks := make([]string, 0, chunkLen)
    36  	for i := 0; i < len(runes); i += chunkSize {
    37  		nn := i + chunkSize
    38  		if nn > len(runes) {
    39  			nn = len(runes)
    40  		}
    41  		chunks = append(chunks, string(runes[i:nn]))
    42  	}
    43  	return chunks
    44  }
    45  
    46  func ConvertSubVersionToInt(str string) int32 {
    47  	i, _ := strconv.ParseInt(strings.Join(strings.Split(str, "."), ""), 10, 32)
    48  	return int32(i) * 10
    49  }
    50  
    51  // B2S converts byte slice to a string without memory allocation.
    52  func B2S(b []byte) string {
    53  	size := len(b)
    54  	if size == 0 {
    55  		return ""
    56  	}
    57  	return unsafe.String(&b[0], size)
    58  }
    59  
    60  // S2B converts string to a byte slice without memory allocation.
    61  //
    62  // Note it may break if string and/or slice header will change
    63  // in the future go versions.
    64  func S2B(s string) (b []byte) {
    65  	return unsafe.Slice(unsafe.StringData(s), len(s))
    66  }
    67  
    68  const (
    69  	escQuot = "&#34;" // shorter than "&quot;"
    70  	escApos = "&#39;" // shorter than "&apos;"
    71  	escAmp  = "&amp;"
    72  	escLT   = "&lt;"
    73  	escGT   = "&gt;"
    74  	escTab  = "&#x9;"
    75  	escNL   = "&#xA;"
    76  	escCR   = "&#xD;"
    77  	escFFFD = "\uFFFD" // Unicode replacement character
    78  )
    79  
    80  func isInCharacterRange(r rune) (inrange bool) {
    81  	return r == 0x09 ||
    82  		r == 0x0A ||
    83  		r == 0x0D ||
    84  		r >= 0x20 && r <= 0xD7FF ||
    85  		r >= 0xE000 && r <= 0xFFFD ||
    86  		r >= 0x10000 && r <= 0x10FFFF
    87  }
    88  
    89  // XmlEscape xml escape string
    90  func XmlEscape(s string) string {
    91  	var esc string
    92  	var sb strings.Builder
    93  	sb.Grow(len(s))
    94  	last := 0
    95  	for i, r := range s {
    96  		width := utf8.RuneLen(r)
    97  		switch r {
    98  		case '"':
    99  			esc = escQuot
   100  		case '\'':
   101  			esc = escApos
   102  		case '&':
   103  			esc = escAmp
   104  		case '<':
   105  			esc = escLT
   106  		case '>':
   107  			esc = escGT
   108  		case '\t':
   109  			esc = escTab
   110  		case '\n':
   111  			esc = escNL
   112  		case '\r':
   113  			esc = escCR
   114  		default:
   115  			if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
   116  				esc = escFFFD
   117  				break
   118  			}
   119  			continue
   120  		}
   121  		sb.WriteString(s[last:i])
   122  		sb.WriteString(esc)
   123  		last = i + width
   124  	}
   125  	sb.WriteString(s[last:])
   126  	return sb.String()
   127  }