main.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. package config
  2. import (
  3. "gogs.qqck.cn/s/gotools/files"
  4. "gogs.qqck.cn/s/gotools/strconv"
  5. strings2 "gogs.qqck.cn/s/gotools/strings"
  6. "strings"
  7. )
  8. const (
  9. type_line = iota
  10. type_notes
  11. type_section
  12. type_value
  13. )
  14. type Config struct {
  15. list []*item
  16. }
  17. type item struct {
  18. byte // type
  19. notes string
  20. section string
  21. key string
  22. value string
  23. }
  24. func Parse(file string) (t *Config) {
  25. t = new(Config)
  26. // -----------------------------------------------------------------------Parse
  27. if file == "" {
  28. return
  29. }
  30. j_ss := strings.Split(strings2.EmptyRight(files.GetString(file)), "\n")
  31. if len(j_ss) == 0 {
  32. return
  33. }
  34. var j_section string
  35. for j_i := 0; j_i < len(j_ss); j_i++ {
  36. switch j_ss[j_i] = strings2.Empty(j_ss[j_i]); {
  37. case j_ss[j_i] == "":
  38. t.list = append(t.list, &item{byte: type_line})
  39. case j_ss[j_i][0] == ';' || j_ss[j_i][0] == '#':
  40. t.list = append(t.list, &item{byte: type_notes, notes: j_ss[j_i]})
  41. case j_ss[j_i][0] == '[' && j_ss[j_i][len(j_ss[j_i])-1] == ']':
  42. j_section = j_ss[j_i][1 : len(j_ss[j_i])-1]
  43. t.addSection(j_section)
  44. case j_section == "":
  45. default:
  46. j_k, j_v := strings2.Empty(strings2.Left(j_ss[j_i], "=")), strings2.Empty(strings2.Right(j_ss[j_i], "="))
  47. if j_k == "" || j_v == "" {
  48. continue
  49. }
  50. t.SetValue(j_section, j_k, j_v)
  51. }
  52. }
  53. return
  54. }
  55. func (t *Config) GetString(section, key string) string {
  56. for j_i, j_item := range t.list {
  57. if j_item.byte == type_section && j_item.section == section {
  58. if j_i+1 == len(t.list) {
  59. break
  60. }
  61. for _, j_item := range t.list[j_i+1:] {
  62. if j_item.byte == type_section {
  63. break
  64. }
  65. if j_item.byte == type_value && j_item.key == key {
  66. return j_item.value
  67. }
  68. }
  69. break
  70. }
  71. }
  72. return ""
  73. }
  74. func (t *Config) GetBool(section, key string) bool {
  75. switch t.GetString(section, key) {
  76. case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "y", "ON", "on", "On":
  77. return true
  78. }
  79. return false
  80. }
  81. func (t *Config) GetInt32(section, key string) int32 {
  82. return strconv.ParseInt32(t.GetString(section, key))
  83. }
  84. func (t *Config) GetUint32(section, key string) uint32 {
  85. return strconv.ParseUint32(t.GetString(section, key))
  86. }
  87. func (t *Config) GetInt64(section, key string) int64 {
  88. return strconv.ParseInt64(t.GetString(section, key))
  89. }
  90. func (t *Config) GetUint64(section, key string) uint64 {
  91. return strconv.ParseUint64(t.GetString(section, key))
  92. }
  93. func (t *Config) GetInt(section, key string) int {
  94. return strconv.ParseInt(t.GetString(section, key))
  95. }
  96. func (t *Config) GetUint(section, key string) uint {
  97. return strconv.ParseUint(t.GetString(section, key))
  98. }
  99. func (t *Config) GetUintptr(section, key string) uintptr {
  100. return strconv.ParseUintptr(t.GetString(section, key))
  101. }
  102. func (t *Config) addSection(section string) {
  103. if section == "" {
  104. return
  105. }
  106. for _, j_item := range t.list {
  107. if j_item.byte == type_section && j_item.section == section {
  108. return
  109. }
  110. }
  111. t.list = append(t.list, &item{
  112. byte: type_section,
  113. section: section,
  114. })
  115. }
  116. func (t *Config) SetValue(section, key string, value any) {
  117. if section == "" {
  118. return
  119. }
  120. var j_i, j_i2 int
  121. var j_item *item
  122. for j_i, j_item = range t.list {
  123. if j_item.byte == type_section && j_item.section == section {
  124. for j_i2, j_item = range t.list[j_i+1:] {
  125. if j_item.byte == type_section {
  126. j_i2--
  127. break
  128. }
  129. if j_item.byte == type_value && j_item.key == key {
  130. t.setValue(j_item, value)
  131. return
  132. }
  133. }
  134. j_i += j_i2
  135. j_i += 2
  136. var j_list []*item
  137. j_item = &item{byte: type_value, key: key}
  138. t.setValue(j_item, value)
  139. if j_i > len(t.list) {
  140. t.list = append(t.list, j_item)
  141. return
  142. }
  143. j_list, t.list = t.list, nil
  144. t.list = append(t.list, j_list[:j_i]...)
  145. t.list = append(t.list, j_item)
  146. t.list = append(t.list, j_list[j_i:]...)
  147. return
  148. }
  149. }
  150. t.list = append(t.list, &item{byte: type_section, section: section})
  151. j_item = &item{byte: type_value, key: key}
  152. t.setValue(j_item, value)
  153. t.list = append(t.list, j_item)
  154. }
  155. func (t *Config) setValue(item *item, value any) bool {
  156. switch value.(type) {
  157. case string:
  158. item.value = value.(string)
  159. case byte:
  160. item.value = strconv.FormatByte(value.(byte))
  161. case bool:
  162. if value.(bool) {
  163. item.value = "1"
  164. } else {
  165. item.value = "0"
  166. }
  167. case int32:
  168. item.value = strconv.FormatInt32(value.(int32))
  169. case uint32:
  170. item.value = strconv.FormatUint32(value.(uint32))
  171. case int64:
  172. item.value = strconv.FormatInt64(value.(int64))
  173. case uint64:
  174. item.value = strconv.FormatUint64(value.(uint64))
  175. case int:
  176. item.value = strconv.FormatInt(value.(int))
  177. case uint:
  178. item.value = strconv.FormatUint(value.(uint))
  179. case uintptr:
  180. item.value = strconv.FormatUintptr(value.(uintptr))
  181. default:
  182. return false
  183. }
  184. return true
  185. }
  186. func (t *Config) Save(file string) {
  187. files.Set(file, nil)
  188. for j_i, j_item := range t.list {
  189. switch j_item.byte {
  190. case type_line:
  191. files.PutString(file, "\r\n")
  192. case type_notes:
  193. files.PutString(file, j_item.notes, "\r\n")
  194. case type_section:
  195. if j_i > 0 && t.list[j_i-1].byte != type_line {
  196. files.PutString(file, "\r\n", "[", j_item.section, "]", "\r\n")
  197. } else {
  198. files.PutString(file, "[", j_item.section, "]", "\r\n")
  199. }
  200. case type_value:
  201. files.PutString(file, j_item.key, "\t", "=", "\t", j_item.value, "\r\n")
  202. }
  203. }
  204. }