worked on FAT stuff and tests

This commit is contained in:
2021-02-21 21:04:11 +01:00
parent 4ac72c678f
commit 2e281f6d26
12 changed files with 758 additions and 396 deletions

View File

@@ -4,25 +4,36 @@ class File {
static constexpr const uint32_t F_EOF = 0xFFFFFFFF;
FS& fs;
uint32_t totalSize;
DirHandle h;
uint32_t curAbsPos = 0; // position withithin the whole file
ClusterNr curCluster = 0; // cluster we are currently reading
uint32_t curAbsPos = 0; // absolute position withithin the file
uint32_t posInCluster = 0; // position within the current cluster
uint32_t iCurCluster = 0; // current cluster index (within list of clusters)
std::vector<ClusterNr> clusters; // all clusters the file uses
public:
File(FS& fs, uint32_t size, ClusterNr firstCluster) : fs(fs), totalSize(size), curCluster(firstCluster) {
Log::addInfo(NAME, "init @ cluster %d", firstCluster);
File(FS& fs, const DirHandle& h) : fs(fs), h(h) {
Log::addInfo(NAME, "init @ cluster %d", getFirstCluster());
getAllClusters(h.getFirstCluster());
}
/** the file's size */
uint32_t getSize() const {return totalSize;}
/** the file's USED size */
uint32_t getSize() const {return h.getSize();}
uint32_t read(uint32_t size, uint8_t* dst, std::function<void(int)> callback) {
/** the file's ALLOCATED size */
uint32_t getAllocatedSize() const {return clusters.size() * fs.tmp.bytesPerCluster;}
/** the file's first cluster */
ClusterNr getFirstCluster() const {return h.getFirstCluster();}
/** get the file's name */
std::string getName() const {return h.getName();}
/** read x bytes from the file */
uint32_t read(uint32_t size, uint8_t* dst) {
Log::addInfo(NAME, "read %d bytes", size);
@@ -37,27 +48,75 @@ public:
remaining -= read;
dst += read;
totalRead += read;
callback(totalRead*100/size);
}
return totalRead;
}
/* write the given data into the file */
uint32_t write(uint32_t size, const uint8_t* src) {
Log::addInfo(NAME, "write %d bytes", size);
uint32_t remaining = size;
uint32_t totalWritten = 0;
while(remaining) {
const uint32_t written = _write(remaining, src);
remaining -= written;
src += written;
totalWritten += written;
//callback(totalWritten*100/size);
}
// update the file header (filesize might have changed)
fs.write(h);
return totalWritten;
}
private:
void setSize(uint32_t size) {h.setSize(size);}
/** fetch the list of all clusters the file is using */
void getAllClusters(ClusterNr startCluster) {
// initial cluster
clusters.push_back(startCluster);
// all following clusters
while(true) {
startCluster = fs.getNextCluster(startCluster);
if (!startCluster.isEndOfClusters()) {
clusters.push_back(startCluster);
} else {
break;
}
}
// debug
//char buf[1024];
//char* dst = buf; dst += sprintf(dst, "clusters: ");
//for (ClusterNr nr : clusters) {dst += sprintf(dst, "%d ", nr);}
//Log::addInfo(NAME, buf);
}
int32_t _read(uint32_t readSize, uint8_t* dst) {
// EOF reached?
if (curAbsPos >= totalSize) {
if (curAbsPos >= getSize()) {
return F_EOF;
}
// end of current cluster reached? -> determine the next one
// end of current cluster reached? -> switch to the next one
if (posInCluster == fs.tmp.bytesPerCluster) {
curCluster = fs.getNextCluster(curCluster);
++iCurCluster;
posInCluster = 0;
Log::addInfo(NAME, "next cluster %d", curCluster);
Log::addInfo(NAME, "next cluster [%d] %d", iCurCluster, clusters[iCurCluster]);
}
// how many bytes are left in the current cluster?
@@ -66,7 +125,7 @@ private:
// 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 offset = fs.clusterToAbsPos(clusters[iCurCluster]) + posInCluster;
const uint32_t read = fs.dev.read(offset, toRead, dst);
posInCluster += read;
curAbsPos += read;
@@ -75,4 +134,45 @@ private:
}
int32_t _write(uint32_t writeSize, const uint8_t* src) {
// do we need to append more free sectors to the end of the file?
if (curAbsPos >= getAllocatedSize()) {
if (clusters.empty()) {
const ClusterNr newCluster = fs.allocFreeCluster(0);
clusters.push_back(newCluster);
Log::addInfo(NAME, "allocFirstCluster: %d", newCluster);
} else {
const ClusterNr prevCluster = clusters.back();
const ClusterNr newCluster = fs.allocFreeCluster(prevCluster);
clusters.push_back(newCluster);
Log::addInfo(NAME, "allocNextCluster(%d): %d", prevCluster, newCluster);
}
}
// end of current cluster reached? -> switch to the next one
if (posInCluster == fs.tmp.bytesPerCluster) {
++iCurCluster;
posInCluster = 0;
Log::addInfo(NAME, "next cluster [%d] %d", iCurCluster, clusters[iCurCluster]);
}
// how many bytes are left in the current cluster?
const uint32_t remainingInCluster = fs.tmp.bytesPerCluster - posInCluster;
// determine how many bytes to write
const uint32_t toWrite = std::min(remainingInCluster, writeSize);
const uint32_t offset = fs.clusterToAbsPos(clusters[iCurCluster]) + posInCluster;
const uint32_t written = fs.dev.write(offset, toWrite, src);
posInCluster += written;
curAbsPos += written;
// adjust the number of bytes used
if (this->getSize() < curAbsPos) {this->setSize(curAbsPos);}
return written;
}
};