Files
ESP8266lib/ext/sd/fat32/DirHandle.h
2021-02-21 21:04:11 +01:00

147 lines
3.8 KiB
C++

#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 <typename BlockDev> 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];
}
}
}
};
}