utils.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. package utils
  2. import (
  3. "bytes"
  4. "compress/gzip"
  5. "errors"
  6. "fmt"
  7. "go/format"
  8. "html/template"
  9. "net/url"
  10. "os"
  11. "path/filepath"
  12. "strconv"
  13. "strings"
  14. "time"
  15. "unicode"
  16. "unsafe"
  17. )
  18. var DSNError = errors.New("dsn string error")
  19. func FirstCharacter(name string) string {
  20. return strings.ToLower(name)[:1]
  21. }
  22. func CamelizeStr(s string, upperCase bool) string {
  23. if len(s) == 0 {
  24. return s
  25. }
  26. s = replaceInvalidChars(s)
  27. var result string
  28. words := strings.Split(s, "_")
  29. for i, word := range words {
  30. //if upper := strings.ToUpper(word); commonInitialisms[upper] {
  31. // result += upper
  32. // continue
  33. //}
  34. if i > 0 || upperCase {
  35. result += camelizeWord(word)
  36. } else {
  37. result += word
  38. }
  39. }
  40. return result
  41. }
  42. func camelizeWord(word string) string {
  43. runes := []rune(word)
  44. for i, r := range runes {
  45. if i == 0 {
  46. runes[i] = unicode.ToUpper(r)
  47. } else {
  48. runes[i] = r
  49. //runes[i] = unicode.ToLower(r)
  50. }
  51. }
  52. return string(runes)
  53. }
  54. func replaceInvalidChars(str string) string {
  55. str = strings.ReplaceAll(str, "-", "_")
  56. str = strings.ReplaceAll(str, " ", "_")
  57. return strings.ReplaceAll(str, ".", "_")
  58. }
  59. // https://github.com/golang/lint/blob/206c0f020eba0f7fbcfbc467a5eb808037df2ed6/lint.go#L731
  60. var commonInitialisms = map[string]bool{
  61. "ACL": true,
  62. "API": true,
  63. "ASCII": true,
  64. "CPU": true,
  65. "CSS": true,
  66. "DNS": true,
  67. "EOF": true,
  68. "ETA": true,
  69. "GPU": true,
  70. "GUID": true,
  71. "HTML": true,
  72. "HTTP": true,
  73. "HTTPS": true,
  74. "ID": true,
  75. "IP": true,
  76. "JSON": true,
  77. "LHS": true,
  78. "OS": true,
  79. "QPS": true,
  80. "RAM": true,
  81. "RHS": true,
  82. "RPC": true,
  83. "SLA": true,
  84. "SMTP": true,
  85. "SQL": true,
  86. "SSH": true,
  87. "TCP": true,
  88. "TLS": true,
  89. "TTL": true,
  90. "UDP": true,
  91. "UI": true,
  92. "UID": true,
  93. "UUID": true,
  94. "URI": true,
  95. "URL": true,
  96. "UTF8": true,
  97. "VM": true,
  98. "XML": true,
  99. "XMPP": true,
  100. "XSRF": true,
  101. "XSS": true,
  102. "OAuth": true,
  103. }
  104. func GetDbNameFromDSN(dsn string) (string, error) {
  105. if len(strings.Split(dsn, " ")) > 1 {
  106. return getDbNameFromDsn(dsn)
  107. }
  108. index := strings.LastIndex(dsn, "/")
  109. if index <= 0 {
  110. return getDbNameFromDsn(dsn)
  111. }
  112. str := dsn[index:]
  113. urlStr, err := url.Parse(str)
  114. if err != nil {
  115. return "", err
  116. }
  117. return strings.Trim(urlStr.Path, "/"), nil
  118. }
  119. // host=127.0.0.1 dbname=test sslmode=disable Timezone=Asia/Shanghai
  120. const dbNamePrefix = "dbname="
  121. func getDbNameFromDsn(dsn string) (string, error) {
  122. strArray := strings.Split(dsn, " ")
  123. for _, item := range strArray {
  124. if strings.HasPrefix(item, dbNamePrefix) {
  125. return strings.TrimPrefix(item, dbNamePrefix), nil
  126. }
  127. }
  128. return "", DSNError
  129. }
  130. func SaveFile(dirPath, fileName string, text []byte) error {
  131. file, err := os.Create(filepath.Join(dirPath, fileName))
  132. if err != nil {
  133. return err
  134. }
  135. defer file.Close()
  136. p, err := format.Source(text)
  137. if err != nil {
  138. return err
  139. }
  140. _, err = file.Write(p)
  141. return err
  142. }
  143. func MkdirPathIfNotExist(dirPath string) error {
  144. if _, err := os.Stat(dirPath); os.IsNotExist(err) {
  145. return os.MkdirAll(dirPath, os.ModePerm)
  146. }
  147. return nil
  148. }
  149. func CleanUpGenFiles(dir string) error {
  150. exist, err := FileExists(dir)
  151. if err != nil {
  152. return err
  153. }
  154. if exist {
  155. return os.RemoveAll(dir)
  156. }
  157. return nil
  158. }
  159. // FileExists reports whether the named file or directory exists.
  160. func FileExists(name string) (bool, error) {
  161. if _, err := os.Stat(name); err != nil {
  162. if os.IsNotExist(err) {
  163. return false, err
  164. }
  165. }
  166. return true, nil
  167. }
  168. func ZipBytes(data []byte) []byte {
  169. var out bytes.Buffer
  170. w := gzip.NewWriter(&out)
  171. defer w.Close()
  172. w.Write(data)
  173. w.Flush()
  174. return out.Bytes()
  175. }
  176. func UnzipBytes(data []byte) []byte {
  177. var in bytes.Buffer
  178. in.Write(data)
  179. r, _ := gzip.NewReader(&in)
  180. var out bytes.Buffer
  181. defer r.Close()
  182. out.ReadFrom(r)
  183. return out.Bytes()
  184. }
  185. func Str2bytes(s string) []byte {
  186. x := (*[2]uintptr)(unsafe.Pointer(&s))
  187. h := [3]uintptr{x[0], x[1], x[1]}
  188. return *(*[]byte)(unsafe.Pointer(&h))
  189. }
  190. func Bytes2str(b []byte) string {
  191. return *(*string)(unsafe.Pointer(&b))
  192. }
  193. func If(condition bool, trueVal, falseVal interface{}) interface{} {
  194. if condition {
  195. return trueVal
  196. }
  197. return falseVal
  198. }
  199. func NewResult(rType string, rName string, apigen func(templateData interface{}, params map[string]interface{}) ([]byte, error), templateData interface{}, isCompress bool) *GenerateResult {
  200. gr := GenerateResult{}
  201. gr.Type = rType
  202. gr.Name = rName
  203. genBytes, err := apigen(templateData, nil)
  204. if err != nil {
  205. fmt.Println(err.Error())
  206. return nil
  207. }
  208. //fmt.Println(string(genBytes))
  209. if isCompress {
  210. gr.Content = ZipBytes(genBytes)
  211. } else {
  212. gr.Content = genBytes
  213. }
  214. return &gr
  215. }
  216. func ParamName(index int, param XmlApiParam) string {
  217. str := param.Name
  218. if str == "" {
  219. str = "paramObj" + strconv.Itoa(index)
  220. }
  221. return str
  222. }
  223. func GenTemplate(templateText string, templateData interface{}, params map[string]interface{}) ([]byte, error) {
  224. t, err := template.New("template").Funcs(template.FuncMap{
  225. "CamelizeStr": CamelizeStr,
  226. "FirstCharacter": FirstCharacter,
  227. "Replace": func(old, new, src string) string {
  228. return strings.ReplaceAll(src, old, new)
  229. },
  230. "Add": func(a, b int) int {
  231. return a + b
  232. },
  233. "Now": func() string {
  234. return time.Now().Format(time.RFC3339)
  235. },
  236. "Xorm": func(col XmlColumn) string {
  237. str := fmt.Sprintf(`xorm:"%s %s %s %s %s %s" `,
  238. "'"+col.Name+"'",
  239. col.DbType,
  240. If(col.IsPK, "pk", ""),
  241. If(col.AutoIncrement, "autoincr", ""),
  242. If(col.IsNull, "null", "notnull"),
  243. If(col.IsUnique, "unique", If(col.IsIndex, "index", "")))
  244. return str
  245. },
  246. "XormTime": func(time string) interface{} {
  247. return If(time == "local_time", "sysmodel.LocalTime", time)
  248. },
  249. "Backquote": func() string {
  250. return "`"
  251. },
  252. // 定义函数unescaped
  253. "Unescaped": func(x string) interface{} {
  254. return template.HTML(x)
  255. },
  256. "TrimPrefix": strings.TrimPrefix,
  257. "TrimSuffix": strings.TrimSuffix,
  258. "Contains": strings.Contains,
  259. "ParamName": ParamName,
  260. "ParamsContainDT": func(params []XmlColumn) bool {
  261. isContain := false
  262. for _, v := range params {
  263. if strings.ToLower(v.DbType) == "datetime" {
  264. isContain = true
  265. break
  266. }
  267. }
  268. return isContain
  269. },
  270. "AllParams": func(params []XmlApiParam) string {
  271. str := ""
  272. for i, v := range params {
  273. if i > 0 {
  274. str += ", "
  275. }
  276. str += ParamName(i, v)
  277. }
  278. return str
  279. },
  280. "SqlAllColumns": func(cols []XmlColumn, isValues bool) string {
  281. str := ""
  282. for i, v := range cols {
  283. if i > 0 {
  284. str += ", "
  285. }
  286. if isValues {
  287. str += "?" + v.Name
  288. } else {
  289. str += "`" + v.Name + "`"
  290. }
  291. }
  292. return str
  293. },
  294. "SqlNoPKUpdate": func(cols []XmlColumn) string {
  295. str := ""
  296. for _, v := range cols {
  297. if !v.IsPK {
  298. str += "`" + v.Name + "` = ?" + v.Name
  299. str += ", "
  300. }
  301. }
  302. out := strings.TrimSuffix(str, ", ")
  303. return out
  304. },
  305. "SqlPKWhere": func(cols []XmlColumn) string {
  306. str := ""
  307. for _, v := range cols {
  308. if v.IsPK {
  309. str += "`" + v.Name + "` = ?" + v.Name
  310. str += " AND "
  311. }
  312. }
  313. out := strings.TrimSuffix(str, " AND ")
  314. return out
  315. },
  316. "Param": func(name string) interface{} {
  317. if v, ok := params[name]; ok {
  318. return v
  319. }
  320. return ""
  321. },
  322. }).Parse(templateText)
  323. if err != nil {
  324. fmt.Println(err.Error())
  325. return nil, err
  326. }
  327. var buf bytes.Buffer
  328. if err := t.Execute(&buf, templateData); err != nil {
  329. fmt.Println(err.Error())
  330. return nil, err
  331. }
  332. return buf.Bytes(), nil
  333. }