Files
QSfera/vendor/github.com/gookit/goutil/strutil/random_windows.go
T
dependabot[bot]andGitHub 452d40dad7 build(deps): bump github.com/gookit/config/v2 from 2.2.5 to 2.2.6
Bumps [github.com/gookit/config/v2](https://github.com/gookit/config) from 2.2.5 to 2.2.6.
- [Release notes](https://github.com/gookit/config/releases)
- [Commits](https://github.com/gookit/config/compare/v2.2.5...v2.2.6)

---
updated-dependencies:
- dependency-name: github.com/gookit/config/v2
  dependency-version: 2.2.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-29 14:15:29 +00:00

86 lines
2.1 KiB
Go

//go:build windows
package strutil
import (
"math"
"math/rand"
"time"
"unsafe"
)
const MaximumCapacity = math.MaxInt>>1 + 1
var rn = rand.NewSource(time.Now().UnixNano())
// nearestPowerOfTwo 返回一个大于等于cap的最近的2的整数次幂,参考java8的hashmap的tableSizeFor函数
// - cap 输入参数
//
// 返回一个大于等于cap的最近的2的整数次幂
func nearestPowerOfTwo(cap int) int {
n := cap - 1
n |= n >> 1
n |= n >> 2
n |= n >> 4
n |= n >> 8
n |= n >> 16
if n < 0 {
return 1
}
if n >= MaximumCapacity {
return MaximumCapacity
}
return n + 1
}
// buildRandomString 生成随机字符串
// - letters 字符串模板
// - length 生成长度
//
// 返回一个指定长度的随机字符串
func buildRandomString(letters string, length int) string {
// 仿照strings.Builder
// 创建一个长度为 length 的字节切片
bytes := make([]byte, length)
strLength := len(letters)
if strLength <= 0 {
return ""
}
if strLength == 1 {
for i := 0; i < length; i++ {
bytes[i] = letters[0]
}
return *(*string)(unsafe.Pointer(&bytes))
}
// letters的字符需要使用多少个比特位数才能表示完
// letterIdBits := int(math.Ceil(math.Log2(strLength))),下面比上面的代码快
letterIdBits := int(math.Log2(float64(nearestPowerOfTwo(strLength))))
// 最大的字母id掩码
var letterIdMask int64 = 1<<letterIdBits - 1
// 可用次数的最大值
letterIdMax := 63 / letterIdBits
// UnixNano: 1607400451937462000
// 循环生成随机字符串
for i, cache, remain := length-1, rn.Int63(), letterIdMax; i >= 0; {
// 检查随机数生成器是否用尽所有随机数
if remain == 0 {
cache, remain = rn.Int63(), letterIdMax
}
// 从可用字符的字符串中随机选择一个字符
if idx := int(cache & letterIdMask); idx < strLength {
bytes[i] = letters[idx]
i--
}
// 右移比特位数,为下次选择字符做准备
cache >>= letterIdBits
remain--
}
// 仿照strings.Builder用unsafe包返回一个字符串,避免拷贝
// 将字节切片转换为字符串并返回
return *(*string)(unsafe.Pointer(&bytes))
}