📝 Document diveToFile, printListing

This commit is contained in:
Scott Lahteine 2021-05-21 22:45:54 -05:00
parent 87a943756a
commit ddc82b84e2
3 changed files with 73 additions and 52 deletions

View file

@ -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;

View file

@ -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; }