class File { static constexpr const int32_t F_EOF = -1; FS& fs; uint32_t totalSize; uint32_t curAbsPos = 0; // position withithin the whole file uint32_t curCluster = 0; // cluster we are currently reading uint32_t posInCluster = 0; // position within the current cluster public: File(FS& fs, uint32_t firstCluster, uint32_t size) : fs(fs), totalSize(size), curCluster(firstCluster) { } /** the file's size */ uint32_t getSize() const {return totalSize;} uint32_t read(uint32_t size, uint8_t* dst) { uint32_t total = 0; while(true) { const uint32_t read = _read(size, dst); if (read == F_EOF) {break;} size -= read; dst += read; total += read; } return total; } private: int32_t _read(uint32_t readSize, uint8_t* dst) { // EOF reached? if (curAbsPos >= totalSize) { return F_EOF; } // end of current cluster reached? -> determine the next one if (posInCluster == fs.tmp.bytesPerCluster) { curCluster = fs.getNextCluster(curCluster); posInCluster = 0; } // how many bytes are left in the current cluster? const uint32_t remainingInCluster = fs.tmp.bytesPerCluster - posInCluster; // determine how many bytes to read const uint32_t toRead = std::min(remainingInCluster, readSize); const uint32_t offset = fs.clusterToAbsPos(curCluster) + posInCluster; const uint32_t read = fs.dev.read(offset, toRead, dst); posInCluster += read; curAbsPos += read; return read; } };