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.

258 lines
4.5 KiB

  1. package util
  2. import (
  3. "bytes"
  4. "crypto/md5"
  5. "crypto/rand"
  6. "encoding/base64"
  7. "fmt"
  8. "io"
  9. "math"
  10. "strconv"
  11. "strings"
  12. "unicode"
  13. )
  14. // BytesToHumanReadable returns the converted human readable representation of the bytes.
  15. func BytesToHumanReadable(b uint64) string {
  16. const unit = 1024
  17. if b < unit {
  18. return fmt.Sprintf("%d B", b)
  19. }
  20. div, exp := uint64(unit), 0
  21. for n := b / unit; n >= unit; n /= unit {
  22. div *= unit
  23. exp++
  24. }
  25. return fmt.Sprintf("%.2f %ciB", float64(b)/float64(div), "KMGTPE"[exp])
  26. }
  27. // big endian
  28. func BytesToUint64(b []byte) (v uint64) {
  29. length := uint(len(b))
  30. for i := uint(0); i < length-1; i++ {
  31. v += uint64(b[i])
  32. v <<= 8
  33. }
  34. v += uint64(b[length-1])
  35. return
  36. }
  37. func BytesToUint32(b []byte) (v uint32) {
  38. length := uint(len(b))
  39. for i := uint(0); i < length-1; i++ {
  40. v += uint32(b[i])
  41. v <<= 8
  42. }
  43. v += uint32(b[length-1])
  44. return
  45. }
  46. func BytesToUint16(b []byte) (v uint16) {
  47. v += uint16(b[0])
  48. v <<= 8
  49. v += uint16(b[1])
  50. return
  51. }
  52. func Uint64toBytes(b []byte, v uint64) {
  53. for i := uint(0); i < 8; i++ {
  54. b[7-i] = byte(v >> (i * 8))
  55. }
  56. }
  57. func Uint32toBytes(b []byte, v uint32) {
  58. for i := uint(0); i < 4; i++ {
  59. b[3-i] = byte(v >> (i * 8))
  60. }
  61. }
  62. func Uint16toBytes(b []byte, v uint16) {
  63. b[0] = byte(v >> 8)
  64. b[1] = byte(v)
  65. }
  66. func Uint8toBytes(b []byte, v uint8) {
  67. b[0] = byte(v)
  68. }
  69. // returns a 64 bit big int
  70. func HashStringToLong(dir string) (v int64) {
  71. h := md5.New()
  72. io.WriteString(h, dir)
  73. b := h.Sum(nil)
  74. v += int64(b[0])
  75. v <<= 8
  76. v += int64(b[1])
  77. v <<= 8
  78. v += int64(b[2])
  79. v <<= 8
  80. v += int64(b[3])
  81. v <<= 8
  82. v += int64(b[4])
  83. v <<= 8
  84. v += int64(b[5])
  85. v <<= 8
  86. v += int64(b[6])
  87. v <<= 8
  88. v += int64(b[7])
  89. return
  90. }
  91. func HashToInt32(data []byte) (v int32) {
  92. h := md5.New()
  93. h.Write(data)
  94. b := h.Sum(nil)
  95. v += int32(b[0])
  96. v <<= 8
  97. v += int32(b[1])
  98. v <<= 8
  99. v += int32(b[2])
  100. v <<= 8
  101. v += int32(b[3])
  102. return
  103. }
  104. func Base64Encode(data []byte) string {
  105. return base64.StdEncoding.EncodeToString(data)
  106. }
  107. func Base64Md5(data []byte) string {
  108. return Base64Encode(Md5(data))
  109. }
  110. func Md5(data []byte) []byte {
  111. hash := md5.New()
  112. hash.Write(data)
  113. return hash.Sum(nil)
  114. }
  115. func Md5String(data []byte) string {
  116. return fmt.Sprintf("%x", Md5(data))
  117. }
  118. func Base64Md5ToBytes(contentMd5 string) []byte {
  119. data, err := base64.StdEncoding.DecodeString(contentMd5)
  120. if err != nil {
  121. return nil
  122. }
  123. return data
  124. }
  125. func RandomInt32() int32 {
  126. buf := make([]byte, 4)
  127. rand.Read(buf)
  128. return int32(BytesToUint32(buf))
  129. }
  130. func RandomBytes(byteCount int) []byte {
  131. buf := make([]byte, byteCount)
  132. rand.Read(buf)
  133. return buf
  134. }
  135. type BytesReader struct {
  136. Bytes []byte
  137. *bytes.Reader
  138. }
  139. func NewBytesReader(b []byte) *BytesReader {
  140. return &BytesReader{
  141. Bytes: b,
  142. Reader: bytes.NewReader(b),
  143. }
  144. }
  145. // EmptyTo returns to if s is empty.
  146. func EmptyTo(s, to string) string {
  147. if s == "" {
  148. return to
  149. }
  150. return s
  151. }
  152. // IfElse works like b ? this : that.
  153. func IfElse(b bool, this, that string) string {
  154. if b {
  155. return this
  156. }
  157. return that
  158. }
  159. // ParseBytes parses a string representation of bytes into the number
  160. // of bytes it represents.
  161. //
  162. // See Also: Bytes, IBytes.
  163. //
  164. // ParseBytes("42MB") -> 42000000, nil
  165. // ParseBytes("42 MB") -> 42000000, nil
  166. // ParseBytes("42 mib") -> 44040192, nil
  167. func ParseBytes(s string) (uint64, error) {
  168. lastDigit := 0
  169. hasComma := false
  170. for _, r := range s {
  171. if !(unicode.IsDigit(r) || r == '.' || r == ',') {
  172. break
  173. }
  174. if r == ',' {
  175. hasComma = true
  176. }
  177. lastDigit++
  178. }
  179. num := s[:lastDigit]
  180. if hasComma {
  181. num = strings.Replace(num, ",", "", -1)
  182. }
  183. f, err := strconv.ParseFloat(num, 64)
  184. if err != nil {
  185. return 0, err
  186. }
  187. extra := strings.ToLower(strings.TrimSpace(s[lastDigit:]))
  188. if m, ok := bytesSizeTable[extra]; ok {
  189. f *= float64(m)
  190. if f >= math.MaxUint64 {
  191. return 0, fmt.Errorf("too large: %v", s)
  192. }
  193. return uint64(f), nil
  194. }
  195. return 0, fmt.Errorf("unhandled size name: %v", extra)
  196. }
  197. var bytesSizeTable = map[string]uint64{
  198. "b": Byte, "kib": KiByte, "kb": KByte, "mib": MiByte, "mb": MByte, "gib": GiByte, "gb": GByte,
  199. "tib": TiByte, "tb": TByte, "pib": PiByte, "pb": PByte, "eib": EiByte, "eb": EByte,
  200. // Without suffix
  201. "": Byte, "ki": KiByte, "k": KByte, "mi": MiByte, "m": MByte, "gi": GiByte, "g": GByte,
  202. "ti": TiByte, "t": TByte, "pi": PiByte, "p": PByte, "ei": EiByte, "e": EByte,
  203. }
  204. // IEC Sizes.
  205. // kibis of bits
  206. const (
  207. Byte = 1 << (iota * 10)
  208. KiByte
  209. MiByte
  210. GiByte
  211. TiByte
  212. PiByte
  213. EiByte
  214. )
  215. // SI Sizes.
  216. const (
  217. IByte = 1
  218. KByte = IByte * 1000
  219. MByte = KByte * 1000
  220. GByte = MByte * 1000
  221. TByte = GByte * 1000
  222. PByte = TByte * 1000
  223. EByte = PByte * 1000
  224. )