size.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Copyright (C) 2017 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package config
  7. import (
  8. "fmt"
  9. "strconv"
  10. "strings"
  11. "github.com/syncthing/syncthing/lib/fs"
  12. )
  13. type Size struct {
  14. Value float64 `json:"value" xml:",chardata"`
  15. Unit string `json:"unit" xml:"unit,attr"`
  16. }
  17. func ParseSize(s string) (Size, error) {
  18. s = strings.TrimSpace(s)
  19. if len(s) == 0 {
  20. return Size{}, nil
  21. }
  22. var num, unit string
  23. for i := 0; i < len(s) && (s[i] >= '0' && s[i] <= '9' || s[i] == '.' || s[i] == ','); i++ {
  24. num = s[:i+1]
  25. }
  26. var i = len(num)
  27. for i < len(s) && s[i] == ' ' {
  28. i++
  29. }
  30. unit = s[i:]
  31. val, err := strconv.ParseFloat(num, 64)
  32. if err != nil {
  33. return Size{}, err
  34. }
  35. return Size{val, unit}, nil
  36. }
  37. func (s Size) BaseValue() float64 {
  38. unitPrefix := s.Unit
  39. if len(unitPrefix) > 1 {
  40. unitPrefix = unitPrefix[:1]
  41. }
  42. mult := 1.0
  43. switch unitPrefix {
  44. case "k", "K":
  45. mult = 1000
  46. case "m", "M":
  47. mult = 1000 * 1000
  48. case "g", "G":
  49. mult = 1000 * 1000 * 1000
  50. case "t", "T":
  51. mult = 1000 * 1000 * 1000 * 1000
  52. }
  53. return s.Value * mult
  54. }
  55. func (s Size) Percentage() bool {
  56. return strings.Contains(s.Unit, "%")
  57. }
  58. func (s Size) String() string {
  59. return fmt.Sprintf("%v %s", s.Value, s.Unit)
  60. }
  61. func (Size) ParseDefault(s string) (interface{}, error) {
  62. return ParseSize(s)
  63. }
  64. func checkFreeSpace(req Size, usage fs.Usage) error {
  65. val := req.BaseValue()
  66. if val <= 0 {
  67. return nil
  68. }
  69. if req.Percentage() {
  70. freePct := (float64(usage.Free) / float64(usage.Total)) * 100
  71. if freePct < val {
  72. return fmt.Errorf("%f %% < %v", freePct, req)
  73. }
  74. } else if float64(usage.Free) < val {
  75. return fmt.Errorf("%v < %v", usage.Free, req)
  76. }
  77. return nil
  78. }