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  }