Skip to content

Instantly share code, notes, and snippets.

@quenbyako
Last active April 1, 2024 13:14
Show Gist options
  • Save quenbyako/bbd83cf4aa821b92892740037f7cbb7d to your computer and use it in GitHub Desktop.
Save quenbyako/bbd83cf4aa821b92892740037f7cbb7d to your computer and use it in GitHub Desktop.
How to get all characters in golang unicode range table
// link to go playground: https://play.golang.org/p/BihbZqsk5Kh
package main
import (
"crypto/rand"
"math/big"
"unicode"
)
func main() {
println(string(getAllChars(unicode.ASCII_Hex_Digit)))
println(string(getRandomChar(unicode.ASCII_Hex_Digit)))
}
func getAllChars(table *unicode.RangeTable) []rune {
res := make([]rune, 0)
for _, r := range table.R16 {
for c := r.Lo; c <= r.Hi; c += r.Stride {
res = append(res, rune(c))
}
}
for _, r := range table.R32 {
for c := r.Lo; c <= r.Hi; c += r.Stride {
res = append(res, rune(c))
}
}
return res
}
// maybe you can optimize it, but these are just unicode tricks
func getRandomChar(table *unicode.RangeTable) rune {
charsSum := getCharsCount(table)
choosed, err := rand.Int(rand.Reader, big.NewInt(int64(charsSum)))
if err != nil {
panic(err)
}
return getNChar(table, int(choosed.Int64()))
}
func getNChar(table *unicode.RangeTable, i int) rune {
for _, r := range table.R16 {
if i >= charsInR16(r) {
i -= charsInR16(r)
} else {
return rune(r.Lo + r.Stride*uint16(i))
}
}
for _, r := range table.R32 {
if i >= charsInR32(r) {
i -= charsInR32(r)
} else {
return rune(r.Lo + r.Stride*uint32(i))
}
}
panic("can't get here")
}
func getCharsCount(table *unicode.RangeTable) int {
var charsSum int
for _, r := range table.R16 {
charsSum += charsInR16(r)
}
for _, r := range table.R32 {
charsSum += charsInR32(r)
}
return charsSum
}
func charsInR16(r unicode.Range16) int {
return int((r.Hi-r.Lo)/r.Stride + 1)
}
func charsInR32(r unicode.Range32) int {
return int((r.Hi-r.Lo)/r.Stride + 1)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment