github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/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  }