github.com/stingnevermore/go@v0.0.0-20180120041312-3810f5bfed72/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 func (out *OutBuf) Write16(v uint16) { 64 out.arch.ByteOrder.PutUint16(out.encbuf[:], v) 65 out.Write(out.encbuf[:2]) 66 } 67 68 func (out *OutBuf) Write32(v uint32) { 69 out.arch.ByteOrder.PutUint32(out.encbuf[:], v) 70 out.Write(out.encbuf[:4]) 71 } 72 73 func (out *OutBuf) Write32b(v uint32) { 74 binary.BigEndian.PutUint32(out.encbuf[:], v) 75 out.Write(out.encbuf[:4]) 76 } 77 78 func (out *OutBuf) Write64(v uint64) { 79 out.arch.ByteOrder.PutUint64(out.encbuf[:], v) 80 out.Write(out.encbuf[:8]) 81 } 82 83 func (out *OutBuf) Write64b(v uint64) { 84 binary.BigEndian.PutUint64(out.encbuf[:], v) 85 out.Write(out.encbuf[:8]) 86 } 87 88 func (out *OutBuf) WriteString(s string) { 89 n, _ := out.w.WriteString(s) 90 out.off += int64(n) 91 } 92 93 // WriteStringN writes the first n bytes of s. 94 // If n is larger than len(s) then it is padded with zero bytes. 95 func (out *OutBuf) WriteStringN(s string, n int) { 96 out.WriteStringPad(s, n, zeros[:]) 97 } 98 99 // WriteStringPad writes the first n bytes of s. 100 // If n is larger than len(s) then it is padded with the bytes in pad (repeated as needed). 101 func (out *OutBuf) WriteStringPad(s string, n int, pad []byte) { 102 if len(s) >= n { 103 out.WriteString(s[:n]) 104 } else { 105 out.WriteString(s) 106 n -= len(s) 107 for n > len(pad) { 108 out.Write(pad) 109 n -= len(pad) 110 111 } 112 out.Write(pad[:n]) 113 } 114 } 115 116 func (out *OutBuf) Flush() { 117 if err := out.w.Flush(); err != nil { 118 Exitf("flushing %s: %v", out.f.Name(), err) 119 } 120 }