Implement Handle.ReadAt
This commit is contained in:
parent
63361b7b47
commit
779f4d3b97
15
client.go
15
client.go
|
@ -1726,6 +1726,7 @@ type Handle interface {
|
|||
io.Reader
|
||||
io.Seeker
|
||||
io.Closer
|
||||
io.ReaderAt
|
||||
}
|
||||
|
||||
// Implements a Handle within a subsection of another Handle.
|
||||
|
@ -1739,9 +1740,10 @@ func (me *sectionHandle) Seek(offset int64, whence int) (ret int64, err error) {
|
|||
offset += me.off
|
||||
} else if whence == 2 {
|
||||
whence = 0
|
||||
offset = me.off + me.n
|
||||
offset += me.off + me.n
|
||||
}
|
||||
ret, err = me.h.Seek(offset, whence)
|
||||
me.cur = ret
|
||||
ret -= me.off
|
||||
return
|
||||
}
|
||||
|
@ -1766,6 +1768,17 @@ func (me *sectionHandle) Read(b []byte) (n int, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (me *sectionHandle) ReadAt(b []byte, off int64) (n int, err error) {
|
||||
if off >= me.n {
|
||||
err = io.EOF
|
||||
return
|
||||
}
|
||||
if int64(len(b)) >= me.n-off {
|
||||
b = b[:me.n-off]
|
||||
}
|
||||
return me.h.ReadAt(b, me.off+off)
|
||||
}
|
||||
|
||||
func (f File) Open() (h Handle, err error) {
|
||||
h = f.t.NewReadHandle()
|
||||
_, err = h.Seek(f.offset, os.SEEK_SET)
|
||||
|
|
55
torrent.go
55
torrent.go
|
@ -7,6 +7,7 @@ import (
|
|||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -106,9 +107,10 @@ type torrent struct {
|
|||
}
|
||||
|
||||
// A file-like handle to torrent data that implements SectionOpener. Opened
|
||||
// sections are be reused so long as Reads are contiguous.
|
||||
// sections will be reused so long as Reads and ReadAt's are contiguous.
|
||||
type handle struct {
|
||||
rc io.ReadCloser
|
||||
rcOff int64
|
||||
curOff int64
|
||||
so SectionOpener
|
||||
size int64
|
||||
|
@ -122,41 +124,52 @@ func (h *handle) Close() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (h *handle) Read(b []byte) (n int, err error) {
|
||||
max := h.t.prepareRead(h.curOff)
|
||||
if int64(len(b)) > max {
|
||||
b = b[:max]
|
||||
func (h *handle) ReadAt(b []byte, off int64) (n int, err error) {
|
||||
return h.readAt(b, off)
|
||||
}
|
||||
|
||||
func (h *handle) readAt(b []byte, off int64) (n int, err error) {
|
||||
avail := h.t.prepareRead(off)
|
||||
if int64(len(b)) > avail {
|
||||
b = b[:avail]
|
||||
}
|
||||
if int64(len(b)) > h.size-off {
|
||||
b = b[:h.size-off]
|
||||
}
|
||||
if h.rcOff != off && h.rc != nil {
|
||||
h.rc.Close()
|
||||
h.rc = nil
|
||||
}
|
||||
if h.rc == nil {
|
||||
h.rc, err = h.so.OpenSection(h.curOff, h.size-h.curOff)
|
||||
h.rc, err = h.so.OpenSection(off, h.size-off)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
h.rcOff = off
|
||||
}
|
||||
n, err = h.rc.Read(b)
|
||||
h.curOff += int64(n)
|
||||
h.rcOff += int64(n)
|
||||
return
|
||||
}
|
||||
|
||||
func (h *handle) Read(b []byte) (n int, err error) {
|
||||
n, err = h.readAt(b, h.curOff)
|
||||
h.curOff = h.rcOff
|
||||
return
|
||||
}
|
||||
|
||||
func (h *handle) Seek(off int64, whence int) (newOff int64, err error) {
|
||||
switch whence {
|
||||
case 0:
|
||||
newOff = off
|
||||
case 1:
|
||||
newOff += off
|
||||
case 2:
|
||||
newOff = h.size + off
|
||||
case os.SEEK_SET:
|
||||
h.curOff = off
|
||||
case os.SEEK_CUR:
|
||||
h.curOff += off
|
||||
case os.SEEK_END:
|
||||
h.curOff = h.size + off
|
||||
default:
|
||||
err = errors.New("bad whence")
|
||||
}
|
||||
if newOff == h.curOff {
|
||||
return
|
||||
}
|
||||
h.curOff = newOff
|
||||
if h.rc != nil {
|
||||
h.Close()
|
||||
h.rc = nil
|
||||
}
|
||||
newOff = h.curOff
|
||||
return
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue