Browse Source

Allow lsDive to recurse with minimal stack usage

Scott Lahteine 9 years ago
parent
commit
98e91f5253
2 changed files with 63 additions and 54 deletions
  1. 18
    30
      Marlin/SdBaseFile.cpp
  2. 45
    24
      Marlin/cardreader.cpp

+ 18
- 30
Marlin/SdBaseFile.cpp View File

@@ -1114,50 +1114,38 @@ int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) {
1114 1114
   if (!isDir() || (0X1F & curPosition_)) return -1;
1115 1115
   
1116 1116
   //If we have a longFilename buffer, mark it as invalid. If we find a long filename it will be filled automaticly.
1117
-  if (longFilename != NULL)
1118
-  {
1119
-  	longFilename[0] = '\0';
1120
-  }
1117
+  if (longFilename != NULL) longFilename[0] = '\0';
1121 1118
 
1122 1119
   while (1) {
1120
+
1123 1121
     n = read(dir, sizeof(dir_t));
1124 1122
     if (n != sizeof(dir_t)) return n == 0 ? 0 : -1;
1123
+
1125 1124
     // last entry if DIR_NAME_FREE
1126 1125
     if (dir->name[0] == DIR_NAME_FREE) return 0;
1126
+
1127 1127
     // skip empty entries and entry for .  and ..
1128 1128
     if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue;
1129
-    //Fill the long filename if we have a long filename entry,
1130
-	// long filename entries are stored before the actual filename.
1131
-	if (DIR_IS_LONG_NAME(dir) && longFilename != NULL)
1132
-    {
1129
+
1130
+    // Fill the long filename if we have a long filename entry.
1131
+    // Long filename entries are stored before the short filename.
1132
+    if (longFilename != NULL && DIR_IS_LONG_NAME(dir)) {
1133 1133
     	vfat_t *VFAT = (vfat_t*)dir;
1134
-		//Sanity check the VFAT entry. The first cluster is always set to zero. And th esequence number should be higher then 0
1135
-    	if (VFAT->firstClusterLow == 0 && (VFAT->sequenceNumber & 0x1F) > 0 && (VFAT->sequenceNumber & 0x1F) <= MAX_VFAT_ENTRIES)
1136
-    	{
1137
-			//TODO: Store the filename checksum to verify if a none-long filename aware system modified the file table.
1134
+  		// Sanity-check the VFAT entry. The first cluster is always set to zero. And the sequence number should be higher than 0
1135
+    	if (VFAT->firstClusterLow == 0 && (VFAT->sequenceNumber & 0x1F) > 0 && (VFAT->sequenceNumber & 0x1F) <= MAX_VFAT_ENTRIES) {
1136
+  			// TODO: Store the filename checksum to verify if a none-long filename aware system modified the file table.
1138 1137
     		n = ((VFAT->sequenceNumber & 0x1F) - 1) * FILENAME_LENGTH;
1139
-			longFilename[n+0] = VFAT->name1[0];
1140
-			longFilename[n+1] = VFAT->name1[1];
1141
-			longFilename[n+2] = VFAT->name1[2];
1142
-			longFilename[n+3] = VFAT->name1[3];
1143
-			longFilename[n+4] = VFAT->name1[4];
1144
-			longFilename[n+5] = VFAT->name2[0];
1145
-			longFilename[n+6] = VFAT->name2[1];
1146
-			longFilename[n+7] = VFAT->name2[2];
1147
-			longFilename[n+8] = VFAT->name2[3];
1148
-			longFilename[n+9] = VFAT->name2[4];
1149
-			longFilename[n+10] = VFAT->name2[5];
1150
-			longFilename[n+11] = VFAT->name3[0];
1151
-			longFilename[n+12] = VFAT->name3[1];
1152
-			//If this VFAT entry is the last one, add a NUL terminator at the end of the string
1153
-			if (VFAT->sequenceNumber & 0x40)
1154
-				longFilename[n+FILENAME_LENGTH] = '\0';
1155
-		}
1138
+        for (uint8_t i=0; i<FILENAME_LENGTH; i++)
1139
+          longFilename[n+i] = (i < 5) ? VFAT->name1[i] : (i < 11) ? VFAT->name2[i-5] : VFAT->name3[i-11];
1140
+        // If this VFAT entry is the last one, add a NUL terminator at the end of the string
1141
+        if (VFAT->sequenceNumber & 0x40) longFilename[n+FILENAME_LENGTH] = '\0';
1142
+  		}
1156 1143
     }
1157
-    // return if normal file or subdirectory
1144
+    // Return if normal file or subdirectory
1158 1145
     if (DIR_IS_FILE_OR_SUBDIR(dir)) return n;
1159 1146
   }
1160 1147
 }
1148
+
1161 1149
 //------------------------------------------------------------------------------
1162 1150
 // Read next directory entry into the cache
1163 1151
 // Assumes file is correctly positioned

+ 45
- 24
Marlin/cardreader.cpp View File

@@ -40,24 +40,43 @@ char *createFilename(char *buffer, const dir_t &p) { //buffer > 12characters
40 40
   return buffer;
41 41
 }
42 42
 
43
+/**
44
+ * Dive into a folder and recurse depth-first to perform a pre-set operation lsAction:
45
+ *   LS_Count       - Add +1 to nrFiles for every file within the parent
46
+ *   LS_GetFilename - Get the filename of the file indexed by nrFiles
47
+ *   LS_SerialPrint - Print the full path of each file to serial output
48
+ */
43 49
 void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) {
44 50
   dir_t p;
45 51
   uint8_t cnt = 0;
46 52
 
53
+  // Read the next entry from a directory
47 54
   while (parent.readDir(p, longFilename) > 0) {
48
-    if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { // hence LS_SerialPrint
49
-      char path[FILENAME_LENGTH*2];
55
+
56
+    // If the entry is a directory and the action is LS_SerialPrint
57
+    if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) {
58
+
59
+      // Allocate enough stack space for the full path to a folder
60
+      int len = strlen(prepend) + FILENAME_LENGTH + 1;
61
+      char path[len];
62
+
63
+      // Get the short name for the item, which we know is a folder
50 64
       char lfilename[FILENAME_LENGTH];
51 65
       createFilename(lfilename, p);
52 66
 
53
-      path[0] = 0;
54
-      if (prepend[0] == 0) strcat(path, "/"); //avoid leading / if already in prepend
67
+      // Append the FOLDERNAME12/ to the passed string.
68
+      // It contains the full path to the "parent" argument.
69
+      // We now have the full path to the item in this folder.
70
+      path[0] = '\0';
71
+      if (prepend[0] == '\0') strcat(path, "/"); // a root slash if prepend is empty
55 72
       strcat(path, prepend);
56 73
       strcat(path, lfilename);
57 74
       strcat(path, "/");
58 75
 
59
-      //Serial.print(path);
76
+      // Serial.print(path);
60 77
 
78
+      // Get a new directory object using the full path
79
+      // and dive recursively into it.
61 80
       SdFile dir;
62 81
       if (!dir.open(parent, lfilename, O_READ)) {
63 82
         if (lsAction == LS_SerialPrint) {
@@ -67,14 +86,13 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
67 86
         }
68 87
       }
69 88
       lsDive(path, dir);
70
-      //close done automatically by destructor of SdFile
89
+      // close() is done automatically by destructor of SdFile
71 90
     }
72 91
     else {
73 92
       char pn0 = p.name[0];
74 93
       if (pn0 == DIR_NAME_FREE) break;
75 94
       if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue;
76
-      char lf0 = longFilename[0];
77
-      if (lf0 == '.') continue;
95
+      if (longFilename[0] == '.') continue;
78 96
 
79 97
       if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
80 98
 
@@ -82,24 +100,27 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
82 100
 
83 101
       if (!filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue;
84 102
 
85
-      //if (cnt++ != nr) continue;
86
-      createFilename(filename, p);
87
-      if (lsAction == LS_SerialPrint) {
88
-        SERIAL_PROTOCOL(prepend);
89
-        SERIAL_PROTOCOLLN(filename);
90
-      }
91
-      else if (lsAction == LS_Count) {
92
-        nrFiles++;
93
-      }
94
-      else if (lsAction == LS_GetFilename) {
95
-        if (match != NULL) {
96
-          if (strcasecmp(match, filename) == 0) return;
97
-        }
98
-        else if (cnt == nrFiles) return;
99
-        cnt++;
103
+      switch (lsAction) {
104
+        case LS_Count:
105
+          nrFiles++;
106
+          break;
107
+        case LS_SerialPrint:
108
+          createFilename(filename, p);
109
+          SERIAL_PROTOCOL(prepend);
110
+          SERIAL_PROTOCOLLN(filename);
111
+          break;
112
+        case LS_GetFilename:
113
+          createFilename(filename, p);
114
+          if (match != NULL) {
115
+            if (strcasecmp(match, filename) == 0) return;
116
+          }
117
+          else if (cnt == nrFiles) return;
118
+          cnt++;
119
+          break;
100 120
       }
121
+
101 122
     }
102
-  }
123
+  } // while readDir
103 124
 }
104 125
 
105 126
 void CardReader::ls()  {

Loading…
Cancel
Save