]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Implement Handle.ReadAt
authorMatt Joiner <anacrolix@gmail.com>
Wed, 4 Mar 2015 02:06:33 +0000 (13:06 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Wed, 4 Mar 2015 02:06:33 +0000 (13:06 +1100)
client.go
torrent.go

index 648dbd9ca6f9b42b4e132620de4264b0fd7b288b..78269d6196cd329b5fa459067b7f48ae558e0318 100644 (file)
--- a/client.go
+++ b/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)
index 890d77ac11421d4d31702f01e32ca457bd3c1c7e..cd9f2633ab48059ba784576f53ba23c016b29989 100644 (file)
@@ -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
 }