github.com/chrislusf/greenpack@v3.7.1-0.20170911073826-ad5bd10b7c47+incompatible/gen/cry.go (about) 1 package gen 2 3 import ( 4 cr "crypto/rand" 5 "encoding/binary" 6 "fmt" 7 "hash/fnv" 8 mr "math/rand" 9 "sync" 10 ) 11 12 var mathRandSrc *mr.Rand 13 14 func init() { 15 seed := CryptoRandInt64() 16 mathRandSrc = mr.New(mr.NewSource(seed)) 17 } 18 19 var fileNameHash string 20 21 func SetFilename(fn string) { 22 h := fnv.New64a() 23 h.Write([]byte(fn)) 24 fileNameHash = fmt.Sprintf("%x", h.Sum64()) 25 } 26 27 // generate a unconflicting symbol name 28 func gensym() string { 29 return "zgensym_" + fileNameHash + fmt.Sprintf("_%d", genSerial()) 30 } 31 32 // generate a random identifier name 33 func randIdentOldVersion() string { 34 bts := make([]byte, idxLen) 35 for i := range bts { 36 bts[i] = idxChars[cryptoRandIntn(len(idxChars))] 37 } 38 39 // Use a `z` prefix so the randomly generated bytes can't conflict with 40 // Go keywords (such as `int` and `var`). 41 return "z" + string(bts) + fmt.Sprintf("%d", genSerial()) 42 } 43 44 // Use crypto/rand to get an random int64. 45 func CryptoRandInt64() int64 { 46 b := make([]byte, 8) 47 _, err := cr.Read(b) 48 if err != nil { 49 panic(err) 50 } 51 r := int64(binary.LittleEndian.Uint64(b)) 52 return r 53 } 54 55 func SeedOurMathRandSrc(seed int64) { 56 mathRandSrc.Seed(seed) 57 } 58 59 func MathRandInt64() int64 { 60 // generate one rand for the sign, xor with a 2nd. 61 return (mathRandSrc.Int63() << 1) ^ mathRandSrc.Int63() 62 } 63 64 const ( 65 idxChars = "abcdefghijlkmnopqrstuvwxyz" 66 idxLen = 3 67 ) 68 69 var nextGenSerial struct { 70 mut sync.Mutex 71 next int 72 } 73 74 // genSerial generates serial numbers, 75 // in sequence, starting at zero. Safe 76 // for concurrent access. 77 func genSerial() int { 78 nextGenSerial.mut.Lock() 79 n := nextGenSerial.next 80 nextGenSerial.next++ 81 nextGenSerial.mut.Unlock() 82 return n 83 } 84 85 func cryptoRandIntn(n int) int { 86 b := make([]byte, 8) 87 _, err := cr.Read(b) 88 if err != nil { 89 panic(err) 90 } 91 u := int(binary.LittleEndian.Uint64(b)) 92 if u < 0 { 93 u = -u 94 } 95 return u % n 96 }