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.Reader
|
||||||
io.Seeker
|
io.Seeker
|
||||||
io.Closer
|
io.Closer
|
||||||
|
io.ReaderAt
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements a Handle within a subsection of another Handle.
|
// 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
|
offset += me.off
|
||||||
} else if whence == 2 {
|
} else if whence == 2 {
|
||||||
whence = 0
|
whence = 0
|
||||||
offset = me.off + me.n
|
offset += me.off + me.n
|
||||||
}
|
}
|
||||||
ret, err = me.h.Seek(offset, whence)
|
ret, err = me.h.Seek(offset, whence)
|
||||||
|
me.cur = ret
|
||||||
ret -= me.off
|
ret -= me.off
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1766,6 +1768,17 @@ func (me *sectionHandle) Read(b []byte) (n int, err error) {
|
||||||
return
|
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) {
|
func (f File) Open() (h Handle, err error) {
|
||||||
h = f.t.NewReadHandle()
|
h = f.t.NewReadHandle()
|
||||||
_, err = h.Seek(f.offset, os.SEEK_SET)
|
_, err = h.Seek(f.offset, os.SEEK_SET)
|
||||||
|
|
55
torrent.go
55
torrent.go
|
@ -7,6 +7,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -106,9 +107,10 @@ type torrent struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A file-like handle to torrent data that implements SectionOpener. Opened
|
// 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 {
|
type handle struct {
|
||||||
rc io.ReadCloser
|
rc io.ReadCloser
|
||||||
|
rcOff int64
|
||||||
curOff int64
|
curOff int64
|
||||||
so SectionOpener
|
so SectionOpener
|
||||||
size int64
|
size int64
|
||||||
|
@ -122,41 +124,52 @@ func (h *handle) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handle) Read(b []byte) (n int, err error) {
|
func (h *handle) ReadAt(b []byte, off int64) (n int, err error) {
|
||||||
max := h.t.prepareRead(h.curOff)
|
return h.readAt(b, off)
|
||||||
if int64(len(b)) > max {
|
}
|
||||||
b = b[:max]
|
|
||||||
|
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 {
|
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 {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
h.rcOff = off
|
||||||
}
|
}
|
||||||
n, err = h.rc.Read(b)
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handle) Seek(off int64, whence int) (newOff int64, err error) {
|
func (h *handle) Seek(off int64, whence int) (newOff int64, err error) {
|
||||||
switch whence {
|
switch whence {
|
||||||
case 0:
|
case os.SEEK_SET:
|
||||||
newOff = off
|
h.curOff = off
|
||||||
case 1:
|
case os.SEEK_CUR:
|
||||||
newOff += off
|
h.curOff += off
|
||||||
case 2:
|
case os.SEEK_END:
|
||||||
newOff = h.size + off
|
h.curOff = h.size + off
|
||||||
default:
|
default:
|
||||||
err = errors.New("bad whence")
|
err = errors.New("bad whence")
|
||||||
}
|
}
|
||||||
if newOff == h.curOff {
|
newOff = h.curOff
|
||||||
return
|
|
||||||
}
|
|
||||||
h.curOff = newOff
|
|
||||||
if h.rc != nil {
|
|
||||||
h.Close()
|
|
||||||
h.rc = nil
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue