github.com/bir3/gocompiler@v0.9.2202/src/debug/elf/reader.go (about) 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 elf 6 7 import ( 8 "io" 9 "os" 10 ) 11 12 // errorReader returns error from all operations. 13 type errorReader struct { 14 error 15 } 16 17 func (r errorReader) Read(p []byte) (n int, err error) { 18 return 0, r.error 19 } 20 21 func (r errorReader) ReadAt(p []byte, off int64) (n int, err error) { 22 return 0, r.error 23 } 24 25 func (r errorReader) Seek(offset int64, whence int) (int64, error) { 26 return 0, r.error 27 } 28 29 func (r errorReader) Close() error { 30 return r.error 31 } 32 33 // readSeekerFromReader converts an io.Reader into an io.ReadSeeker. 34 // In general Seek may not be efficient, but it is optimized for 35 // common cases such as seeking to the end to find the length of the 36 // data. 37 type readSeekerFromReader struct { 38 reset func() (io.Reader, error) 39 r io.Reader 40 size int64 41 offset int64 42 } 43 44 func (r *readSeekerFromReader) start() { 45 x, err := r.reset() 46 if err != nil { 47 r.r = errorReader{err} 48 } else { 49 r.r = x 50 } 51 r.offset = 0 52 } 53 54 func (r *readSeekerFromReader) Read(p []byte) (n int, err error) { 55 if r.r == nil { 56 r.start() 57 } 58 n, err = r.r.Read(p) 59 r.offset += int64(n) 60 return n, err 61 } 62 63 func (r *readSeekerFromReader) Seek(offset int64, whence int) (int64, error) { 64 var newOffset int64 65 switch whence { 66 case io.SeekStart: 67 newOffset = offset 68 case io.SeekCurrent: 69 newOffset = r.offset + offset 70 case io.SeekEnd: 71 newOffset = r.size + offset 72 default: 73 return 0, os.ErrInvalid 74 } 75 76 switch { 77 case newOffset == r.offset: 78 return newOffset, nil 79 80 case newOffset < 0, newOffset > r.size: 81 return 0, os.ErrInvalid 82 83 case newOffset == 0: 84 r.r = nil 85 86 case newOffset == r.size: 87 r.r = errorReader{io.EOF} 88 89 default: 90 if newOffset < r.offset { 91 // Restart at the beginning. 92 r.start() 93 } 94 // Read until we reach offset. 95 var buf [512]byte 96 for r.offset < newOffset { 97 b := buf[:] 98 if newOffset-r.offset < int64(len(buf)) { 99 b = buf[:newOffset-r.offset] 100 } 101 if _, err := r.Read(b); err != nil { 102 return 0, err 103 } 104 } 105 } 106 r.offset = newOffset 107 return r.offset, nil 108 }