buf.go (3160B)
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. 6 package bio 7 8 import ( 9 "bufio" 10 "io" 11 "log" 12 "os" 13 ) 14 15 // Reader implements a seekable buffered io.Reader. 16 type Reader struct { 17 f *os.File 18 *bufio.Reader 19 } 20 21 // Writer implements a seekable buffered io.Writer. 22 type 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. 29 func 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. 38 func 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. 47 func NewReader(f *os.File) *Reader { 48 return &Reader{f: f, Reader: bufio.NewReader(f)} 49 } 50 51 func (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 63 func (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 74 func (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 83 func (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 94 func (r *Reader) Close() error { 95 return r.f.Close() 96 } 97 98 func (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 107 func (r *Reader) File() *os.File { 108 return r.f 109 } 110 111 func (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. 120 func (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. 142 func (r *Reader) SliceRO(length uint64) []byte { 143 data, ok := r.sliceOS(length) 144 if ok { 145 return data 146 } 147 return nil 148 }