// Decode returns the Unicode code point sequence represented
// by the UTF-16 encoding s.
func Decode(s []uint16) []rune {
- a := make([]rune, len(s))
- n := 0
+ // Preallocate capacity to hold up to 64 runes.
+ // Decode inlines, so the allocation can live on the stack.
+ buf := make([]rune, 0, 64)
+ return decode(s, buf)
+}
+
+// decode appends to buf the Unicode code point sequence represented
+// by the UTF-16 encoding s and return the extended buffer.
+func decode(s []uint16, buf []rune) []rune {
for i := 0; i < len(s); i++ {
+ var ar rune
switch r := s[i]; {
case r < surr1, surr3 <= r:
// normal rune
- a[n] = rune(r)
+ ar = rune(r)
case surr1 <= r && r < surr2 && i+1 < len(s) &&
surr2 <= s[i+1] && s[i+1] < surr3:
// valid surrogate sequence
- a[n] = DecodeRune(rune(r), rune(s[i+1]))
+ ar = DecodeRune(rune(r), rune(s[i+1]))
i++
default:
// invalid surrogate sequence
- a[n] = replacementChar
+ ar = replacementChar
}
- n++
+ buf = append(buf, ar)
}
- return a[:n]
+ return buf
}
package utf16_test
import (
+ "internal/testenv"
"reflect"
"testing"
"unicode"
{[]uint16{0xdfff}, []rune{0xfffd}},
}
+func TestAllocationsDecode(t *testing.T) {
+ testenv.SkipIfOptimizationOff(t)
+
+ for _, tt := range decodeTests {
+ allocs := testing.AllocsPerRun(10, func() {
+ out := Decode(tt.in)
+ if out == nil {
+ t.Errorf("Decode(%x) = nil", tt.in)
+ }
+ })
+ if allocs > 0 {
+ t.Errorf("Decode allocated %v times", allocs)
+ }
+ }
+}
+
func TestDecode(t *testing.T) {
for _, tt := range decodeTests {
out := Decode(tt.in)