summaryrefslogtreecommitdiffstats
path: root/src/cmd/internal/bio/buf.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/internal/bio/buf.go')
-rw-r--r--src/cmd/internal/bio/buf.go148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/cmd/internal/bio/buf.go b/src/cmd/internal/bio/buf.go
new file mode 100644
index 0000000..c4c2514
--- /dev/null
+++ b/src/cmd/internal/bio/buf.go
@@ -0,0 +1,148 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package bio implements common I/O abstractions used within the Go toolchain.
+package bio
+
+import (
+ "bufio"
+ "io"
+ "log"
+ "os"
+)
+
+// Reader implements a seekable buffered io.Reader.
+type Reader struct {
+ f *os.File
+ *bufio.Reader
+}
+
+// Writer implements a seekable buffered io.Writer.
+type Writer struct {
+ f *os.File
+ *bufio.Writer
+}
+
+// Create creates the file named name and returns a Writer
+// for that file.
+func Create(name string) (*Writer, error) {
+ f, err := os.Create(name)
+ if err != nil {
+ return nil, err
+ }
+ return &Writer{f: f, Writer: bufio.NewWriter(f)}, nil
+}
+
+// Open returns a Reader for the file named name.
+func Open(name string) (*Reader, error) {
+ f, err := os.Open(name)
+ if err != nil {
+ return nil, err
+ }
+ return NewReader(f), nil
+}
+
+// NewReader returns a Reader from an open file.
+func NewReader(f *os.File) *Reader {
+ return &Reader{f: f, Reader: bufio.NewReader(f)}
+}
+
+func (r *Reader) MustSeek(offset int64, whence int) int64 {
+ if whence == 1 {
+ offset -= int64(r.Buffered())
+ }
+ off, err := r.f.Seek(offset, whence)
+ if err != nil {
+ log.Fatalf("seeking in output: %v", err)
+ }
+ r.Reset(r.f)
+ return off
+}
+
+func (w *Writer) MustSeek(offset int64, whence int) int64 {
+ if err := w.Flush(); err != nil {
+ log.Fatalf("writing output: %v", err)
+ }
+ off, err := w.f.Seek(offset, whence)
+ if err != nil {
+ log.Fatalf("seeking in output: %v", err)
+ }
+ return off
+}
+
+func (r *Reader) Offset() int64 {
+ off, err := r.f.Seek(0, 1)
+ if err != nil {
+ log.Fatalf("seeking in output [0, 1]: %v", err)
+ }
+ off -= int64(r.Buffered())
+ return off
+}
+
+func (w *Writer) Offset() int64 {
+ if err := w.Flush(); err != nil {
+ log.Fatalf("writing output: %v", err)
+ }
+ off, err := w.f.Seek(0, 1)
+ if err != nil {
+ log.Fatalf("seeking in output [0, 1]: %v", err)
+ }
+ return off
+}
+
+func (r *Reader) Close() error {
+ return r.f.Close()
+}
+
+func (w *Writer) Close() error {
+ err := w.Flush()
+ err1 := w.f.Close()
+ if err == nil {
+ err = err1
+ }
+ return err
+}
+
+func (r *Reader) File() *os.File {
+ return r.f
+}
+
+func (w *Writer) File() *os.File {
+ return w.f
+}
+
+// Slice reads the next length bytes of r into a slice.
+//
+// This slice may be backed by mmap'ed memory. Currently, this memory
+// will never be unmapped. The second result reports whether the
+// backing memory is read-only.
+func (r *Reader) Slice(length uint64) ([]byte, bool, error) {
+ if length == 0 {
+ return []byte{}, false, nil
+ }
+
+ data, ok := r.sliceOS(length)
+ if ok {
+ return data, true, nil
+ }
+
+ data = make([]byte, length)
+ _, err := io.ReadFull(r, data)
+ if err != nil {
+ return nil, false, err
+ }
+ return data, false, nil
+}
+
+// SliceRO returns a slice containing the next length bytes of r
+// backed by a read-only mmap'd data. If the mmap cannot be
+// established (limit exceeded, region too small, etc) a nil slice
+// will be returned. If mmap succeeds, it will never be unmapped.
+func (r *Reader) SliceRO(length uint64) []byte {
+ data, ok := r.sliceOS(length)
+ if ok {
+ return data
+ }
+ return nil
+}