...

Source file src/pkg/debug/elf/reader.go

     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