package org.torrent.internal.data; import java.util.Iterator; import org.torrent.internal.util.Validator; /** * * @author dante * */ public class PieceInfos implements Iterable<BTPart> { private final int piecesCount; private final int pieceLength; private final long dataSize; private final int pieceInfoLength; private int partsPerPiece; public PieceInfos(int pieceLength, long dataSize, int pieceInfoLength) { this.piecesCount = (int) ((dataSize + pieceLength - 1) / pieceLength); this.pieceLength = pieceLength; this.dataSize = dataSize; this.pieceInfoLength = pieceInfoLength; this.partsPerPiece = (pieceLength + pieceInfoLength - 1) / pieceInfoLength; } @Override public Iterator<BTPart> iterator() { return new Iterator<BTPart>() { int pieceIndex, infoIndex; @Override public boolean hasNext() { return getPieceInfo(pieceIndex, infoIndex) != null; } @Override public BTPart next() { BTPart result = getPieceInfo(pieceIndex, infoIndex); if (result != null) { infoIndex++; if (getPieceInfo(pieceIndex, infoIndex) == null) { pieceIndex++; infoIndex = 0; } } return result; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } public BTPart getPieceInfo(int pieceIndex, int infoIndex) { Validator.isTrue(pieceIndex >= 0, "Piece Index < 0!"); Validator.isTrue(infoIndex >= 0, "PieceInfo Index < 0!"); if (pieceIndex >= getPiecesCount() || infoIndex >= partsPerPiece) { return null; } int start = infoIndex * pieceInfoLength; int length = (Math.min((int) (dataSize - (long) pieceIndex * pieceLength), (infoIndex + 1) * pieceInfoLength) - start); if (length <= 0) { return null; } return new BTPart(pieceIndex, start, length); } @Override public String toString() { return "PieceInfos: dSize = " + dataSize + ", plen = " + pieceLength + ", pinfoLen = " + pieceInfoLength + " pcount = " + getPiecesCount(); } public int getPiecesCount() { return piecesCount; } public int getPieceInfoCount() { return (int) ((dataSize + pieceInfoLength - 1) / pieceInfoLength); } }