Allow lsDive to recurse with minimal stack usage

This commit is contained in:
Scott Lahteine
2015-05-15 03:19:07 -07:00
parent 8b2cd930c3
commit 98e91f5253
2 changed files with 63 additions and 54 deletions

View File

@ -40,24 +40,43 @@ char *createFilename(char *buffer, const dir_t &p) { //buffer > 12characters
return buffer;
}
/**
* Dive into a folder and recurse depth-first to perform a pre-set operation lsAction:
* LS_Count - Add +1 to nrFiles for every file within the parent
* LS_GetFilename - Get the filename of the file indexed by nrFiles
* LS_SerialPrint - Print the full path of each file to serial output
*/
void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) {
dir_t p;
uint8_t cnt = 0;
// Read the next entry from a directory
while (parent.readDir(p, longFilename) > 0) {
if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { // hence LS_SerialPrint
char path[FILENAME_LENGTH*2];
// If the entry is a directory and the action is LS_SerialPrint
if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) {
// Allocate enough stack space for the full path to a folder
int len = strlen(prepend) + FILENAME_LENGTH + 1;
char path[len];
// Get the short name for the item, which we know is a folder
char lfilename[FILENAME_LENGTH];
createFilename(lfilename, p);
path[0] = 0;
if (prepend[0] == 0) strcat(path, "/"); //avoid leading / if already in prepend
// Append the FOLDERNAME12/ to the passed string.
// It contains the full path to the "parent" argument.
// We now have the full path to the item in this folder.
path[0] = '\0';
if (prepend[0] == '\0') strcat(path, "/"); // a root slash if prepend is empty
strcat(path, prepend);
strcat(path, lfilename);
strcat(path, "/");
//Serial.print(path);
// Serial.print(path);
// Get a new directory object using the full path
// and dive recursively into it.
SdFile dir;
if (!dir.open(parent, lfilename, O_READ)) {
if (lsAction == LS_SerialPrint) {
@ -67,14 +86,13 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
}
}
lsDive(path, dir);
//close done automatically by destructor of SdFile
// close() is done automatically by destructor of SdFile
}
else {
char pn0 = p.name[0];
if (pn0 == DIR_NAME_FREE) break;
if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue;
char lf0 = longFilename[0];
if (lf0 == '.') continue;
if (longFilename[0] == '.') continue;
if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
@ -82,24 +100,27 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
if (!filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue;
//if (cnt++ != nr) continue;
createFilename(filename, p);
if (lsAction == LS_SerialPrint) {
SERIAL_PROTOCOL(prepend);
SERIAL_PROTOCOLLN(filename);
}
else if (lsAction == LS_Count) {
nrFiles++;
}
else if (lsAction == LS_GetFilename) {
if (match != NULL) {
if (strcasecmp(match, filename) == 0) return;
}
else if (cnt == nrFiles) return;
cnt++;
switch (lsAction) {
case LS_Count:
nrFiles++;
break;
case LS_SerialPrint:
createFilename(filename, p);
SERIAL_PROTOCOL(prepend);
SERIAL_PROTOCOLLN(filename);
break;
case LS_GetFilename:
createFilename(filename, p);
if (match != NULL) {
if (strcasecmp(match, filename) == 0) return;
}
else if (cnt == nrFiles) return;
cnt++;
break;
}
}
}
} // while readDir
}
void CardReader::ls() {