@@ -84,91 +84,108 @@ bool SD_TC::format() {
84
84
return sd.format ();
85
85
}
86
86
87
- void SD_TC::listFiles (void (*callWhenFull)(char *, bool ), byte tabulation) {
88
- // Only called on real device
87
+ bool SD_TC::iterateOnFiles (doOnFile functionName, void * userData) {
89
88
#ifndef MOCK_PINS_COUNT
90
- File* parent = &hierarchy[hierarchySize - 1 ];
91
- File current;
92
- char fileName[15 ];
93
- char buffer[300 ]; // Each line shouldn't be more than 30 characters long
94
- int linePos = 0 ;
95
- int filesWritten = 0 ; // When we hit 10 here we will call buffer and suspend
96
-
97
- while (filesWritten < 10 ) {
98
- if (current.openNext (parent, O_READ)) {
99
- if (!current.isHidden ()) {
100
- current.getName (fileName, sizeof (fileName));
101
- for (int i = 0 ; i < tabulation; i++) {
102
- buffer[i] = ' \t ' ;
103
- ++linePos;
104
- }
105
- if (current.isDir ()) {
106
- int bytesWritten = snprintf_P (buffer + linePos, sizeof (buffer) - linePos, (PGM_P)F (" %s/\n " ), fileName);
107
- // "Overwrite" null terminator
108
- linePos += bytesWritten;
109
- ++filesWritten;
110
- // Create a new array with bigger size
111
- File* newHierarchy = new File[hierarchySize + 1 ];
112
- memcpy (newHierarchy, hierarchy, sizeof (File) * hierarchySize);
113
- delete[] hierarchy;
114
- hierarchy = newHierarchy;
115
- ++hierarchySize;
116
- // Add the current file to the new array
117
- hierarchy[hierarchySize - 1 ] = current;
118
- // Now we change parent directory
119
- parent = &hierarchy[hierarchySize - 1 ];
89
+ // Only called on real device
90
+ // Returns false only when all files have been iterated on
91
+ bool flag = true ;
92
+ while (flag) {
93
+ if (fileStack[fileStackSize].openNext (&fileStack[fileStackSize - 1 ], O_READ)) {
94
+ if (!fileStack[fileStackSize].isHidden ()) {
95
+ flag = functionName (&fileStack[fileStackSize], userData);
96
+ if (fileStack[fileStackSize].isDir ()) {
97
+ // maxDepth was set to 2 in SD_TC.h
98
+ // So this code is untested
99
+ if (fileStackSize < maxDepth - 1 ) {
100
+ ++fileStackSize;
101
+ };
120
102
} else {
121
- int bytesWritten = snprintf_P (buffer + linePos, sizeof (buffer) - linePos, (PGM_P)F (" %s\t %6u bytes\n " ),
122
- fileName, current.fileSize ());
123
- // "Overwrite" null terminator
124
- linePos += bytesWritten;
125
- ++filesWritten;
126
- // Close current (if it's a file); close current (if it's a directory) as a parent later
127
- current.close ();
103
+ // Close current file; directories are closed later
104
+ fileStack[fileStackSize].close ();
128
105
}
129
106
}
130
107
} else {
131
- if (hierarchySize == 1 ) {
132
- // We're done listing root
133
- parent->close ();
134
- --hierarchySize;
135
- delete[] hierarchy;
136
- hierarchy = nullptr ;
137
- buffer[linePos] = ' \0 ' ;
138
- inProgress = false ;
139
- callWhenFull (buffer, true );
140
- return ;
108
+ // We're done with a directory
109
+ fileStack[--fileStackSize].close ();
110
+ if (fileStackSize == 0 ) {
111
+ return false ; // Done with root---there are no more files
141
112
}
142
- // All done with parent, remove directory from hierarchy
143
- parent->close ();
144
- --hierarchySize;
145
- parent = &hierarchy[hierarchySize - 1 ];
146
113
}
147
114
}
148
- // We have 10 lines written, so add null terminator
149
- buffer[linePos] = ' \0 ' ;
150
- callWhenFull (buffer, false );
115
+ return true ; // There are (probably) more files remaining
116
+ #else
117
+ return false ;
118
+ #endif
119
+ }
120
+
121
+ bool SD_TC::incrementFileCount (File* myFile, void * pFileCount) {
122
+ return ++(*(int *)pFileCount) % 10 != 0 ; // Pause after counting 10 files
123
+ }
124
+
125
+ void SD_TC::countFiles (void (*callWhenFinished)(int )) {
126
+ if (!inProgress) {
127
+ const char path[] PROGMEM = " /" ;
128
+ fileStack[0 ] = SD_TC::instance ()->open (path);
129
+ if (!fileStack[0 ]) {
130
+ serial (F (" SD_TC open() failed" ));
131
+ return ;
132
+ }
133
+ fileStack[0 ].rewind ();
134
+ fileStackSize = 1 ;
135
+ fileCount = 0 ;
136
+ inProgress = true ;
137
+ }
138
+ inProgress = iterateOnFiles (incrementFileCount, (void *)&fileCount);
139
+ if (!inProgress) {
140
+ callWhenFinished (fileCount);
141
+ }
142
+ }
143
+
144
+ // Issue: This function does not visually display depth for items in subfolders
145
+ // With maxDepth set to 2, no subfolders are traversed
146
+ bool SD_TC::listFile (File* myFile, void * userData) {
147
+ #ifndef MOCK_PINS_COUNT
148
+ listFilesData_t* pListFileData = static_cast <listFilesData_t*>(userData);
149
+ char fileName[15 ];
150
+ myFile->getName (fileName, sizeof (fileName));
151
+ int bytesWritten;
152
+ if (myFile->isDir ()) {
153
+ bytesWritten = snprintf_P (pListFileData->buffer + pListFileData->linePos ,
154
+ sizeof (pListFileData->buffer ) - pListFileData->linePos ,
155
+ (PGM_P)F (" %11.11s/ \r\n " ), fileName);
156
+ } else {
157
+ bytesWritten = snprintf_P (pListFileData->buffer + pListFileData->linePos ,
158
+ sizeof (pListFileData->buffer ) - pListFileData->linePos , (PGM_P)F (" %s\t %6u KB\r\n " ),
159
+ fileName, myFile->fileSize () / 1024 + 1 );
160
+ }
161
+ // "Overwrite" null terminator
162
+ pListFileData->linePos += bytesWritten;
163
+ return (++(pListFileData->filesWritten )) % 10 != 0 ; // Stop iterating after 10 files
164
+ #else
165
+ return false ;
151
166
#endif
152
167
}
153
168
154
169
void SD_TC::listRootToBuffer (void (*callWhenFull)(char *, bool )) {
155
170
#ifndef MOCK_PINS_COUNT
156
171
if (!inProgress) {
157
- // Initialize hierarchy
158
- hierarchy = new File;
159
- ++hierarchySize;
160
172
const char path[] PROGMEM = " /" ;
161
- File root = SD_TC::instance ()->open (path);
162
- if (!root ) {
173
+ fileStack[ 0 ] = SD_TC::instance ()->open (path);
174
+ if (!fileStack[ 0 ] ) {
163
175
serial (F (" SD_TC open() failed" ));
164
176
return ;
165
177
}
166
- // Add root to hierarchy if successful
167
- root.rewind ();
168
- hierarchy[0 ] = root;
178
+ fileStack[0 ].rewind ();
179
+ fileStackSize = 1 ;
169
180
inProgress = true ;
170
181
}
171
- listFiles (callWhenFull);
182
+ listFilesData_t listFileData;
183
+ listFileData.linePos = 0 ;
184
+ listFileData.filesWritten = 0 ;
185
+ inProgress = iterateOnFiles (listFile, (void *)&listFileData);
186
+ // Terminate the buffer
187
+ listFileData.buffer [listFileData.linePos ] = ' \0 ' ;
188
+ callWhenFull (listFileData.buffer , !inProgress);
172
189
#else
173
190
static const char notImplemented[] PROGMEM = " Root directory not supported by CI framework.\r\n " ;
174
191
char buffer[sizeof (notImplemented)];
0 commit comments