class File { static constexpr const char* NAME = "FAT32_File"; static constexpr const uint32_t F_EOF = 0xFFFFFFFF; 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 size, uint32_t firstCluster) : fs(fs), totalSize(size), curCluster(firstCluster) { Log::addInfo(NAME, "init @ cluster %d", firstCluster); } /** the file's size */ uint32_t getSize() const {return totalSize;} uint32_t read(uint32_t size, uint8_t* dst, std::function callback) { Log::addInfo(NAME, "read %d bytes", size); uint32_t remaining = size; uint32_t totalRead = 0; while(remaining) { const uint32_t read = _read(remaining, dst); if (read == F_EOF) { Log::addInfo(NAME, "EOF"); break; } remaining -= read; dst += read; totalRead += read; callback(totalRead*100/size); } return totalRead; } 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; Log::addInfo(NAME, "next cluster %d", curCluster); } // 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; } };