github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/mobile/bind/seq/utf16.go (about)

     1  // Copyright 2014 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 seq
     6  
     7  import (
     8  	"fmt"
     9  	"unicode/utf16"
    10  	"unsafe"
    11  )
    12  
    13  // Based heavily on package unicode/utf16 from the Go standard library.
    14  
    15  const (
    16  	replacementChar = '\uFFFD'     // Unicode replacement character
    17  	maxRune         = '\U0010FFFF' // Maximum valid Unicode code point.
    18  )
    19  
    20  const (
    21  	// 0xd800-0xdc00 encodes the high 10 bits of a pair.
    22  	// 0xdc00-0xe000 encodes the low 10 bits of a pair.
    23  	// the value is those 20 bits plus 0x10000.
    24  	surr1 = 0xd800
    25  	surr2 = 0xdc00
    26  	surr3 = 0xe000
    27  
    28  	surrSelf = 0x10000
    29  )
    30  
    31  func writeUint16(b []byte, v rune) {
    32  	*(*uint16)(unsafe.Pointer(&b[0])) = uint16(v)
    33  }
    34  
    35  func (b *Buffer) WriteUTF16(s string) {
    36  	// first 4 bytes is the length, as int32. written last.
    37  	// next n bytes is utf-16 string.
    38  	if len(b.Data)-b.Offset < 4+4*len(s) {
    39  		b.grow(4 + 4*len(s)) // worst case estimate, everything is surrogate pair
    40  	}
    41  	data := b.Data[b.Offset+4:]
    42  	n := 0
    43  	for _, v := range s {
    44  		switch {
    45  		case v < 0, surr1 <= v && v < surr3, v > maxRune:
    46  			v = replacementChar
    47  			fallthrough
    48  		case v < surrSelf:
    49  			writeUint16(data[n:], v)
    50  			n += 2
    51  		default:
    52  			// surrogate pair, two uint16 values
    53  			r1, r2 := utf16.EncodeRune(v)
    54  			writeUint16(data[n:], r1)
    55  			writeUint16(data[n+2:], r2)
    56  			n += 4
    57  		}
    58  	}
    59  
    60  	// write length at b.Data[b.Offset:], before contents.
    61  	// length is number of uint16 values, not number of bytes.
    62  	b.WriteInt32(int32(n / 2))
    63  
    64  	b.Offset += n
    65  }
    66  
    67  const maxSliceLen = (1<<31 - 1) / 2
    68  
    69  func (b *Buffer) ReadUTF16() string {
    70  	size := int(b.ReadInt32())
    71  	if size == 0 {
    72  		return ""
    73  	}
    74  	if size < 0 {
    75  		panic(fmt.Sprintf("string size negative: %d", size))
    76  	}
    77  	u := (*[maxSliceLen]uint16)(unsafe.Pointer(&b.Data[b.Offset]))[:size]
    78  	s := string(utf16.Decode(u)) // TODO: save the []rune alloc
    79  	b.Offset += 2 * size
    80  
    81  	return s
    82  }