github.com/lheiskan/zebrapack@v4.1.1-0.20181107023619-e955d028f9bf+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  }