#include "Structs.h" #include "Helper.h" namespace FAT32 { /** combine a DirectoryEntry with its absolute location on disk */ class DirHandle { friend class File; friend class DirIterator; template friend class FS; /** the absolute byte location on the disk where the underlying DirEntry is stored */ AbsPos posOnDisk; /** the FAT32 entry format */ DirEntry entry; /** is this a valid handle? */ bool valid; public: /** ctor for an invalid handle */ DirHandle() : valid(false) {} /** ctor for a valid handle */ DirHandle(AbsPos posOnDisk, DirEntry* entry) : posOnDisk(posOnDisk), entry(*entry), valid(true) {} static DirHandle invalid() {return DirHandle();} /** is this a valid handle? */ bool isValid() const {return valid;} /** get the entry's size */ uint32_t getSize() const {return entry.size;} /** get the entry's name (filename / foldername) */ std::string getName() const { char buf[16]; // the name uint8_t pos = 0; for (uint8_t i = 0; i < 8; ++i) {if (entry.name[i] != ' ') {buf[pos++] = entry.name[i];}} // the extension (if any, folder have none) if (entry.ext[0] != ' ') { buf[pos++] = '.'; for (uint8_t i = 0; i < 3; ++i) {if ( entry.ext[i] != ' ') {buf[pos++] = entry.ext[i];}} } // null terminate and return buf[pos] = 0; std::string str(buf); toLower(str); return str; } bool isUnused() const {return entry.name[0] == 0xE5;} bool isDirectory() const {return entry.attr.bits.directory;} bool isEndOfDirectory() const {return entry.name[0] == 0x00;} bool isLongFileName() const {return (entry.attr.raw & 0b1111) == 0b1111;} bool isDot() const {return entry.name[0] == '.' && entry.name[1] == ' ';} bool isDotDot() const {return entry.name[0] == '.' && entry.name[1] == '.' && entry.name[2] == ' ';} ClusterNr getFirstCluster() const {return entry.firstClusterHi<<16 | entry.firstClusterLo<<0;} bool hasExtension(const char* ext) const { const size_t len = strlen(ext); if (len > 3) {return false;} for (int i = 0; i < len; ++i) { if (asciitolower(entry.ext[i]) != asciitolower(ext[i])) {return false;} } for (int i = len; i < 3; ++i) { if (entry.ext[i] != ' ') {return false;} } return true; } private: void setSize(uint32_t size) {entry.size = size;} /** this entry is an end-of-directory marker */ void setEndOfDirectory() { entry.name[0] = 0x00; } /** this entry is a directory */ void setDirectory() { setSize(0); entry.attr.bits.directory = 1; } /** this entry is the '.' pointer (to self) */ void setDot(ClusterNr myClusterNr) { setSize(0); entry.attr.bits.directory = 1; // not explicitly pointed out within manual, but e.g. linux needs it memcpy(entry.name83, ". ", 8+3); setFirstCluster(myClusterNr); } /** this entry is the '.' pointer (to parent) */ void setDotDot(ClusterNr parentClusterNr) { setSize(0); entry.attr.bits.directory = 1; // not explicitly pointed out within manual, but e.g. linux needs it memcpy(entry.name83, ".. ", 8+3); setFirstCluster(parentClusterNr); } void setFirstCluster(ClusterNr nr) {entry.firstClusterHi = (uint16_t)(nr << 16); entry.firstClusterLo = (uint16_t)(nr << 0);} void setName(const std::string& str) { // "zero" fill name and extension (0x20) memset(entry.name83, ' ', 11); auto pos = str.find('.'); // name for (size_t i = 0; i < min(8, min(pos, str.length())); ++i) { if (i >= 8) {break;} entry.name[i] = str[i]; } // extension (if any, folders have none) if (pos != std::string::npos) { uint32_t extLen = min(3, str.length() - pos - 1); for (size_t i = 0; i < extLen; ++i) { if (i >= 3) {break;} entry.ext[i] = str[i+pos+1]; } } } }; }