github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/cmd/link/internal/ld/outbuf.go (about) 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 ld 6 7 import ( 8 "bufio" 9 "cmd/internal/sys" 10 "encoding/binary" 11 "os" 12 ) 13 14 // OutBuf is a buffered file writer. 15 // 16 // It is simlar to the Writer in cmd/internal/bio with a few small differences. 17 // 18 // First, it tracks the output architecture and uses it to provide 19 // endian helpers. 20 // 21 // Second, it provides a very cheap offset counter that doesn't require 22 // any system calls to read the value. 23 type OutBuf struct { 24 arch *sys.Arch 25 off int64 26 w *bufio.Writer 27 f *os.File 28 encbuf [8]byte // temp buffer used by WriteN methods 29 } 30 31 func (out *OutBuf) SeekSet(p int64) { 32 if p == out.off { 33 return 34 } 35 out.Flush() 36 if _, err := out.f.Seek(p, 0); err != nil { 37 Exitf("seeking to %d in %s: %v", p, out.f.Name(), err) 38 } 39 out.off = p 40 } 41 42 func (out *OutBuf) Offset() int64 { 43 return out.off 44 } 45 46 // Write writes the contents of v to the buffer. 47 // 48 // As Write is backed by a bufio.Writer, callers do not have 49 // to explicitly handle the returned error as long as Flush is 50 // eventually called. 51 func (out *OutBuf) Write(v []byte) (int, error) { 52 n, err := out.w.Write(v) 53 out.off += int64(n) 54 return n, err 55 } 56 57 func (out *OutBuf) Write8(v uint8) { 58 if err := out.w.WriteByte(v); err == nil { 59 out.off++ 60 } 61 } 62 63 // WriteByte is an alias for Write8 to fulfill the io.ByteWriter interface. 64 func (out *OutBuf) WriteByte(v byte) error { 65 out.Write8(v) 66 return nil 67 } 68 69 func (out *OutBuf) Write16(v uint16) { 70 out.arch.ByteOrder.PutUint16(out.encbuf[:], v) 71 out.Write(out.encbuf[:2]) 72 } 73 74 func (out *OutBuf) Write32(v uint32) { 75 out.arch.ByteOrder.PutUint32(out.encbuf[:], v) 76 out.Write(out.encbuf[:4]) 77 } 78 79 func (out *OutBuf) Write32b(v uint32) { 80 binary.BigEndian.PutUint32(out.encbuf[:], v) 81 out.Write(out.encbuf[:4]) 82 } 83 84 func (out *OutBuf) Write64(v uint64) { 85 out.arch.ByteOrder.PutUint64(out.encbuf[:], v) 86 out.Write(out.encbuf[:8]) 87 } 88 89 func (out *OutBuf) Write64b(v uint64) { 90 binary.BigEndian.PutUint64(out.encbuf[:], v) 91 out.Write(out.encbuf[:8]) 92 } 93 94 func (out *OutBuf) WriteString(s string) { 95 n, _ := out.w.WriteString(s) 96 out.off += int64(n) 97 } 98 99 // WriteStringN writes the first n bytes of s. 100 // If n is larger than len(s) then it is padded with zero bytes. 101 func (out *OutBuf) WriteStringN(s string, n int) { 102 out.WriteStringPad(s, n, zeros[:]) 103 } 104 105 // WriteStringPad writes the first n bytes of s. 106 // If n is larger than len(s) then it is padded with the bytes in pad (repeated as needed). 107 func (out *OutBuf) WriteStringPad(s string, n int, pad []byte) { 108 if len(s) >= n { 109 out.WriteString(s[:n]) 110 } else { 111 out.WriteString(s) 112 n -= len(s) 113 for n > len(pad) { 114 out.Write(pad) 115 n -= len(pad) 116 117 } 118 out.Write(pad[:n]) 119 } 120 } 121 122 func (out *OutBuf) Flush() { 123 if err := out.w.Flush(); err != nil { 124 Exitf("flushing %s: %v", out.f.Name(), err) 125 } 126 }