buf.go 3.1 KB

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