parse.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package options
  2. import (
  3. "slices"
  4. "strconv"
  5. log "github.com/sirupsen/logrus"
  6. )
  7. // ensureMaxArgs checks if the number of arguments is as expected
  8. func ensureMaxArgs(name string, args []string, max int) error {
  9. if len(args) > max {
  10. return newInvalidArgsError(name, args)
  11. }
  12. return nil
  13. }
  14. // parseBool parses a boolean option value and warns if the value is invalid
  15. func parseBool(value *bool, name string, args ...string) error {
  16. if err := ensureMaxArgs(name, args, 1); err != nil {
  17. return err
  18. }
  19. b, err := strconv.ParseBool(args[0])
  20. if err != nil {
  21. log.Warningf("%s `%s` is not a valid boolean value. Treated as false", name, args[0])
  22. }
  23. *value = b
  24. return nil
  25. }
  26. // parseFloat64 parses a float64 option value
  27. func parseFloat64(value *float64, name string, args ...string) error {
  28. if err := ensureMaxArgs(name, args, 1); err != nil {
  29. return err
  30. }
  31. f, err := strconv.ParseFloat(args[0], 64)
  32. if err != nil {
  33. return newInvalidArgsError(name, args)
  34. }
  35. *value = f
  36. return nil
  37. }
  38. // parsePositiveFloat64 parses a positive float64 option value
  39. func parsePositiveFloat64(value *float64, name string, args ...string) error {
  40. if err := ensureMaxArgs(name, args, 1); err != nil {
  41. return err
  42. }
  43. f, err := strconv.ParseFloat(args[0], 64)
  44. if err != nil || f < 0 {
  45. return newInvalidArgsError(name, args, "positive number or 0")
  46. }
  47. *value = f
  48. return nil
  49. }
  50. // parsePositiveFloat64 parses a positive float64 option value
  51. func parsePositiveNonZeroFloat64(value *float64, name string, args ...string) error {
  52. if err := ensureMaxArgs(name, args, 1); err != nil {
  53. return err
  54. }
  55. f, err := strconv.ParseFloat(args[0], 64)
  56. if err != nil || f <= 0 {
  57. return newInvalidArgsError(name, args, "positive number")
  58. }
  59. *value = f
  60. return nil
  61. }
  62. // parsePositiveFloat32 parses a positive float32 option value
  63. func parsePositiveNonZeroFloat32(value *float32, name string, args ...string) error {
  64. if err := ensureMaxArgs(name, args, 1); err != nil {
  65. return err
  66. }
  67. f, err := strconv.ParseFloat(args[0], 32)
  68. if err != nil || f <= 0 {
  69. return newInvalidArgsError(name, args, "positive number")
  70. }
  71. *value = float32(f)
  72. return nil
  73. }
  74. // parseInt parses a positive integer option value
  75. func parseInt(value *int, name string, args ...string) error {
  76. if err := ensureMaxArgs(name, args, 1); err != nil {
  77. return err
  78. }
  79. i, err := strconv.Atoi(args[0])
  80. if err != nil {
  81. return newOptionArgumentError(name, args)
  82. }
  83. *value = i
  84. return nil
  85. }
  86. // parsePositiveNonZeroInt parses a positive non-zero integer option value
  87. func parsePositiveNonZeroInt(value *int, name string, args ...string) error {
  88. if err := ensureMaxArgs(name, args, 1); err != nil {
  89. return err
  90. }
  91. i, err := strconv.Atoi(args[0])
  92. if err != nil || i <= 0 {
  93. return newInvalidArgsError(name, args, "positive number")
  94. }
  95. *value = i
  96. return nil
  97. }
  98. // parsePositiveInt parses a positive integer option value
  99. func parsePositiveInt(value *int, name string, args ...string) error {
  100. if err := ensureMaxArgs(name, args, 1); err != nil {
  101. return err
  102. }
  103. i, err := strconv.Atoi(args[0])
  104. if err != nil || i < 0 {
  105. return newOptionArgumentError("Invalid %s arguments: %s (expected positive number)", name, args)
  106. }
  107. *value = i
  108. return nil
  109. }
  110. // parseQualityInt parses a quality integer option value (1-100)
  111. func parseQualityInt(value *int, name string, args ...string) error {
  112. if err := ensureMaxArgs(name, args, 1); err != nil {
  113. return err
  114. }
  115. i, err := strconv.Atoi(args[0])
  116. if err != nil || i < 1 || i > 100 {
  117. return newInvalidArgsError(name, args, "number in range 1-100")
  118. }
  119. *value = i
  120. return nil
  121. }
  122. func isGravityOffcetValid(gravity GravityType, offset float64) bool {
  123. return gravity != GravityFocusPoint || (offset >= 0 && offset <= 1)
  124. }
  125. func parseGravity(g *GravityOptions, name string, args []string, allowedTypes []GravityType) error {
  126. nArgs := len(args)
  127. if t, ok := gravityTypes[args[0]]; ok && slices.Contains(allowedTypes, t) {
  128. g.Type = t
  129. } else {
  130. return newOptionArgumentError("Invalid %s: %s", name, args[0])
  131. }
  132. switch g.Type {
  133. case GravitySmart:
  134. if nArgs > 1 {
  135. return newInvalidArgsError(name, args)
  136. }
  137. g.X, g.Y = 0.0, 0.0
  138. case GravityFocusPoint:
  139. if nArgs != 3 {
  140. return newInvalidArgsError(name, args)
  141. }
  142. fallthrough
  143. default:
  144. if nArgs > 3 {
  145. return newInvalidArgsError(name, args)
  146. }
  147. if nArgs > 1 {
  148. if x, err := strconv.ParseFloat(args[1], 64); err == nil && isGravityOffcetValid(g.Type, x) {
  149. g.X = x
  150. } else {
  151. return newOptionArgumentError("Invalid %s X: %s", name, args[1])
  152. }
  153. }
  154. if nArgs > 2 {
  155. if y, err := strconv.ParseFloat(args[2], 64); err == nil && isGravityOffcetValid(g.Type, y) {
  156. g.Y = y
  157. } else {
  158. return newOptionArgumentError("Invalid %s Y: %s", name, args[2])
  159. }
  160. }
  161. }
  162. return nil
  163. }
  164. func parseExtend(opts *ExtendOptions, name string, args []string) error {
  165. if err := ensureMaxArgs(name, args, 4); err != nil {
  166. return err
  167. }
  168. if err := parseBool(&opts.Enabled, name+" enabled", args[0]); err != nil {
  169. return err
  170. }
  171. if len(args) > 1 {
  172. return parseGravity(&opts.Gravity, name+" gravity", args[1:], extendGravityTypes)
  173. }
  174. return nil
  175. }