/src/go/splib/splib.go

http://github.com/speedata/publisher · Go · 201 lines · 156 code · 24 blank · 21 comment · 31 complexity · becffdcfa422d9f2b3faa3761a864262 MD5 · raw file

  1. package main
  2. import "C"
  3. import (
  4. "bytes"
  5. "encoding/xml"
  6. "fmt"
  7. "io"
  8. "os"
  9. "path/filepath"
  10. "regexp"
  11. "strings"
  12. "unsafe"
  13. "splibaux"
  14. )
  15. var (
  16. errorpattern = `**err`
  17. )
  18. // Convert a string slice to a C char* array and add a NULL pointer.
  19. func toCharArray(s []string) **C.char {
  20. cArray := C.malloc(C.size_t(len(s)+1) * C.size_t(unsafe.Sizeof(uintptr(0))))
  21. a := (*[1<<29 - 1]*C.char)(cArray)
  22. for idx, substring := range s {
  23. a[idx] = C.CString(substring)
  24. }
  25. // add sentinel
  26. a[len(s)] = nil
  27. return (**C.char)(cArray)
  28. }
  29. func s2c(input string) *C.char {
  30. return C.CString(input)
  31. }
  32. //export parseHTMLText
  33. func parseHTMLText(htmltext string, csstext string) *C.char {
  34. str, err := splibaux.ParseHTMLText(htmltext, csstext)
  35. if err != nil {
  36. return s2c(errorpattern + err.Error())
  37. }
  38. return C.CString(str)
  39. }
  40. //export parseHTML
  41. func parseHTML(filename string) *C.char {
  42. str, err := splibaux.ParseHTML(filename)
  43. if err != nil {
  44. return s2c(errorpattern + err.Error())
  45. }
  46. return C.CString(str)
  47. }
  48. //export contains
  49. func contains(haystack string, needle string) *C.char {
  50. var ret string
  51. if strings.Contains(haystack, needle) {
  52. ret = "true"
  53. } else {
  54. ret = "false"
  55. }
  56. return C.CString(ret)
  57. }
  58. //export tokenize
  59. func tokenize(text, rexpr string) **C.char {
  60. r := regexp.MustCompile(rexpr)
  61. idx := r.FindAllStringIndex(text, -1)
  62. pos := 0
  63. var res []string
  64. for _, v := range idx {
  65. res = append(res, text[pos:v[0]])
  66. pos = v[1]
  67. }
  68. res = append(res, text[pos:])
  69. return toCharArray(res)
  70. }
  71. //export replace
  72. func replace(text string, rexpr string, repl string) *C.char {
  73. r := regexp.MustCompile(rexpr)
  74. // xpath uses $12 for $12 or $1, depending on the existence of $12 or $1.
  75. // go on the other hand uses $12 for $12 and never for $1, so you have to write
  76. // $1 as ${1} if there is text after the $1.
  77. // We escape the $n backwards to prevent expansion of $12 to ${1}2
  78. for i := r.NumSubexp(); i > 0; i-- {
  79. // first create rexepx that match "$i"
  80. x := fmt.Sprintf(`\$(%d)`, i)
  81. nummatcher := regexp.MustCompile(x)
  82. repl = nummatcher.ReplaceAllString(repl, fmt.Sprintf(`$${%d}`, i))
  83. }
  84. str := r.ReplaceAllString(text, repl)
  85. return C.CString(str)
  86. }
  87. //export htmlToXml
  88. func htmlToXml(input string) *C.char {
  89. input = "<toplevel·toplevel>" + input + "</toplevel·toplevel>"
  90. r := strings.NewReader(input)
  91. var w bytes.Buffer
  92. enc := xml.NewEncoder(&w)
  93. dec := xml.NewDecoder(r)
  94. dec.Strict = false
  95. dec.AutoClose = xml.HTMLAutoClose
  96. for {
  97. t, err := dec.Token()
  98. if err == io.EOF {
  99. break
  100. }
  101. if err != nil {
  102. enc.Flush()
  103. return nil
  104. }
  105. switch v := t.(type) {
  106. case xml.StartElement:
  107. if v.Name.Local != "toplevel·toplevel" {
  108. enc.EncodeToken(t)
  109. }
  110. case xml.EndElement:
  111. if v.Name.Local != "toplevel·toplevel" {
  112. enc.EncodeToken(t)
  113. }
  114. case xml.CharData:
  115. enc.EncodeToken(t)
  116. default:
  117. // fmt.Println(v)
  118. }
  119. }
  120. enc.Flush()
  121. return C.CString(w.String())
  122. }
  123. //export buildFilelist
  124. func buildFilelist() {
  125. paths := filepath.SplitList(os.Getenv("PUBLISHER_BASE_PATH"))
  126. if fp := os.Getenv("SP_FONT_PATH"); fp != "" {
  127. for _, p := range filepath.SplitList(fp) {
  128. paths = append(paths, p)
  129. }
  130. }
  131. for _, p := range filepath.SplitList(os.Getenv("SD_EXTRA_DIRS")) {
  132. paths = append(paths, p)
  133. }
  134. splibaux.BuildFilelist(paths)
  135. }
  136. //export addDir
  137. func addDir(p string) {
  138. splibaux.AddDir(p)
  139. }
  140. //export lookupFile
  141. func lookupFile(path string) *C.char {
  142. ret, err := splibaux.GetFullPath(path)
  143. if err != nil {
  144. return s2c(errorpattern + err.Error())
  145. }
  146. return s2c(ret)
  147. }
  148. //export listFonts
  149. func listFonts() **C.char {
  150. res := splibaux.ListFonts()
  151. return toCharArray(res)
  152. }
  153. //export convertContents
  154. func convertContents(contents, handler string) *C.char {
  155. ret, err := splibaux.ConvertContents(contents, handler)
  156. if err != nil {
  157. return s2c(errorpattern + err.Error())
  158. }
  159. return s2c(ret)
  160. }
  161. //export convertImage
  162. func convertImage(filename, handler string) *C.char {
  163. ret, err := splibaux.ConvertImage(filename, handler)
  164. if err != nil {
  165. return s2c(errorpattern + err.Error())
  166. }
  167. return s2c(ret)
  168. }
  169. //export convertSVGImage
  170. func convertSVGImage(path string) *C.char {
  171. ret, err := splibaux.ConvertSVGImage(path)
  172. if err != nil {
  173. return s2c(errorpattern + err.Error())
  174. }
  175. return s2c(ret)
  176. }
  177. func main() {}