...

Source file src/strings/builder.go

Documentation: strings

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

View as plain text