cpp_generator.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package main
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "os"
  8. "path"
  9. "strings"
  10. "unicode"
  11. )
  12. type CppGenerator struct {
  13. includes []string
  14. files map[string]*CppGenerator
  15. Body *bytes.Buffer
  16. BodyBeforeLocalIncludes *bytes.Buffer
  17. Filename string
  18. IsHeader bool
  19. }
  20. // NewCppGenerator docsy bo ci wywali sie blad xd
  21. func NewCppGenerator(filename string) *CppGenerator {
  22. isHeader := true
  23. if strings.HasSuffix(filename, ".cpp") {
  24. isHeader = false
  25. }
  26. return &CppGenerator{
  27. includes: []string{},
  28. Body: &bytes.Buffer{},
  29. BodyBeforeLocalIncludes: &bytes.Buffer{},
  30. files: make(map[string]*CppGenerator),
  31. Filename: filename,
  32. IsHeader: isHeader,
  33. }
  34. }
  35. func (cg *CppGenerator) SubFile(filename string, isHeader bool) *CppGenerator {
  36. if gen, ok := cg.files[filename]; ok {
  37. return gen
  38. }
  39. gen := NewCppGenerator(filename)
  40. gen.IsHeader = isHeader
  41. gen.files = cg.files
  42. cg.files[filename] = gen
  43. return gen
  44. }
  45. // AddLibraryInclude yes
  46. func (cg *CppGenerator) AddLibraryInclude(name string) *CppGenerator {
  47. resultingLine := fmt.Sprintf("#include <%s>", name)
  48. for _, a := range cg.includes {
  49. if a == resultingLine {
  50. return cg
  51. }
  52. }
  53. cg.includes = append(cg.includes, resultingLine)
  54. return cg
  55. }
  56. func (cg *CppGenerator) AddLocalInclude(name string) *CppGenerator {
  57. resultingLine := fmt.Sprintf("#include \"%s\"", name)
  58. for _, a := range cg.includes {
  59. if a == resultingLine {
  60. return cg
  61. }
  62. }
  63. cg.includes = append(cg.includes, resultingLine)
  64. return cg
  65. }
  66. // OutputClassField yes
  67. func (cg *CppGenerator) OutputClassField(theType string, name string) {
  68. fmt.Fprintf(cg.Body, "%v %v;\n", theType, name)
  69. }
  70. // OutputClassTypeID yes
  71. func (cg *CppGenerator) OutputClassTypeID(theID string) {
  72. fmt.Fprintf(cg.Body, "static constexpr ReflectTypeID _TYPE_ID = ReflectTypeID::%v;\n", theID)
  73. }
  74. // OutputClass yes
  75. func (cg *CppGenerator) OutputClass(name string, cb func()) {
  76. fmt.Fprintf(cg.Body, "class %v {\npublic:\n", name)
  77. cb()
  78. fmt.Fprintf(cg.Body, "};\n\n")
  79. }
  80. // OutputEnumClass
  81. func (cg *CppGenerator) OutputEnumClass(name string, cb func()) {
  82. fmt.Fprintf(cg.Body, "enum class %v {\n", name)
  83. cb()
  84. fmt.Fprintf(cg.Body, "};\n\n")
  85. }
  86. func (cg *CppGenerator) OutputArrayVariable(t string, name string, length int, cb func()) {
  87. fmt.Fprintf(cg.Body, "%v %v[%d] = {\n", t, name, length)
  88. cb()
  89. fmt.Fprintf(cg.Body, "};\n\n")
  90. }
  91. func (cg *CppGenerator) OutputArrayVariableExtern(t string, name string, length int) {
  92. fmt.Fprintf(cg.Body, "extern %v %v[%d];", t, name, length)
  93. }
  94. func (cg *CppGenerator) OutputEnumClassField(name string, value string) {
  95. fmt.Fprintf(cg.Body, "%v", name)
  96. if value != "" {
  97. fmt.Fprintf(cg.Body, " = %v", value)
  98. }
  99. fmt.Fprintf(cg.Body, ",\n")
  100. }
  101. func (cg *CppGenerator) EscapeCppString(str string) string {
  102. d, _ := json.Marshal(str)
  103. return string(d)
  104. }
  105. func (cg *CppGenerator) WriteToWriter(w io.Writer) {
  106. fmt.Fprintf(w, "// THIS CORNFILE IS GENERATED. DO NOT EDIT! 🌽\n")
  107. guardString := "_"
  108. for _, c := range []rune(cg.Filename) {
  109. if unicode.IsUpper(c) {
  110. guardString += "_"
  111. }
  112. if unicode.IsLetter(c) {
  113. guardString += strings.ToUpper(string([]rune{c}))
  114. }
  115. }
  116. if cg.IsHeader {
  117. fmt.Fprintf(w, "#ifndef %v\n", guardString)
  118. fmt.Fprintf(w, "#define %v\n", guardString)
  119. }
  120. for _, a := range cg.includes {
  121. if strings.Contains(a, "<") {
  122. fmt.Fprintf(w, "%v\n", a)
  123. }
  124. }
  125. io.Copy(w, cg.BodyBeforeLocalIncludes)
  126. for _, a := range cg.includes {
  127. if !strings.Contains(a, "<") && a != fmt.Sprintf("#include \"%v\"", cg.Filename) {
  128. fmt.Fprintf(w, "%v\n", a)
  129. }
  130. }
  131. io.Copy(w, cg.Body)
  132. if cg.IsHeader {
  133. fmt.Fprintf(w, "#endif\n")
  134. }
  135. }
  136. func (cg *CppGenerator) OutputToDirectory(dirPath string) {
  137. f, _ := os.Create(path.Join(dirPath, cg.Filename))
  138. defer f.Close()
  139. cg.WriteToWriter(f)
  140. for _, fileToOutput := range cg.files {
  141. f, _ := os.Create(path.Join(dirPath, fileToOutput.Filename))
  142. defer f.Close()
  143. fileToOutput.WriteToWriter(f)
  144. }
  145. }