dec.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. package terminfo
  2. import (
  3. "sort"
  4. )
  5. const (
  6. // maxFileLength is the max file length.
  7. maxFileLength = 4096
  8. // magic is the file magic for terminfo files.
  9. magic = 0o432
  10. // magicExtended is the file magic for terminfo files with the extended
  11. // number format.
  12. magicExtended = 0o1036
  13. )
  14. // header fields.
  15. const (
  16. fieldMagic = iota
  17. fieldNameSize
  18. fieldBoolCount
  19. fieldNumCount
  20. fieldStringCount
  21. fieldTableSize
  22. )
  23. // header extended fields.
  24. const (
  25. fieldExtBoolCount = iota
  26. fieldExtNumCount
  27. fieldExtStringCount
  28. fieldExtOffsetCount
  29. fieldExtTableSize
  30. )
  31. // hasInvalidCaps determines if the capabilities in h are invalid.
  32. func hasInvalidCaps(h []int) bool {
  33. return h[fieldBoolCount] > CapCountBool ||
  34. h[fieldNumCount] > CapCountNum ||
  35. h[fieldStringCount] > CapCountString
  36. }
  37. // capLength returns the total length of the capabilities in bytes.
  38. func capLength(h []int) int {
  39. return h[fieldNameSize] +
  40. h[fieldBoolCount] +
  41. (h[fieldNameSize]+h[fieldBoolCount])%2 + // account for word align
  42. h[fieldNumCount]*2 +
  43. h[fieldStringCount]*2 +
  44. h[fieldTableSize]
  45. }
  46. // hasInvalidExtOffset determines if the extended offset field is valid.
  47. func hasInvalidExtOffset(h []int) bool {
  48. return h[fieldExtBoolCount]+
  49. h[fieldExtNumCount]+
  50. h[fieldExtStringCount]*2 != h[fieldExtOffsetCount]
  51. }
  52. // extCapLength returns the total length of extended capabilities in bytes.
  53. func extCapLength(h []int, numWidth int) int {
  54. return h[fieldExtBoolCount] +
  55. h[fieldExtBoolCount]%2 + // account for word align
  56. h[fieldExtNumCount]*(numWidth/8) +
  57. h[fieldExtOffsetCount]*2 +
  58. h[fieldExtTableSize]
  59. }
  60. // findNull finds the position of null in buf.
  61. func findNull(buf []byte, i int) int {
  62. for ; i < len(buf); i++ {
  63. if buf[i] == 0 {
  64. return i
  65. }
  66. }
  67. return -1
  68. }
  69. // readStrings decodes n strings from string data table buf using the indexes in idx.
  70. func readStrings(idx []int, buf []byte, n int) (map[int][]byte, int, error) {
  71. var last int
  72. m := make(map[int][]byte)
  73. for i := 0; i < n; i++ {
  74. start := idx[i]
  75. if start < 0 {
  76. continue
  77. }
  78. if end := findNull(buf, start); end != -1 {
  79. m[i], last = buf[start:end], end+1
  80. } else {
  81. return nil, 0, ErrInvalidStringTable
  82. }
  83. }
  84. return m, last, nil
  85. }
  86. // decoder holds state info while decoding a terminfo file.
  87. type decoder struct {
  88. buf []byte
  89. pos int
  90. n int
  91. }
  92. // readBytes reads the next n bytes of buf, incrementing pos by n.
  93. func (d *decoder) readBytes(n int) ([]byte, error) {
  94. if d.n < d.pos+n {
  95. return nil, ErrUnexpectedFileEnd
  96. }
  97. n, d.pos = d.pos, d.pos+n
  98. return d.buf[n:d.pos], nil
  99. }
  100. // readInts reads n number of ints with width w.
  101. func (d *decoder) readInts(n, w int) ([]int, error) {
  102. w /= 8
  103. l := n * w
  104. buf, err := d.readBytes(l)
  105. if err != nil {
  106. return nil, err
  107. }
  108. // align
  109. d.pos += d.pos % 2
  110. z := make([]int, n)
  111. for i, j := 0, 0; i < l; i, j = i+w, j+1 {
  112. switch w {
  113. case 1:
  114. z[i] = int(buf[i])
  115. case 2:
  116. z[j] = int(int16(buf[i+1])<<8 | int16(buf[i]))
  117. case 4:
  118. z[j] = int(buf[i+3])<<24 | int(buf[i+2])<<16 | int(buf[i+1])<<8 | int(buf[i])
  119. }
  120. }
  121. return z, nil
  122. }
  123. // readBools reads the next n bools.
  124. func (d *decoder) readBools(n int) (map[int]bool, map[int]bool, error) {
  125. buf, err := d.readInts(n, 8)
  126. if err != nil {
  127. return nil, nil, err
  128. }
  129. // process
  130. bools, boolsM := make(map[int]bool), make(map[int]bool)
  131. for i, b := range buf {
  132. bools[i] = b == 1
  133. if int8(b) == -2 {
  134. boolsM[i] = true
  135. }
  136. }
  137. return bools, boolsM, nil
  138. }
  139. // readNums reads the next n nums.
  140. func (d *decoder) readNums(n, w int) (map[int]int, map[int]bool, error) {
  141. buf, err := d.readInts(n, w)
  142. if err != nil {
  143. return nil, nil, err
  144. }
  145. // process
  146. nums, numsM := make(map[int]int), make(map[int]bool)
  147. for i := 0; i < n; i++ {
  148. nums[i] = buf[i]
  149. if buf[i] == -2 {
  150. numsM[i] = true
  151. }
  152. }
  153. return nums, numsM, nil
  154. }
  155. // readStringTable reads the string data for n strings and the accompanying data
  156. // table of length sz.
  157. func (d *decoder) readStringTable(n, sz int) ([][]byte, []int, error) {
  158. buf, err := d.readInts(n, 16)
  159. if err != nil {
  160. return nil, nil, err
  161. }
  162. // read string data table
  163. data, err := d.readBytes(sz)
  164. if err != nil {
  165. return nil, nil, err
  166. }
  167. // align
  168. d.pos += d.pos % 2
  169. // process
  170. s := make([][]byte, n)
  171. var m []int
  172. for i := 0; i < n; i++ {
  173. start := buf[i]
  174. if start == -2 {
  175. m = append(m, i)
  176. } else if start >= 0 {
  177. if end := findNull(data, start); end != -1 {
  178. s[i] = data[start:end]
  179. } else {
  180. return nil, nil, ErrInvalidStringTable
  181. }
  182. }
  183. }
  184. return s, m, nil
  185. }
  186. // readStrings reads the next n strings and processes the string data table of
  187. // length sz.
  188. func (d *decoder) readStrings(n, sz int) (map[int][]byte, map[int]bool, error) {
  189. s, m, err := d.readStringTable(n, sz)
  190. if err != nil {
  191. return nil, nil, err
  192. }
  193. strs := make(map[int][]byte)
  194. for k, v := range s {
  195. if k == AcsChars {
  196. v = canonicalizeAscChars(v)
  197. }
  198. strs[k] = v
  199. }
  200. strsM := make(map[int]bool, len(m))
  201. for _, k := range m {
  202. strsM[k] = true
  203. }
  204. return strs, strsM, nil
  205. }
  206. // canonicalizeAscChars reorders chars to be unique, in order.
  207. //
  208. // see repair_ascc in ncurses-6.3/progs/dump_entry.c
  209. func canonicalizeAscChars(z []byte) []byte {
  210. var c []byte
  211. enc := make(map[byte]byte, len(z)/2)
  212. for i := 0; i < len(z); i += 2 {
  213. if _, ok := enc[z[i]]; !ok {
  214. a, b := z[i], z[i+1]
  215. // log.Printf(">>> a: %d %c, b: %d %c", a, a, b, b)
  216. c, enc[a] = append(c, b), b
  217. }
  218. }
  219. sort.Slice(c, func(i, j int) bool {
  220. return c[i] < c[j]
  221. })
  222. r := make([]byte, 2*len(c))
  223. for i := 0; i < len(c); i++ {
  224. r[i*2], r[i*2+1] = c[i], enc[c[i]]
  225. }
  226. return r
  227. }