...

Source file src/debug/elf/reader.go

Documentation: debug/elf

		 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 seekStart:
		67  		newOffset = offset
		68  	case seekCurrent:
		69  		newOffset = r.offset + offset
		70  	case 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  }
	 109  

View as plain text