]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Add torrent.Mmap and MmapSpan, types that abstract memory-mapped torrent data
authorMatt Joiner <anacrolix@gmail.com>
Thu, 26 Sep 2013 03:42:24 +0000 (13:42 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Thu, 26 Sep 2013 03:42:24 +0000 (13:42 +1000)
mmap_span.go [new file with mode: 0644]
span.go [new file with mode: 0644]

diff --git a/mmap_span.go b/mmap_span.go
new file mode 100644 (file)
index 0000000..e851416
--- /dev/null
@@ -0,0 +1,56 @@
+package torrent
+
+import (
+       "io"
+       "launchpad.net/gommap"
+)
+
+type Mmap struct {
+       gommap.MMap
+}
+
+func (me Mmap) Size() int64 {
+       return int64(len(me.MMap))
+}
+
+type MmapSpan []Mmap
+
+func (me MmapSpan) span() (s span) {
+       for _, mmap := range me {
+               s = append(s, mmap)
+       }
+       return
+}
+
+func (me MmapSpan) Size() (ret int64) {
+       for _, mmap := range me {
+               ret += mmap.Size()
+       }
+       return
+}
+
+func (me MmapSpan) ReadAt(p []byte, off int64) (n int, err error) {
+       me.span().ApplyTo(off, func(intervalOffset int64, interval sizer) (stop bool) {
+               _n := copy(p, interval.(Mmap).MMap[intervalOffset:])
+               p = p[_n:]
+               n += _n
+               return len(p) == 0
+       })
+       if len(p) != 0 {
+               err = io.EOF
+       }
+       return
+}
+
+func (me MmapSpan) WriteAt(p []byte, off int64) (n int, err error) {
+       me.span().ApplyTo(off, func(iOff int64, i sizer) (stop bool) {
+               _n := copy(i.(Mmap).MMap[iOff:], p)
+               p = p[_n:]
+               n += _n
+               return len(p) == 0
+       })
+       if len(p) != 0 {
+               err = io.EOF
+       }
+       return
+}
diff --git a/span.go b/span.go
new file mode 100644 (file)
index 0000000..b744926
--- /dev/null
+++ b/span.go
@@ -0,0 +1,23 @@
+package torrent
+
+type sizer interface {
+       Size() int64
+}
+
+type (
+       span []sizer
+)
+
+func (me span) ApplyTo(off int64, f func(int64, sizer) (stop bool)) {
+       for _, interval := range me {
+               iSize := interval.Size()
+               if off >= iSize {
+                       off -= iSize
+               } else {
+                       if f(off, interval) {
+                               return
+                       }
+                       off = 0
+               }
+       }
+}