mirror of
https://github.com/autc04/Retro68.git
synced 2024-11-03 07:07:20 +00:00
109 lines
2.1 KiB
Go
109 lines
2.1 KiB
Go
// 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 elf
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
)
|
|
|
|
// errorReader returns error from all operations.
|
|
type errorReader struct {
|
|
error
|
|
}
|
|
|
|
func (r errorReader) Read(p []byte) (n int, err error) {
|
|
return 0, r.error
|
|
}
|
|
|
|
func (r errorReader) ReadAt(p []byte, off int64) (n int, err error) {
|
|
return 0, r.error
|
|
}
|
|
|
|
func (r errorReader) Seek(offset int64, whence int) (int64, error) {
|
|
return 0, r.error
|
|
}
|
|
|
|
func (r errorReader) Close() error {
|
|
return r.error
|
|
}
|
|
|
|
// readSeekerFromReader converts an io.Reader into an io.ReadSeeker.
|
|
// In general Seek may not be efficient, but it is optimized for
|
|
// common cases such as seeking to the end to find the length of the
|
|
// data.
|
|
type readSeekerFromReader struct {
|
|
reset func() (io.Reader, error)
|
|
r io.Reader
|
|
size int64
|
|
offset int64
|
|
}
|
|
|
|
func (r *readSeekerFromReader) start() {
|
|
x, err := r.reset()
|
|
if err != nil {
|
|
r.r = errorReader{err}
|
|
} else {
|
|
r.r = x
|
|
}
|
|
r.offset = 0
|
|
}
|
|
|
|
func (r *readSeekerFromReader) Read(p []byte) (n int, err error) {
|
|
if r.r == nil {
|
|
r.start()
|
|
}
|
|
n, err = r.r.Read(p)
|
|
r.offset += int64(n)
|
|
return n, err
|
|
}
|
|
|
|
func (r *readSeekerFromReader) Seek(offset int64, whence int) (int64, error) {
|
|
var newOffset int64
|
|
switch whence {
|
|
case 0:
|
|
newOffset = offset
|
|
case 1:
|
|
newOffset = r.offset + offset
|
|
case 2:
|
|
newOffset = r.size + offset
|
|
default:
|
|
return 0, os.ErrInvalid
|
|
}
|
|
|
|
switch {
|
|
case newOffset == r.offset:
|
|
return newOffset, nil
|
|
|
|
case newOffset < 0, newOffset > r.size:
|
|
return 0, os.ErrInvalid
|
|
|
|
case newOffset == 0:
|
|
r.r = nil
|
|
|
|
case newOffset == r.size:
|
|
r.r = errorReader{io.EOF}
|
|
|
|
default:
|
|
if newOffset < r.offset {
|
|
// Restart at the beginning.
|
|
r.start()
|
|
}
|
|
// Read until we reach offset.
|
|
var buf [512]byte
|
|
for r.offset < newOffset {
|
|
b := buf[:]
|
|
if newOffset-r.offset < int64(len(buf)) {
|
|
b = buf[:newOffset-r.offset]
|
|
}
|
|
if _, err := r.Read(b); err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
}
|
|
r.offset = newOffset
|
|
return r.offset, nil
|
|
}
|