/pkg/expressions/stdlib/funcsStrings.go

https://github.com/zix99/rare · Go · 211 lines · 177 code · 28 blank · 6 comment · 52 complexity · bedd3546bad6f818c325a91ed5132e13 MD5 · raw file

  1. package stdlib
  2. import (
  3. "fmt"
  4. "rare/pkg/humanize"
  5. "strconv"
  6. "strings"
  7. . "rare/pkg/expressions" //lint:ignore ST1001 Legacy
  8. )
  9. // {prefix string prefix}
  10. func kfPrefix(args []KeyBuilderStage) KeyBuilderStage {
  11. if len(args) != 2 {
  12. return stageError(ErrorArgCount)
  13. }
  14. return KeyBuilderStage(func(context KeyBuilderContext) string {
  15. val := args[0](context)
  16. contains := args[1](context)
  17. if strings.HasPrefix(val, contains) {
  18. return val
  19. }
  20. return ""
  21. })
  22. }
  23. // {suffix string suffix}
  24. func kfSuffix(args []KeyBuilderStage) KeyBuilderStage {
  25. if len(args) != 2 {
  26. return stageError(ErrorArgCount)
  27. }
  28. return KeyBuilderStage(func(context KeyBuilderContext) string {
  29. val := args[0](context)
  30. contains := args[1](context)
  31. if strings.HasSuffix(val, contains) {
  32. return val
  33. }
  34. return ""
  35. })
  36. }
  37. // {substr {0} }
  38. func kfSubstr(args []KeyBuilderStage) KeyBuilderStage {
  39. if len(args) != 3 {
  40. return stageLiteral(ErrorArgCount)
  41. }
  42. return KeyBuilderStage(func(context KeyBuilderContext) string {
  43. s := args[0](context)
  44. lenS := len(s)
  45. if lenS == 0 {
  46. return ""
  47. }
  48. left, err1 := strconv.Atoi(args[1](context))
  49. length, err2 := strconv.Atoi(args[2](context))
  50. if err1 != nil || err2 != nil {
  51. return ErrorParsing
  52. }
  53. if length < 0 {
  54. length = 0
  55. }
  56. if left < 0 { // negative number wrap-around
  57. left += lenS
  58. if left < 0 {
  59. left = 0
  60. }
  61. } else if left > lenS {
  62. left = lenS
  63. }
  64. right := left + length
  65. if right > lenS {
  66. right = lenS
  67. }
  68. return s[left:right]
  69. })
  70. }
  71. // {select {0} 1}
  72. func kfSelect(args []KeyBuilderStage) KeyBuilderStage {
  73. if len(args) != 2 {
  74. return stageLiteral(ErrorArgCount)
  75. }
  76. return KeyBuilderStage(func(context KeyBuilderContext) string {
  77. s := args[0](context)
  78. idx, err := strconv.Atoi(args[1](context))
  79. if err != nil {
  80. return ErrorParsing
  81. }
  82. return selectField(s, idx)
  83. })
  84. }
  85. func selectField(s string, idx int) string {
  86. currIdx := 0
  87. wordStart := 0
  88. inDelim := false
  89. quoted := false
  90. for i, c := range s {
  91. if (quoted && c == '"') || (!quoted && (c == ' ' || c == '\t' || c == '\n' || c == '\x00')) {
  92. if currIdx == idx {
  93. return s[wordStart:i]
  94. }
  95. inDelim = true
  96. quoted = false
  97. } else if c == '"' {
  98. quoted = !quoted
  99. } else if inDelim {
  100. wordStart = i
  101. currIdx++
  102. inDelim = false
  103. }
  104. }
  105. if currIdx == idx {
  106. return s[wordStart:]
  107. }
  108. return ""
  109. }
  110. // {format str args...}
  111. // just like fmt.Sprintf
  112. func kfFormat(args []KeyBuilderStage) KeyBuilderStage {
  113. if len(args) < 1 {
  114. return stageError(ErrorArgCount)
  115. }
  116. return KeyBuilderStage(func(context KeyBuilderContext) string {
  117. format := args[0](context)
  118. printArgs := make([]interface{}, len(args)-1)
  119. for idx, stage := range args[1:] {
  120. printArgs[idx] = stage(context)
  121. }
  122. return fmt.Sprintf(format, printArgs...)
  123. })
  124. }
  125. func kfHumanizeInt(args []KeyBuilderStage) KeyBuilderStage {
  126. if len(args) != 1 {
  127. return stageError(ErrorArgCount)
  128. }
  129. return KeyBuilderStage(func(context KeyBuilderContext) string {
  130. val, err := strconv.Atoi(args[0](context))
  131. if err != nil {
  132. return ErrorType
  133. }
  134. return humanize.Hi(val)
  135. })
  136. }
  137. func kfHumanizeFloat(args []KeyBuilderStage) KeyBuilderStage {
  138. if len(args) != 1 {
  139. return stageError(ErrorArgCount)
  140. }
  141. return KeyBuilderStage(func(context KeyBuilderContext) string {
  142. val, err := strconv.ParseFloat(args[0](context), 64)
  143. if err != nil {
  144. return ErrorType
  145. }
  146. return humanize.Hf(val)
  147. })
  148. }
  149. func kfBytesize(args []KeyBuilderStage) KeyBuilderStage {
  150. if len(args) < 1 {
  151. return stageError(ErrorArgCount)
  152. }
  153. precision, err := strconv.Atoi(EvalStageIndexOrDefault(args, 1, "0"))
  154. if err != nil {
  155. return stageError(ErrorType)
  156. }
  157. return KeyBuilderStage(func(context KeyBuilderContext) string {
  158. val, err := strconv.ParseUint(args[0](context), 10, 64)
  159. if err != nil {
  160. return ErrorType
  161. }
  162. return humanize.AlwaysByteSize(val, precision)
  163. })
  164. }
  165. func kfJoin(delim rune) KeyBuilderFunction {
  166. return func(args []KeyBuilderStage) KeyBuilderStage {
  167. if len(args) == 0 {
  168. return stageLiteral("")
  169. }
  170. if len(args) == 1 {
  171. return args[0]
  172. }
  173. return KeyBuilderStage(func(context KeyBuilderContext) string {
  174. var sb strings.Builder
  175. sb.WriteString(args[0](context))
  176. for _, arg := range args[1:] {
  177. sb.WriteRune(delim)
  178. sb.WriteString(arg(context))
  179. }
  180. return sb.String()
  181. })
  182. }
  183. }