#ifndef DIRECTORY_WALKER_H #define DIRECTORY_WALKER_H #include #include #include "DirectoryNode.h" struct WalkerState { const DirectoryNode* node; uint8_t phase; // 0: Start, 1: Files, 2: Subdirs, 3: End size_t idx; // Index for vectors WalkerState(const DirectoryNode* n) : node(n), phase(0), idx(0) {} }; class DirectoryWalker { private: std::vector stack; String pending; size_t pendingOffset; void generateNext() { if (stack.empty()) return; WalkerState& state = stack.back(); const DirectoryNode* node = state.node; switch (state.phase) { case 0: // Start if (node->getName() == "/") { pending += F("
    \r\n"); } else { pending += F("
  • getId()); pending += F("\">"); pending += node->getName(); pending += F("
  • \r\n"); } state.phase = 1; state.idx = 0; break; case 1: // Files if (state.idx < node->getMP3Files().size()) { pending += F("
  • getFileIdAt(state.idx)); pending += F("\">"); pending += node->getMP3Files()[state.idx]; pending += F("
  • \r\n"); state.idx++; } else { state.phase = 2; state.idx = 0; } break; case 2: // Subdirs if (state.idx < node->getSubdirectories().size()) { // Push child const DirectoryNode* child = node->getSubdirectories()[state.idx]; state.idx++; // Advance index for when we return stack.emplace_back(child); // Next loop will process the child (Phase 0) } else { state.phase = 3; } break; case 3: // End if (node->getName() == "/") { pending += F("
\r\n"); } stack.pop_back(); break; } } public: DirectoryWalker(const DirectoryNode* root) : pendingOffset(0) { if (root) { stack.emplace_back(root); // Reserve some space for pending string to avoid frequent reallocations pending.reserve(256); } } size_t read(uint8_t* buffer, size_t maxLen) { size_t written = 0; while (written < maxLen) { // If pending buffer is empty or fully consumed, generate more if (pending.length() == 0 || pendingOffset >= pending.length()) { pending = ""; // Reset string content (capacity is kept) pendingOffset = 0; if (stack.empty()) { break; // Done } generateNext(); } // Copy from pending to output buffer if (pending.length() > pendingOffset) { size_t available = pending.length() - pendingOffset; size_t toCopy = std::min(available, maxLen - written); memcpy(buffer + written, pending.c_str() + pendingOffset, toCopy); written += toCopy; pendingOffset += toCopy; } } return written; } }; #endif