-// The relative file path for a multi-file torrent, and the torrent name for a
-// single-file torrent.
-func (f *File) DisplayPath() string {
- fip := f.FileInfo().Path
- if len(fip) == 0 {
- return f.t.info.Name
+// Number of bytes of the entire file we have completed. This is the sum of
+// completed pieces, and dirtied chunks of incomplete pieces.
+func (f *File) BytesCompleted() (n int64) {
+ f.t.cl.rLock()
+ n = f.bytesCompletedLocked()
+ f.t.cl.rUnlock()
+ return
+}
+
+func (f *File) bytesCompletedLocked() int64 {
+ return f.length - f.bytesLeft()
+}
+
+func fileBytesLeft(
+ torrentUsualPieceSize int64,
+ fileFirstPieceIndex int,
+ fileEndPieceIndex int,
+ fileTorrentOffset int64,
+ fileLength int64,
+ torrentCompletedPieces *roaring.Bitmap,
+) (left int64) {
+ numPiecesSpanned := fileEndPieceIndex - fileFirstPieceIndex
+ switch numPiecesSpanned {
+ case 0:
+ case 1:
+ if !torrentCompletedPieces.Contains(bitmap.BitIndex(fileFirstPieceIndex)) {
+ left += fileLength
+ }
+ default:
+ if !torrentCompletedPieces.Contains(bitmap.BitIndex(fileFirstPieceIndex)) {
+ left += torrentUsualPieceSize - (fileTorrentOffset % torrentUsualPieceSize)
+ }
+ if !torrentCompletedPieces.Contains(bitmap.BitIndex(fileEndPieceIndex - 1)) {
+ left += fileTorrentOffset + fileLength - int64(fileEndPieceIndex-1)*torrentUsualPieceSize
+ }
+ completedMiddlePieces := torrentCompletedPieces.Clone()
+ completedMiddlePieces.RemoveRange(0, bitmap.BitRange(fileFirstPieceIndex+1))
+ completedMiddlePieces.RemoveRange(bitmap.BitRange(fileEndPieceIndex-1), bitmap.ToEnd)
+ left += int64(numPiecesSpanned-2-pieceIndex(completedMiddlePieces.GetCardinality())) * torrentUsualPieceSize