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