1// Copyright 2015 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 bio implements common I/O abstractions used within the Go toolchain. 6package bio 7 8import ( 9 "bufio" 10 "io" 11 "log" 12 "os" 13) 14 15// Reader implements a seekable buffered io.Reader. 16type Reader struct { 17 f *os.File 18 *bufio.Reader 19} 20 21// Writer implements a seekable buffered io.Writer. 22type Writer struct { 23 f *os.File 24 *bufio.Writer 25} 26 27// Create creates the file named name and returns a Writer 28// for that file. 29func Create(name string) (*Writer, error) { 30 f, err := os.Create(name) 31 if err != nil { 32 return nil, err 33 } 34 return &Writer{f: f, Writer: bufio.NewWriter(f)}, nil 35} 36 37// Open returns a Reader for the file named name. 38func Open(name string) (*Reader, error) { 39 f, err := os.Open(name) 40 if err != nil { 41 return nil, err 42 } 43 return NewReader(f), nil 44} 45 46// NewReader returns a Reader from an open file. 47func NewReader(f *os.File) *Reader { 48 return &Reader{f: f, Reader: bufio.NewReader(f)} 49} 50 51func (r *Reader) MustSeek(offset int64, whence int) int64 { 52 if whence == 1 { 53 offset -= int64(r.Buffered()) 54 } 55 off, err := r.f.Seek(offset, whence) 56 if err != nil { 57 log.Fatalf("seeking in output: %v", err) 58 } 59 r.Reset(r.f) 60 return off 61} 62 63func (w *Writer) MustSeek(offset int64, whence int) int64 { 64 if err := w.Flush(); err != nil { 65 log.Fatalf("writing output: %v", err) 66 } 67 off, err := w.f.Seek(offset, whence) 68 if err != nil { 69 log.Fatalf("seeking in output: %v", err) 70 } 71 return off 72} 73 74func (r *Reader) Offset() int64 { 75 off, err := r.f.Seek(0, 1) 76 if err != nil { 77 log.Fatalf("seeking in output [0, 1]: %v", err) 78 } 79 off -= int64(r.Buffered()) 80 return off 81} 82 83func (w *Writer) Offset() int64 { 84 if err := w.Flush(); err != nil { 85 log.Fatalf("writing output: %v", err) 86 } 87 off, err := w.f.Seek(0, 1) 88 if err != nil { 89 log.Fatalf("seeking in output [0, 1]: %v", err) 90 } 91 return off 92} 93 94func (r *Reader) Close() error { 95 return r.f.Close() 96} 97 98func (w *Writer) Close() error { 99 err := w.Flush() 100 err1 := w.f.Close() 101 if err == nil { 102 err = err1 103 } 104 return err 105} 106 107func (r *Reader) File() *os.File { 108 return r.f 109} 110 111func (w *Writer) File() *os.File { 112 return w.f 113} 114 115// Slice reads the next length bytes of r into a slice. 116// 117// This slice may be backed by mmap'ed memory. Currently, this memory 118// will never be unmapped. The second result reports whether the 119// backing memory is read-only. 120func (r *Reader) Slice(length uint64) ([]byte, bool, error) { 121 if length == 0 { 122 return []byte{}, false, nil 123 } 124 125 data, ok := r.sliceOS(length) 126 if ok { 127 return data, true, nil 128 } 129 130 data = make([]byte, length) 131 _, err := io.ReadFull(r, data) 132 if err != nil { 133 return nil, false, err 134 } 135 return data, false, nil 136} 137 138// SliceRO returns a slice containing the next length bytes of r 139// backed by a read-only mmap'd data. If the mmap cannot be 140// established (limit exceeded, region too small, etc) a nil slice 141// will be returned. If mmap succeeds, it will never be unmapped. 142func (r *Reader) SliceRO(length uint64) []byte { 143 data, ok := r.sliceOS(length) 144 if ok { 145 return data 146 } 147 return nil 148} 149