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  }