stringutil.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package stringutil
  2. import (
  3. "fmt"
  4. "math"
  5. "math/rand"
  6. "time"
  7. )
  8. const (
  9. _ = 1 << (10 * iota)
  10. // KiB is bytes per Kibibyte
  11. KiB
  12. // MiB is bytes per Mebibyte
  13. MiB
  14. // GiB is bytes per Gibibyte
  15. GiB
  16. // TiB is bytes per Tebibyte
  17. TiB
  18. )
  19. var alpha = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
  20. var alphanumeric = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
  21. func init() {
  22. rand.Seed(time.Now().UnixNano())
  23. }
  24. // RandSeq generates a pseudo-random alphabetic string of the given length
  25. func RandSeq(n int) string {
  26. b := make([]rune, n)
  27. for i := range b {
  28. b[i] = alpha[rand.Intn(len(alpha))] // #nosec No need for a cryptographic strength random here
  29. }
  30. return string(b)
  31. }
  32. // RandSeq generates a pseudo-random alphabetic string of the given length
  33. func RandSeqWith(r *rand.Rand, n int) string {
  34. b := make([]rune, n)
  35. for i := range b {
  36. b[i] = alpha[r.Intn(len(alpha))] // #nosec No need for a cryptographic strength random here
  37. }
  38. return string(b)
  39. }
  40. // FormatBytes takes a number of bytes and formats it as a string
  41. func FormatBytes(numBytes int64) string {
  42. if numBytes > TiB {
  43. return fmt.Sprintf("%.2fTiB", float64(numBytes)/TiB)
  44. }
  45. if numBytes > GiB {
  46. return fmt.Sprintf("%.2fGiB", float64(numBytes)/GiB)
  47. }
  48. if numBytes > MiB {
  49. return fmt.Sprintf("%.2fMiB", float64(numBytes)/MiB)
  50. }
  51. if numBytes > KiB {
  52. return fmt.Sprintf("%.2fKiB", float64(numBytes)/KiB)
  53. }
  54. return fmt.Sprintf("%dB", numBytes)
  55. }
  56. // FormatUTCOffset converts a duration to a string of format "-07:00"
  57. func FormatUTCOffset(dur time.Duration) string {
  58. utcOffSig := "+"
  59. if dur.Hours() < 0 {
  60. utcOffSig = "-"
  61. }
  62. utcOffHrs := int(math.Trunc(math.Abs(dur.Hours())))
  63. utcOffMin := int(math.Abs(dur.Minutes())) - (utcOffHrs * 60)
  64. return fmt.Sprintf("%s%02d:%02d", utcOffSig, utcOffHrs, utcOffMin)
  65. }
  66. // StringSlicesEqual checks if two string slices with arbitrary order have the same elements
  67. func StringSlicesEqual(left, right []string) bool {
  68. if len(left) != len(right) {
  69. return false
  70. }
  71. // Build maps for each slice that counts each unique instance
  72. leftMap := make(map[string]int, len(left))
  73. for _, str := range left {
  74. count, ok := leftMap[str]
  75. if ok {
  76. leftMap[str] = count + 1
  77. } else {
  78. leftMap[str] = 1
  79. }
  80. }
  81. rightMap := make(map[string]int, len(right))
  82. for _, str := range right {
  83. count, ok := rightMap[str]
  84. if ok {
  85. rightMap[str] = count + 1
  86. } else {
  87. rightMap[str] = 1
  88. }
  89. }
  90. // check that each unique key has the same count in each slice
  91. for key, count := range leftMap {
  92. if rightMap[key] != count {
  93. return false
  94. }
  95. }
  96. return true
  97. }
  98. // DeleteEmptyStringsFromArray removes the empty strings from an array.
  99. func DeleteEmptyStringsFromArray(input []string) (output []string) {
  100. for _, str := range input {
  101. if str != "" {
  102. output = append(output, str)
  103. }
  104. }
  105. return
  106. }