node.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package binres
  5. // NodeHeader is header all xml node types have, providing additional
  6. // information regarding an xml node over binChunkHeader.
  7. type NodeHeader struct {
  8. chunkHeader
  9. LineNumber uint32 // line number in source file this element appears
  10. Comment PoolRef // optional xml comment associated with element, MaxUint32 if none
  11. }
  12. func (hdr *NodeHeader) UnmarshalBinary(bin []byte) error {
  13. if err := (&hdr.chunkHeader).UnmarshalBinary(bin); err != nil {
  14. return err
  15. }
  16. hdr.LineNumber = btou32(bin[8:])
  17. hdr.Comment = PoolRef(btou32(bin[12:]))
  18. return nil
  19. }
  20. func (hdr *NodeHeader) MarshalBinary() ([]byte, error) {
  21. bin := make([]byte, 16)
  22. b, err := hdr.chunkHeader.MarshalBinary()
  23. if err != nil {
  24. return nil, err
  25. }
  26. copy(bin, b)
  27. putu32(bin[8:], hdr.LineNumber)
  28. putu32(bin[12:], uint32(hdr.Comment))
  29. return bin, nil
  30. }
  31. type Namespace struct {
  32. NodeHeader
  33. prefix PoolRef
  34. uri PoolRef
  35. end *Namespace // TODO don't let this type be recursive
  36. }
  37. func (ns *Namespace) UnmarshalBinary(bin []byte) error {
  38. if err := (&ns.NodeHeader).UnmarshalBinary(bin); err != nil {
  39. return err
  40. }
  41. buf := bin[ns.headerByteSize:]
  42. ns.prefix = PoolRef(btou32(buf))
  43. ns.uri = PoolRef(btou32(buf[4:]))
  44. return nil
  45. }
  46. func (ns *Namespace) MarshalBinary() ([]byte, error) {
  47. if ns.end == nil {
  48. ns.typ = ResXMLEndNamespace
  49. } else {
  50. ns.typ = ResXMLStartNamespace
  51. }
  52. ns.headerByteSize = 16
  53. ns.byteSize = 24
  54. bin := make([]byte, ns.byteSize)
  55. b, err := ns.NodeHeader.MarshalBinary()
  56. if err != nil {
  57. return nil, err
  58. }
  59. copy(bin, b)
  60. putu32(bin[16:], uint32(ns.prefix))
  61. putu32(bin[20:], uint32(ns.uri))
  62. return bin, nil
  63. }
  64. type Element struct {
  65. NodeHeader
  66. NS PoolRef
  67. Name PoolRef // name of node if element, otherwise chardata if CDATA
  68. AttributeStart uint16 // byte offset where attrs start
  69. AttributeSize uint16 // byte size of attrs
  70. AttributeCount uint16 // length of attrs
  71. IdIndex uint16 // Index (1-based) of the "id" attribute. 0 if none.
  72. ClassIndex uint16 // Index (1-based) of the "class" attribute. 0 if none.
  73. StyleIndex uint16 // Index (1-based) of the "style" attribute. 0 if none.
  74. attrs []*Attribute
  75. Children []*Element
  76. end *ElementEnd
  77. head, tail *CharData
  78. }
  79. func (el *Element) UnmarshalBinary(buf []byte) error {
  80. if err := (&el.NodeHeader).UnmarshalBinary(buf); err != nil {
  81. return err
  82. }
  83. buf = buf[el.headerByteSize:]
  84. el.NS = PoolRef(btou32(buf))
  85. el.Name = PoolRef(btou32(buf[4:]))
  86. el.AttributeStart = btou16(buf[8:])
  87. el.AttributeSize = btou16(buf[10:])
  88. el.AttributeCount = btou16(buf[12:])
  89. el.IdIndex = btou16(buf[14:])
  90. el.ClassIndex = btou16(buf[16:])
  91. el.StyleIndex = btou16(buf[18:])
  92. buf = buf[el.AttributeStart:]
  93. el.attrs = make([]*Attribute, int(el.AttributeCount))
  94. for i := range el.attrs {
  95. attr := new(Attribute)
  96. if err := attr.UnmarshalBinary(buf); err != nil {
  97. return err
  98. }
  99. el.attrs[i] = attr
  100. buf = buf[el.AttributeSize:]
  101. }
  102. return nil
  103. }
  104. func (el *Element) MarshalBinary() ([]byte, error) {
  105. el.typ = ResXMLStartElement
  106. el.headerByteSize = 16
  107. el.AttributeSize = 20
  108. el.AttributeStart = 20
  109. el.AttributeCount = uint16(len(el.attrs))
  110. el.IdIndex = 0
  111. el.ClassIndex = 0
  112. el.StyleIndex = 0
  113. el.byteSize = uint32(el.headerByteSize) + uint32(el.AttributeStart) + uint32(len(el.attrs)*int(el.AttributeSize))
  114. bin := make([]byte, el.byteSize)
  115. b, err := el.NodeHeader.MarshalBinary()
  116. if err != nil {
  117. return nil, err
  118. }
  119. copy(bin, b)
  120. putu32(bin[16:], uint32(el.NS))
  121. putu32(bin[20:], uint32(el.Name))
  122. putu16(bin[24:], el.AttributeStart)
  123. putu16(bin[26:], el.AttributeSize)
  124. putu16(bin[28:], el.AttributeCount)
  125. putu16(bin[30:], el.IdIndex)
  126. putu16(bin[32:], el.ClassIndex)
  127. putu16(bin[34:], el.StyleIndex)
  128. buf := bin[36:]
  129. for _, attr := range el.attrs {
  130. b, err := attr.MarshalBinary()
  131. if err != nil {
  132. return nil, err
  133. }
  134. copy(buf, b)
  135. buf = buf[int(el.AttributeSize):]
  136. }
  137. return bin, nil
  138. }
  139. // ElementEnd marks the end of an element node, either Element or CharData.
  140. type ElementEnd struct {
  141. NodeHeader
  142. NS PoolRef
  143. Name PoolRef // name of node if binElement, raw chardata if binCharData
  144. }
  145. func (el *ElementEnd) UnmarshalBinary(bin []byte) error {
  146. (&el.NodeHeader).UnmarshalBinary(bin)
  147. buf := bin[el.headerByteSize:]
  148. el.NS = PoolRef(btou32(buf))
  149. el.Name = PoolRef(btou32(buf[4:]))
  150. return nil
  151. }
  152. func (el *ElementEnd) MarshalBinary() ([]byte, error) {
  153. el.typ = ResXMLEndElement
  154. el.headerByteSize = 16
  155. el.byteSize = 24
  156. bin := make([]byte, 24)
  157. b, err := el.NodeHeader.MarshalBinary()
  158. if err != nil {
  159. return nil, err
  160. }
  161. copy(bin, b)
  162. putu32(bin[16:], uint32(el.NS))
  163. putu32(bin[20:], uint32(el.Name))
  164. return bin, nil
  165. }
  166. type Attribute struct {
  167. NS PoolRef
  168. Name PoolRef
  169. RawValue PoolRef // The original raw string value of this attribute.
  170. TypedValue Data // Processesd typed value of this attribute.
  171. }
  172. func (attr *Attribute) UnmarshalBinary(bin []byte) error {
  173. attr.NS = PoolRef(btou32(bin))
  174. attr.Name = PoolRef(btou32(bin[4:]))
  175. attr.RawValue = PoolRef(btou32(bin[8:]))
  176. return (&attr.TypedValue).UnmarshalBinary(bin[12:])
  177. }
  178. func (attr *Attribute) MarshalBinary() ([]byte, error) {
  179. bin := make([]byte, 20)
  180. putu32(bin, uint32(attr.NS))
  181. putu32(bin[4:], uint32(attr.Name))
  182. putu32(bin[8:], uint32(attr.RawValue))
  183. b, err := attr.TypedValue.MarshalBinary()
  184. if err != nil {
  185. return nil, err
  186. }
  187. copy(bin[12:], b)
  188. return bin, nil
  189. }
  190. // CharData represents a CDATA node and includes ref to node's text value.
  191. type CharData struct {
  192. NodeHeader
  193. RawData PoolRef // raw character data
  194. TypedData Data // typed value of character data
  195. }
  196. func (cdt *CharData) UnmarshalBinary(bin []byte) error {
  197. if err := (&cdt.NodeHeader).UnmarshalBinary(bin); err != nil {
  198. return err
  199. }
  200. buf := bin[cdt.headerByteSize:]
  201. cdt.RawData = PoolRef(btou32(buf))
  202. return (&cdt.TypedData).UnmarshalBinary(buf[4:])
  203. }
  204. func (cdt *CharData) MarshalBinary() ([]byte, error) {
  205. cdt.typ = ResXMLCharData
  206. cdt.headerByteSize = 16
  207. cdt.byteSize = 28
  208. bin := make([]byte, cdt.byteSize)
  209. b, err := cdt.NodeHeader.MarshalBinary()
  210. if err != nil {
  211. return nil, err
  212. }
  213. copy(bin, b)
  214. putu32(bin[16:], uint32(cdt.RawData))
  215. b, err = cdt.TypedData.MarshalBinary()
  216. if err != nil {
  217. return nil, err
  218. }
  219. copy(bin[20:], b)
  220. return bin, nil
  221. }