github.com/shakinm/xlsReader@v0.9.12/xls/structure/XLUnicodeRichExtendedString.go (about)

     1  package structure
     2  
     3  import (
     4  	"github.com/shakinm/xlsReader/helpers"
     5  	"unicode/utf16"
     6  )
     7  
     8  type XLUnicodeRichExtendedString struct {
     9  	Cch [2]byte
    10  
    11  	/*
    12  		A - fHighByte (1 bit): A bit that specifies whether the characters in rgb are double-byte characters.
    13  		MUST be a value from the following table:
    14  
    15  		B - reserved1 (1 bit): MUST be zero, and MUST be ignored.
    16  		C - fExtSt (1 bit): A bit that specifies whether the string contains phonetic string data
    17  		D - fRichSt (1 bit): A bit that specifies whether the string is a rich string and the string
    18  			has at least
    19  		reserved2 (4 bits): MUST be zero, and MUST be ignored.
    20  	*/
    21  	FHighByte byte // ABCD
    22  	CRun      [2]byte
    23  	CbExtRst  [4]byte
    24  	Rgb       []byte // If fHighByte is 0x0 size = cch.  If fHighByte is 0x1 size = cch*2
    25  
    26  	/*
    27  		An optional array of FormatRun structure that specifies the formatting for each
    28  		text run. The number of elements in the array is cRun. MUST exist if and only if fRichSt is 0x1.
    29  	*/
    30  	RgRun []FormatRun
    31  
    32  	/*
    33  		An optional ExtRst that specifies the phonetic string data. The size of this structure is
    34  		cbExtRst. MUST exist if and only if fExtSt is 0x1.
    35  	*/
    36  	ExtRst ExtRst
    37  }
    38  
    39  func (s *XLUnicodeRichExtendedString) Read(stream []byte)   uint32 {
    40  	var rgbSize uint16
    41  	oft := uint32(0)
    42  
    43  	copy(s.Cch[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
    44  
    45  	//offset 2
    46  	s.FHighByte = stream[iOft(&oft, 0):iOft(&oft, 1)][0]
    47  
    48  	if s.FHighByte&1 == 1 {
    49  		rgbSize = helpers.BytesToUint16(s.Cch[:]) * 2
    50  
    51  	} else {
    52  		rgbSize = helpers.BytesToUint16(s.Cch[:])
    53  
    54  	}
    55  
    56  	if s.FHighByte>>3&1 == 1 { // if fRichSt == 1
    57  
    58  		copy(s.CRun[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
    59  	}
    60  
    61  	if s.FHighByte>>2&1 == 1 { //fExtSt  == 1
    62  		//offset 4
    63  		copy(s.CbExtRst[:], stream[iOft(&oft, 0):iOft(&oft, 4)])
    64  	}
    65  
    66  	//offset rgbSize
    67  	s.Rgb = make([]byte, uint32(rgbSize))
    68  	copy(s.Rgb[0:], stream[iOft(&oft, 0):iOft(&oft, uint32(rgbSize))])
    69  
    70  	if s.FHighByte>>3&1 == 1 { // if fRichSt == 1
    71  		cRunSize := helpers.BytesToUint16(s.CRun[:])
    72  		for i := uint16(0); i <= cRunSize-1; i++ {
    73  			var rgRun FormatRun
    74  			copy(rgRun.Ich[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
    75  			copy(rgRun.Ifnt.Ifnt[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
    76  			s.RgRun = append(s.RgRun, rgRun)
    77  		}
    78  	}
    79  
    80  	if s.FHighByte>>2&1 == 1 { //fExtSt  == 1
    81  		copy(s.ExtRst.Reserved[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
    82  		copy(s.ExtRst.Cb[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
    83  
    84  		copy(s.ExtRst.Phs.Ifnt.Ifnt[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
    85  		copy(s.ExtRst.Phs.Info[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
    86  
    87  		copy(s.ExtRst.Rphssub.Crun[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
    88  		copy(s.ExtRst.Rphssub.Cch[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
    89  
    90  		copy(s.ExtRst.Rphssub.St.CchCharacters[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
    91  
    92  		rgchDataSize := helpers.BytesToUint16(s.ExtRst.Rphssub.St.CchCharacters[:]) * 2
    93  		for i := uint16(0); i <= rgchDataSize; i++ {
    94  			s.ExtRst.Rphssub.St.RgchData = append(s.ExtRst.Rphssub.St.RgchData, stream[iOft(&oft, 0):iOft(&oft, 2)]...)
    95  		}
    96  
    97  		//The number of elements in this array is rphssub.crun
    98  		phRunsSizeL := helpers.BytesToUint16(s.ExtRst.Rphssub.Crun[:])
    99  		if phRunsSizeL > 0 {
   100  			for i := uint16(0); i <= phRunsSizeL; i++ {
   101  				var phRuns PhRuns
   102  				copy(phRuns.IchFirst[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
   103  				copy(phRuns.IchMom[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
   104  				copy(phRuns.CchMom[:], stream[iOft(&oft, 0):iOft(&oft, 2)])
   105  
   106  				s.ExtRst.Rgphruns = append(s.ExtRst.Rgphruns, phRuns)
   107  			}
   108  		}
   109  	}
   110  
   111  	return oft
   112  }
   113  
   114  func iOft(offset *uint32, inc uint32) uint32 {
   115  	*offset = *offset + inc
   116  	return *offset
   117  }
   118  
   119  func (s *XLUnicodeRichExtendedString) String() string {
   120  
   121  	if s.FHighByte&1 == 1 {
   122  		name := helpers.BytesToUints16(s.Rgb[:])
   123  		runes := utf16.Decode(name)
   124  		return string(runes)
   125  	} else {
   126  
   127  		return string(s.Rgb[:])
   128  	}
   129  
   130  }