utils.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "strconv"
  6. "strings"
  7. "github.com/beanzilla/gonode"
  8. "golang.org/x/exp/slices"
  9. )
  10. // Strips out the tabs in the line and returns the text
  11. func Text(n *gonode.Node) string {
  12. if n.Data() == nil {
  13. return ""
  14. }
  15. txt := fmt.Sprintf("%v", n.Data())
  16. for strings.HasPrefix(txt, "\t") {
  17. txt = txt[1:]
  18. }
  19. return txt
  20. }
  21. // Endless sky stores most data as 'key value'
  22. //
  23. // With special cases:
  24. //
  25. // As String '"some key" value' (Or '"some key" "some value"')
  26. //
  27. // As Int: '"some key" 13'
  28. //
  29. // As Float: '"some key" 9.81'
  30. //
  31. // Return's key part
  32. func Key(text string) string {
  33. parts := strings.Split(text, " ")
  34. if strings.Contains(parts[0], "\"") {
  35. pref := ""
  36. for _, part := range parts {
  37. if strings.HasSuffix(part, "\"") {
  38. if pref != "" {
  39. pref += " "
  40. }
  41. pref += part
  42. break
  43. }
  44. if pref != "" {
  45. pref += " "
  46. }
  47. pref += part
  48. }
  49. pref = strings.ReplaceAll(pref, "\"", "")
  50. return pref
  51. }
  52. return parts[0]
  53. }
  54. // Endless sky stores mose data as 'key value'
  55. //
  56. // With special cases:
  57. //
  58. // As String '"some key" value' (Or '"some key" "some value"')
  59. //
  60. // As Int: '"some key" 13'
  61. //
  62. // As Float: '"some key" 9.81'
  63. //
  64. // Return's value part (as string)
  65. func Value(text string) string {
  66. key := Key(text)
  67. val := strings.Replace(text, Format(key)+" ", "", 1)
  68. val = strings.ReplaceAll(val, "\"", "")
  69. return val
  70. }
  71. // Returns the value as integer (errors return 0)
  72. func ValueInt(text string) int {
  73. v, err := strconv.Atoi(Value(text))
  74. if err != nil {
  75. log.Printf("ValueInt('%s') => %v", Value(text), err)
  76. return 0
  77. }
  78. return v
  79. }
  80. // Returns the value as float64 (errors return 0.0)
  81. func ValueFloat64(text string) float64 {
  82. v, err := strconv.ParseFloat(text, 64)
  83. if err != nil {
  84. log.Printf("ValueFloat64('%s') => %v", Value(text), err)
  85. return 0.0
  86. }
  87. return v
  88. }
  89. // Format function
  90. //
  91. // Endless sky demands any multi word key or value must be wrapped in "s
  92. //
  93. // Both Node.Key() and Node.Value() remove the "s so this must be called to form the new Node.Line (for setters)
  94. func Format(text string) string {
  95. if strings.Contains(text, " ") {
  96. return "\"" + text + "\""
  97. }
  98. return text
  99. }
  100. // Checks if the given text could be converted to an integer
  101. //
  102. // Might want to check IsFloat first (as it includes '.')
  103. func IsInt(text string) bool {
  104. negative := false
  105. numbers := []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
  106. for _, char := range text {
  107. if char == '-' {
  108. if !negative {
  109. negative = true
  110. } else {
  111. return false
  112. }
  113. continue
  114. }
  115. if !slices.Contains(numbers, char) {
  116. return false
  117. }
  118. }
  119. return true
  120. }
  121. // Checks if the given text could be converted to a float
  122. //
  123. // Might want to check IsInt after (this checks '.')
  124. func IsFloat(text string) bool {
  125. negative := false
  126. point := false
  127. numbers := []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
  128. for _, char := range text {
  129. if char == '-' {
  130. if !negative {
  131. negative = true
  132. } else {
  133. return false
  134. }
  135. continue
  136. }
  137. if char == '.' {
  138. if !point {
  139. point = true
  140. } else {
  141. return false
  142. }
  143. continue
  144. }
  145. if !slices.Contains(numbers, char) {
  146. return false
  147. }
  148. }
  149. /* This won't require a '.' somewhere in it
  150. if !point {
  151. return false
  152. }*/
  153. return true
  154. }