Require target lra in gcc.dg/pr108095.c
[official-gcc.git] / libgo / go / strings / builder.go
blobba4df618bfaa0329c6c525524a414e7c4eafd64d
1 // Copyright 2017 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.
5 package strings
7 import (
8 "unicode/utf8"
9 "unsafe"
12 // A Builder is used to efficiently build a string using Write methods.
13 // It minimizes memory copying. The zero value is ready to use.
14 // Do not copy a non-zero Builder.
15 type Builder struct {
16 addr *Builder // of receiver, to detect copies by value
17 buf []byte
20 // noescape hides a pointer from escape analysis. It is the identity function
21 // but escape analysis doesn't think the output depends on the input.
22 // noescape is inlined and currently compiles down to zero instructions.
23 // USE CAREFULLY!
24 // This was copied from the runtime; see issues 23382 and 7921.
25 //go:nosplit
26 //go:nocheckptr
27 func noescape(p unsafe.Pointer) unsafe.Pointer {
28 x := uintptr(p)
29 return unsafe.Pointer(x ^ 0)
32 func (b *Builder) copyCheck() {
33 if b.addr == nil {
34 // This hack works around a failing of Go's escape analysis
35 // that was causing b to escape and be heap allocated.
36 // See issue 23382.
37 // TODO: once issue 7921 is fixed, this should be reverted to
38 // just "b.addr = b".
39 b.addr = (*Builder)(noescape(unsafe.Pointer(b)))
40 } else if b.addr != b {
41 panic("strings: illegal use of non-zero Builder copied by value")
45 // String returns the accumulated string.
46 func (b *Builder) String() string {
47 return *(*string)(unsafe.Pointer(&b.buf))
50 // Len returns the number of accumulated bytes; b.Len() == len(b.String()).
51 func (b *Builder) Len() int { return len(b.buf) }
53 // Cap returns the capacity of the builder's underlying byte slice. It is the
54 // total space allocated for the string being built and includes any bytes
55 // already written.
56 func (b *Builder) Cap() int { return cap(b.buf) }
58 // Reset resets the Builder to be empty.
59 func (b *Builder) Reset() {
60 b.addr = nil
61 b.buf = nil
64 // grow copies the buffer to a new, larger buffer so that there are at least n
65 // bytes of capacity beyond len(b.buf).
66 func (b *Builder) grow(n int) {
67 buf := make([]byte, len(b.buf), 2*cap(b.buf)+n)
68 copy(buf, b.buf)
69 b.buf = buf
72 // Grow grows b's capacity, if necessary, to guarantee space for
73 // another n bytes. After Grow(n), at least n bytes can be written to b
74 // without another allocation. If n is negative, Grow panics.
75 func (b *Builder) Grow(n int) {
76 b.copyCheck()
77 if n < 0 {
78 panic("strings.Builder.Grow: negative count")
80 if cap(b.buf)-len(b.buf) < n {
81 b.grow(n)
85 // Write appends the contents of p to b's buffer.
86 // Write always returns len(p), nil.
87 func (b *Builder) Write(p []byte) (int, error) {
88 b.copyCheck()
89 b.buf = append(b.buf, p...)
90 return len(p), nil
93 // WriteByte appends the byte c to b's buffer.
94 // The returned error is always nil.
95 func (b *Builder) WriteByte(c byte) error {
96 b.copyCheck()
97 b.buf = append(b.buf, c)
98 return nil
101 // WriteRune appends the UTF-8 encoding of Unicode code point r to b's buffer.
102 // It returns the length of r and a nil error.
103 func (b *Builder) WriteRune(r rune) (int, error) {
104 b.copyCheck()
105 // Compare as uint32 to correctly handle negative runes.
106 if uint32(r) < utf8.RuneSelf {
107 b.buf = append(b.buf, byte(r))
108 return 1, nil
110 l := len(b.buf)
111 if cap(b.buf)-l < utf8.UTFMax {
112 b.grow(utf8.UTFMax)
114 n := utf8.EncodeRune(b.buf[l:l+utf8.UTFMax], r)
115 b.buf = b.buf[:l+n]
116 return n, nil
119 // WriteString appends the contents of s to b's buffer.
120 // It returns the length of s and a nil error.
121 func (b *Builder) WriteString(s string) (int, error) {
122 b.copyCheck()
123 b.buf = append(b.buf, s...)
124 return len(s), nil