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.

138 lines
2.6 KiB

9 years ago
9 years ago
9 years ago
  1. package common
  2. import (
  3. crand "crypto/rand"
  4. "math/rand"
  5. "time"
  6. )
  7. const (
  8. strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters
  9. )
  10. func init() {
  11. b := cRandBytes(8)
  12. var seed uint64
  13. for i := 0; i < 8; i++ {
  14. seed |= uint64(b[i])
  15. seed <<= 8
  16. }
  17. rand.Seed(int64(seed))
  18. }
  19. // Constructs an alphanumeric string of given length.
  20. func RandStr(length int) string {
  21. chars := []byte{}
  22. MAIN_LOOP:
  23. for {
  24. val := rand.Int63()
  25. for i := 0; i < 10; i++ {
  26. v := int(val & 0x3f) // rightmost 6 bits
  27. if v >= 62 { // only 62 characters in strChars
  28. val >>= 6
  29. continue
  30. } else {
  31. chars = append(chars, strChars[v])
  32. if len(chars) == length {
  33. break MAIN_LOOP
  34. }
  35. val >>= 6
  36. }
  37. }
  38. }
  39. return string(chars)
  40. }
  41. func RandUint16() uint16 {
  42. return uint16(rand.Uint32() & (1<<16 - 1))
  43. }
  44. func RandUint32() uint32 {
  45. return rand.Uint32()
  46. }
  47. func RandUint64() uint64 {
  48. return uint64(rand.Uint32())<<32 + uint64(rand.Uint32())
  49. }
  50. func RandUint() uint {
  51. return uint(rand.Int())
  52. }
  53. func RandInt16() int16 {
  54. return int16(rand.Uint32() & (1<<16 - 1))
  55. }
  56. func RandInt32() int32 {
  57. return int32(rand.Uint32())
  58. }
  59. func RandInt64() int64 {
  60. return int64(rand.Uint32())<<32 + int64(rand.Uint32())
  61. }
  62. func RandInt() int {
  63. return rand.Int()
  64. }
  65. // Distributed pseudo-exponentially to test for various cases
  66. func RandUint16Exp() uint16 {
  67. bits := rand.Uint32() % 16
  68. if bits == 0 {
  69. return 0
  70. }
  71. n := uint16(1 << (bits - 1))
  72. n += uint16(rand.Int31()) & ((1 << (bits - 1)) - 1)
  73. return n
  74. }
  75. // Distributed pseudo-exponentially to test for various cases
  76. func RandUint32Exp() uint32 {
  77. bits := rand.Uint32() % 32
  78. if bits == 0 {
  79. return 0
  80. }
  81. n := uint32(1 << (bits - 1))
  82. n += uint32(rand.Int31()) & ((1 << (bits - 1)) - 1)
  83. return n
  84. }
  85. // Distributed pseudo-exponentially to test for various cases
  86. func RandUint64Exp() uint64 {
  87. bits := rand.Uint32() % 64
  88. if bits == 0 {
  89. return 0
  90. }
  91. n := uint64(1 << (bits - 1))
  92. n += uint64(rand.Int63()) & ((1 << (bits - 1)) - 1)
  93. return n
  94. }
  95. func RandFloat32() float32 {
  96. return rand.Float32()
  97. }
  98. func RandTime() time.Time {
  99. return time.Unix(int64(RandUint64Exp()), 0)
  100. }
  101. func RandBytes(n int) []byte {
  102. bs := make([]byte, n)
  103. for i := 0; i < n; i++ {
  104. bs[i] = byte(rand.Intn(256))
  105. }
  106. return bs
  107. }
  108. // NOTE: This relies on the os's random number generator.
  109. // For real security, we should salt that with some seed.
  110. // See github.com/tendermint/go-crypto for a more secure reader.
  111. func cRandBytes(numBytes int) []byte {
  112. b := make([]byte, numBytes)
  113. _, err := crand.Read(b)
  114. if err != nil {
  115. PanicCrisis(err)
  116. }
  117. return b
  118. }