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