📝 Document diveToFile, printListing
This commit is contained in:
parent
87a943756a
commit
ddc82b84e2
@ -261,7 +261,14 @@ void CardReader::selectByName(SdFile dir, const char * const match) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Recursive method to list all files within a folder
|
// Recursive method to print all files within a folder in flat
|
||||||
|
// DOS 8.3 format. This style of listing is the most compatible
|
||||||
|
// with legacy hosts.
|
||||||
|
//
|
||||||
|
// This method recurses to unlimited depth and lists every
|
||||||
|
// G-code file within the given parent. If the hierarchy is
|
||||||
|
// very deep this can blow up the stack, so a 'depth' parameter
|
||||||
|
// (as with printListingJSON) would be a good addition.
|
||||||
//
|
//
|
||||||
void CardReader::printListing(SdFile parent, const char * const prepend/*=nullptr*/) {
|
void CardReader::printListing(SdFile parent, const char * const prepend/*=nullptr*/) {
|
||||||
dir_t p;
|
dir_t p;
|
||||||
@ -288,17 +295,17 @@ void CardReader::printListing(SdFile parent, const char * const prepend/*=nullpt
|
|||||||
|
|
||||||
// Get a new directory object using the full path
|
// Get a new directory object using the full path
|
||||||
// and dive recursively into it.
|
// and dive recursively into it.
|
||||||
SdFile child;
|
SdFile child; // child.close() in destructor
|
||||||
if (!child.open(&parent, dosFilename, O_READ))
|
if (child.open(&parent, dosFilename, O_READ))
|
||||||
SERIAL_ECHO_MSG(STR_SD_CANT_OPEN_SUBDIR, dosFilename);
|
|
||||||
|
|
||||||
printListing(child, path);
|
printListing(child, path);
|
||||||
// close() is done automatically by destructor of SdFile
|
else {
|
||||||
|
SERIAL_ECHO_MSG(STR_SD_CANT_OPEN_SUBDIR, dosFilename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (is_dir_or_gcode(p)) {
|
else if (is_dir_or_gcode(p)) {
|
||||||
createFilename(filename, p);
|
|
||||||
if (prepend) SERIAL_ECHO(prepend);
|
if (prepend) SERIAL_ECHO(prepend);
|
||||||
SERIAL_ECHO(filename);
|
SERIAL_ECHO(createFilename(filename, p));
|
||||||
SERIAL_CHAR(' ');
|
SERIAL_CHAR(' ');
|
||||||
SERIAL_ECHOLN(p.fileSize);
|
SERIAL_ECHOLN(p.fileSize);
|
||||||
}
|
}
|
||||||
@ -342,7 +349,7 @@ void CardReader::ls() {
|
|||||||
// Go to the next segment
|
// Go to the next segment
|
||||||
while (path[++i]) { }
|
while (path[++i]) { }
|
||||||
|
|
||||||
// SERIAL_ECHOPGM("Looking for segment: "); SERIAL_ECHOLN(segment);
|
//SERIAL_ECHOLNPAIR("Looking for segment: ", segment);
|
||||||
|
|
||||||
// Find the item, setting the long filename
|
// Find the item, setting the long filename
|
||||||
diveDir.rewind();
|
diveDir.rewind();
|
||||||
@ -720,14 +727,14 @@ void CardReader::removeFile(const char * const name) {
|
|||||||
|
|
||||||
//abortFilePrintNow();
|
//abortFilePrintNow();
|
||||||
|
|
||||||
SdFile *curDir;
|
SdFile *itsDirPtr;
|
||||||
const char * const fname = diveToFile(false, curDir, name);
|
const char * const fname = diveToFile(false, itsDirPtr, name);
|
||||||
if (!fname) return;
|
if (!fname) return;
|
||||||
|
|
||||||
#if ENABLED(SDCARD_READONLY)
|
#if ENABLED(SDCARD_READONLY)
|
||||||
SERIAL_ECHOLNPAIR("Deletion failed (read-only), File: ", fname, ".");
|
SERIAL_ECHOLNPAIR("Deletion failed (read-only), File: ", fname, ".");
|
||||||
#else
|
#else
|
||||||
if (file.remove(curDir, fname)) {
|
if (file.remove(itsDirPtr, fname)) {
|
||||||
SERIAL_ECHOLNPAIR("File deleted:", fname);
|
SERIAL_ECHOLNPAIR("File deleted:", fname);
|
||||||
sdpos = 0;
|
sdpos = 0;
|
||||||
TERN_(SDCARD_SORT_ALPHA, presort());
|
TERN_(SDCARD_SORT_ALPHA, presort());
|
||||||
@ -870,98 +877,101 @@ uint16_t CardReader::countFilesInWorkDir() {
|
|||||||
* - If update_cwd was 'true' the workDir now points to the file's directory.
|
* - If update_cwd was 'true' the workDir now points to the file's directory.
|
||||||
*
|
*
|
||||||
* Returns a pointer to the last segment (filename) of the given DOS 8.3 path.
|
* Returns a pointer to the last segment (filename) of the given DOS 8.3 path.
|
||||||
|
* On exit, inDirPtr contains an SdFile reference to the file's directory.
|
||||||
*
|
*
|
||||||
* A nullptr result indicates an unrecoverable error.
|
* A nullptr result indicates an unrecoverable error.
|
||||||
|
*
|
||||||
|
* NOTE: End the path with a slash to dive to a folder. In this case the
|
||||||
|
* returned filename will be blank (points to the end of the path).
|
||||||
*/
|
*/
|
||||||
const char* CardReader::diveToFile(const bool update_cwd, SdFile* &diveDir, const char * const path, const bool echo/*=false*/) {
|
const char* CardReader::diveToFile(const bool update_cwd, SdFile* &inDirPtr, const char * const path, const bool echo/*=false*/) {
|
||||||
DEBUG_SECTION(est, "diveToFile", true);
|
DEBUG_SECTION(est, "diveToFile", true);
|
||||||
|
|
||||||
// Track both parent and subfolder
|
// Track both parent and subfolder
|
||||||
static SdFile newDir1, newDir2;
|
static SdFile newDir1, newDir2;
|
||||||
SdFile *sub = &newDir1, *startDir;
|
SdFile *sub = &newDir1, *startDirPtr;
|
||||||
|
|
||||||
// Parsing the path string
|
// Parsing the path string
|
||||||
const char *item_name_adr = path;
|
const char *atom_ptr = path;
|
||||||
|
|
||||||
DEBUG_ECHOLNPAIR(" path = '", path, "'");
|
DEBUG_ECHOLNPAIR(" path = '", path, "'");
|
||||||
|
|
||||||
if (path[0] == '/') { // Starting at the root directory?
|
if (path[0] == '/') { // Starting at the root directory?
|
||||||
diveDir = &root;
|
inDirPtr = &root;
|
||||||
item_name_adr++;
|
atom_ptr++;
|
||||||
DEBUG_ECHOLNPAIR(" CWD to root: ", hex_address((void*)diveDir));
|
DEBUG_ECHOLNPAIR(" CWD to root: ", hex_address((void*)inDirPtr));
|
||||||
if (update_cwd) workDirDepth = 0; // The cwd can be updated for the benefit of sub-programs
|
if (update_cwd) workDirDepth = 0; // The cwd can be updated for the benefit of sub-programs
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
diveDir = &workDir; // Dive from workDir (as set by the UI)
|
inDirPtr = &workDir; // Dive from workDir (as set by the UI)
|
||||||
|
|
||||||
startDir = diveDir;
|
startDirPtr = inDirPtr;
|
||||||
|
|
||||||
DEBUG_ECHOLNPAIR(" startDir = ", hex_address((void*)startDir));
|
DEBUG_ECHOLNPAIR(" startDirPtr = ", hex_address((void*)startDirPtr));
|
||||||
|
|
||||||
while (item_name_adr) {
|
while (atom_ptr) {
|
||||||
// Find next subdirectory delimiter
|
// Find next subdirectory delimiter
|
||||||
char * const name_end = strchr(item_name_adr, '/');
|
char * const name_end = strchr(atom_ptr, '/');
|
||||||
|
|
||||||
// Last atom in the path? Item found.
|
// Last atom in the path? Item found.
|
||||||
if (name_end <= item_name_adr) break;
|
if (name_end <= atom_ptr) break;
|
||||||
|
|
||||||
// Set subDirName
|
// Isolate the next subitem name
|
||||||
const uint8_t len = name_end - item_name_adr;
|
const uint8_t len = name_end - atom_ptr;
|
||||||
char dosSubdirname[len + 1];
|
char dosSubdirname[len + 1];
|
||||||
strncpy(dosSubdirname, item_name_adr, len);
|
strncpy(dosSubdirname, atom_ptr, len);
|
||||||
dosSubdirname[len] = 0;
|
dosSubdirname[len] = 0;
|
||||||
|
|
||||||
if (echo) SERIAL_ECHOLN(dosSubdirname);
|
if (echo) SERIAL_ECHOLN(dosSubdirname);
|
||||||
|
|
||||||
DEBUG_ECHOLNPAIR(" sub = ", hex_address((void*)sub));
|
DEBUG_ECHOLNPAIR(" sub = ", hex_address((void*)sub));
|
||||||
|
|
||||||
// Open diveDir (closing first)
|
// Open inDirPtr (closing first)
|
||||||
sub->close();
|
sub->close();
|
||||||
if (!sub->open(diveDir, dosSubdirname, O_READ)) {
|
if (!sub->open(inDirPtr, dosSubdirname, O_READ)) {
|
||||||
openFailed(dosSubdirname);
|
openFailed(dosSubdirname);
|
||||||
item_name_adr = nullptr;
|
atom_ptr = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close diveDir if not at starting-point
|
// Close inDirPtr if not at starting-point
|
||||||
if (diveDir != startDir) {
|
if (inDirPtr != startDirPtr) {
|
||||||
DEBUG_ECHOLNPAIR(" closing diveDir: ", hex_address((void*)diveDir));
|
DEBUG_ECHOLNPAIR(" closing inDirPtr: ", hex_address((void*)inDirPtr));
|
||||||
diveDir->close();
|
inDirPtr->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// diveDir now subDir
|
// inDirPtr now subDir
|
||||||
diveDir = sub;
|
inDirPtr = sub;
|
||||||
DEBUG_ECHOLNPAIR(" diveDir = sub: ", hex_address((void*)diveDir));
|
DEBUG_ECHOLNPAIR(" inDirPtr = sub: ", hex_address((void*)inDirPtr));
|
||||||
|
|
||||||
// Update workDirParents and workDirDepth
|
// Update workDirParents and workDirDepth
|
||||||
if (update_cwd) {
|
if (update_cwd) {
|
||||||
DEBUG_ECHOLNPAIR(" update_cwd");
|
DEBUG_ECHOLNPAIR(" update_cwd");
|
||||||
if (workDirDepth < MAX_DIR_DEPTH)
|
if (workDirDepth < MAX_DIR_DEPTH)
|
||||||
workDirParents[workDirDepth++] = *diveDir;
|
workDirParents[workDirDepth++] = *inDirPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Point sub at the other scratch object
|
// Point sub at the other scratch object
|
||||||
sub = (diveDir != &newDir1) ? &newDir1 : &newDir2;
|
sub = (inDirPtr != &newDir1) ? &newDir1 : &newDir2;
|
||||||
DEBUG_ECHOLNPAIR(" swapping sub = ", hex_address((void*)sub));
|
DEBUG_ECHOLNPAIR(" swapping sub = ", hex_address((void*)sub));
|
||||||
|
|
||||||
// Next path atom address
|
// Next path atom address
|
||||||
item_name_adr = name_end + 1;
|
atom_ptr = name_end + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_cwd) {
|
if (update_cwd) {
|
||||||
workDir = *diveDir;
|
workDir = *inDirPtr;
|
||||||
DEBUG_ECHOLNPAIR(" final workDir = ", hex_address((void*)diveDir));
|
DEBUG_ECHOLNPAIR(" final workDir = ", hex_address((void*)inDirPtr));
|
||||||
flag.workDirIsRoot = (workDirDepth == 0);
|
flag.workDirIsRoot = (workDirDepth == 0);
|
||||||
TERN_(SDCARD_SORT_ALPHA, presort());
|
TERN_(SDCARD_SORT_ALPHA, presort());
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_ECHOLNPAIR(" returning string ", item_name_adr ?: "nullptr");
|
DEBUG_ECHOLNPAIR(" returning string ", atom_ptr ?: "nullptr");
|
||||||
return item_name_adr;
|
return atom_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardReader::cd(const char * relpath) {
|
void CardReader::cd(const char * relpath) {
|
||||||
SdFile newDir;
|
SdFile newDir, *parent = &getWorkDir();
|
||||||
SdFile *parent = workDir.isOpen() ? &workDir : &root;
|
|
||||||
|
|
||||||
if (newDir.open(parent, relpath, O_READ)) {
|
if (newDir.open(parent, relpath, O_READ)) {
|
||||||
workDir = newDir;
|
workDir = newDir;
|
||||||
|
@ -111,7 +111,6 @@ public:
|
|||||||
static void mount();
|
static void mount();
|
||||||
static void release();
|
static void release();
|
||||||
static inline bool isMounted() { return flag.mounted; }
|
static inline bool isMounted() { return flag.mounted; }
|
||||||
static void ls();
|
|
||||||
|
|
||||||
// Handle media insert/remove
|
// Handle media insert/remove
|
||||||
static void manage_media();
|
static void manage_media();
|
||||||
@ -176,8 +175,17 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for open and remove
|
/**
|
||||||
static const char* diveToFile(const bool update_cwd, SdFile* &curDir, const char * const path, const bool echo=false);
|
* Dive down to a relative or absolute path.
|
||||||
|
* Relative paths apply to the workDir.
|
||||||
|
*
|
||||||
|
* update_cwd: Pass 'true' to update the workDir on success.
|
||||||
|
* inDirPtr: On exit your pointer points to the target SdFile.
|
||||||
|
* A nullptr indicates failure.
|
||||||
|
* path: Start with '/' for abs path. End with '/' to get a folder ref.
|
||||||
|
* echo: Set 'true' to print the path throughout the loop.
|
||||||
|
*/
|
||||||
|
static const char* diveToFile(const bool update_cwd, SdFile* &inDirPtr, const char * const path, const bool echo=false);
|
||||||
|
|
||||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||||
static void presort();
|
static void presort();
|
||||||
@ -191,6 +199,8 @@ public:
|
|||||||
FORCE_INLINE static void getfilename_sorted(const uint16_t nr) { selectFileByIndex(nr); }
|
FORCE_INLINE static void getfilename_sorted(const uint16_t nr) { selectFileByIndex(nr); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void ls();
|
||||||
|
|
||||||
#if ENABLED(POWER_LOSS_RECOVERY)
|
#if ENABLED(POWER_LOSS_RECOVERY)
|
||||||
static bool jobRecoverFileExists();
|
static bool jobRecoverFileExists();
|
||||||
static void openJobRecoveryFile(const bool read);
|
static void openJobRecoveryFile(const bool read);
|
||||||
@ -199,6 +209,7 @@ public:
|
|||||||
|
|
||||||
// Current Working Dir - Set by cd, cdup, cdroot, and diveToFile(true, ...)
|
// Current Working Dir - Set by cd, cdup, cdroot, and diveToFile(true, ...)
|
||||||
static inline char* getWorkDirName() { workDir.getDosName(filename); return filename; }
|
static inline char* getWorkDirName() { workDir.getDosName(filename); return filename; }
|
||||||
|
static inline SdFile& getWorkDir() { return workDir.isOpen() ? workDir : root; }
|
||||||
|
|
||||||
// Print File stats
|
// Print File stats
|
||||||
static inline uint32_t getFileSize() { return filesize; }
|
static inline uint32_t getFileSize() { return filesize; }
|
||||||
|
Loading…
Reference in New Issue
Block a user