You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
3.2 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package common
  2. import (
  3. crand "crypto/rand"
  4. "math/rand"
  5. "sync"
  6. "time"
  7. )
  8. const (
  9. strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters
  10. )
  11. var rng struct {
  12. sync.Mutex
  13. *rand.Rand
  14. }
  15. func init() {
  16. b := cRandBytes(8)
  17. var seed uint64
  18. for i := 0; i < 8; i++ {
  19. seed |= uint64(b[i])
  20. seed <<= 8
  21. }
  22. rng.Rand = rand.New(rand.NewSource(int64(seed)))
  23. }
  24. // Constructs an alphanumeric string of given length.
  25. func RandStr(length int) string {
  26. chars := []byte{}
  27. MAIN_LOOP:
  28. for {
  29. val := rng.Int63()
  30. for i := 0; i < 10; i++ {
  31. v := int(val & 0x3f) // rightmost 6 bits
  32. if v >= 62 { // only 62 characters in strChars
  33. val >>= 6
  34. continue
  35. } else {
  36. chars = append(chars, strChars[v])
  37. if len(chars) == length {
  38. break MAIN_LOOP
  39. }
  40. val >>= 6
  41. }
  42. }
  43. }
  44. return string(chars)
  45. }
  46. func RandUint16() uint16 {
  47. return uint16(RandUint32() & (1<<16 - 1))
  48. }
  49. func RandUint32() uint32 {
  50. rng.Lock()
  51. u32 := rng.Uint32()
  52. rng.Unlock()
  53. return u32
  54. }
  55. func RandUint64() uint64 {
  56. return uint64(RandUint32())<<32 + uint64(RandUint32())
  57. }
  58. func RandUint() uint {
  59. rng.Lock()
  60. i := rng.Int()
  61. rng.Unlock()
  62. return uint(i)
  63. }
  64. func RandInt16() int16 {
  65. return int16(RandUint32() & (1<<16 - 1))
  66. }
  67. func RandInt32() int32 {
  68. return int32(RandUint32())
  69. }
  70. func RandInt64() int64 {
  71. return int64(RandUint64())
  72. }
  73. func RandInt() int {
  74. rng.Lock()
  75. i := rng.Int()
  76. rng.Unlock()
  77. return i
  78. }
  79. func RandInt31() int32 {
  80. rng.Lock()
  81. i31 := rng.Int31()
  82. rng.Unlock()
  83. return i31
  84. }
  85. func RandInt63() int64 {
  86. rng.Lock()
  87. i63 := rng.Int63()
  88. rng.Unlock()
  89. return i63
  90. }
  91. // Distributed pseudo-exponentially to test for various cases
  92. func RandUint16Exp() uint16 {
  93. bits := RandUint32() % 16
  94. if bits == 0 {
  95. return 0
  96. }
  97. n := uint16(1 << (bits - 1))
  98. n += uint16(RandInt31()) & ((1 << (bits - 1)) - 1)
  99. return n
  100. }
  101. // Distributed pseudo-exponentially to test for various cases
  102. func RandUint32Exp() uint32 {
  103. bits := RandUint32() % 32
  104. if bits == 0 {
  105. return 0
  106. }
  107. n := uint32(1 << (bits - 1))
  108. n += uint32(RandInt31()) & ((1 << (bits - 1)) - 1)
  109. return n
  110. }
  111. // Distributed pseudo-exponentially to test for various cases
  112. func RandUint64Exp() uint64 {
  113. bits := RandUint32() % 64
  114. if bits == 0 {
  115. return 0
  116. }
  117. n := uint64(1 << (bits - 1))
  118. n += uint64(RandInt63()) & ((1 << (bits - 1)) - 1)
  119. return n
  120. }
  121. func RandFloat32() float32 {
  122. rng.Lock()
  123. f32 := rng.Float32()
  124. rng.Unlock()
  125. return f32
  126. }
  127. func RandTime() time.Time {
  128. return time.Unix(int64(RandUint64Exp()), 0)
  129. }
  130. func RandBytes(n int) []byte {
  131. return cRandBytes(n)
  132. }
  133. // RandIntn returns, as an int, a non-negative pseudo-random number in [0, n).
  134. // It panics if n <= 0
  135. func RandIntn(n int) int {
  136. rng.Lock()
  137. i := rng.Intn(n)
  138. rng.Unlock()
  139. return i
  140. }
  141. // RandPerm returns a pseudo-random permutation of n integers in [0, n).
  142. func RandPerm(n int) []int {
  143. rng.Lock()
  144. perm := rng.Perm(n)
  145. rng.Unlock()
  146. return perm
  147. }
  148. // NOTE: This relies on the os's random number generator.
  149. // For real security, we should salt that with some seed.
  150. // See github.com/tendermint/go-crypto for a more secure reader.
  151. func cRandBytes(numBytes int) []byte {
  152. b := make([]byte, numBytes)
  153. _, err := crand.Read(b)
  154. if err != nil {
  155. PanicCrisis(err)
  156. }
  157. return b
  158. }