#include "ExtentIterator.h" namespace { int64 roundUp(int64 numToRound, int64 multiple) { return ((numToRound + multiple - 1) / multiple) * multiple; } int64 roundDown(int64 numToRound, int64 multiple) { return ((numToRound / multiple) * multiple); } } ExtentIterator::ExtentIterator(IFile * sparse_extents_f, bool take_file_ownership, int64 blocksize) : sparse_extents_f(sparse_extents_f), num_sparse_extents(-1), next_sparse_extent_num(0), take_file_ownership(take_file_ownership), blocksize(blocksize) { if (sparse_extents_f != NULL) { sparse_extents_f->Seek(0); } } ExtentIterator::~ExtentIterator() { if (!take_file_ownership) { sparse_extents_f.release(); } } IFsFile::SSparseExtent ExtentIterator::nextExtent() { if (num_sparse_extents == -1) { if (sparse_extents_f.get() == NULL || sparse_extents_f->Read(reinterpret_cast(&num_sparse_extents), sizeof(num_sparse_extents)) != sizeof(num_sparse_extents)) { num_sparse_extents = 0; } } IFsFile::SSparseExtent ret; while (next_sparse_extent_num < num_sparse_extents && ret.offset==-1) { if (sparse_extents_f->Read(reinterpret_cast(&ret), sizeof(IFsFile::SSparseExtent)) != sizeof(IFsFile::SSparseExtent)) { num_sparse_extents = 0; return IFsFile::SSparseExtent(); } else { ++next_sparse_extent_num; int64 ret_end = roundDown(ret.offset + ret.size, blocksize); ret.offset = roundUp(ret.offset, blocksize); if (ret.offset < ret_end) { ret.size = ret_end - ret.offset; return ret; } } } return IFsFile::SSparseExtent(); } void ExtentIterator::reset() { num_sparse_extents = -1; next_sparse_extent_num = 0; if (sparse_extents_f.get() != NULL) { sparse_extents_f->Seek(0); } } FsExtentIterator::FsExtentIterator(IFsFile * backing_file, int64 blocksize) : backing_file(backing_file), blocksize(blocksize) { backing_file->resetSparseExtentIter(); } IFsFile::SSparseExtent FsExtentIterator::nextExtent() { while (true) { IFsFile::SSparseExtent next = backing_file->nextSparseExtent(); if (next.offset == -1) { return next; } int64 next_end = roundDown(next.offset + next.size, blocksize); next.offset = roundUp(next.offset, blocksize); if (next.offset < next_end) { next.size = next_end - next.offset; return next; } } } void FsExtentIterator::reset() { backing_file->resetSparseExtentIter(); }