parent
30aaefca64
commit
28cf749951
@ -1,72 +0,0 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#include "database/file_gatherer.hpp" |
||||
|
||||
#include <deque> |
||||
#include <functional> |
||||
#include <sstream> |
||||
#include <string> |
||||
|
||||
#include "ff.h" |
||||
|
||||
#include "drivers/spi.hpp" |
||||
#include "memory_resource.hpp" |
||||
|
||||
namespace database { |
||||
|
||||
static_assert(sizeof(TCHAR) == sizeof(char), "TCHAR must be CHAR"); |
||||
|
||||
auto FileGathererImpl::FindFiles( |
||||
const std::string& root, |
||||
std::function<void(std::string_view, const FILINFO&)> cb) -> void { |
||||
std::pmr::deque<std::pmr::string> to_explore{&memory::kSpiRamResource}; |
||||
to_explore.push_back({root.data(), root.size()}); |
||||
|
||||
while (!to_explore.empty()) { |
||||
auto next_path_str = to_explore.front(); |
||||
to_explore.pop_front(); |
||||
|
||||
const TCHAR* next_path = static_cast<const TCHAR*>(next_path_str.c_str()); |
||||
|
||||
FF_DIR dir; |
||||
FRESULT res = f_opendir(&dir, next_path); |
||||
if (res != FR_OK) { |
||||
// TODO: log.
|
||||
continue; |
||||
} |
||||
|
||||
for (;;) { |
||||
FILINFO info; |
||||
res = f_readdir(&dir, &info); |
||||
if (res != FR_OK || info.fname[0] == 0) { |
||||
// No more files in the directory.
|
||||
break; |
||||
} else if (info.fattrib & (AM_HID | AM_SYS) || info.fname[0] == '.') { |
||||
// System or hidden file. Ignore it and move on.
|
||||
continue; |
||||
} else { |
||||
std::pmr::string full_path{&memory::kSpiRamResource}; |
||||
full_path += next_path_str; |
||||
full_path += "/"; |
||||
full_path += info.fname; |
||||
|
||||
if (info.fattrib & AM_DIR) { |
||||
// This is a directory. Add it to the explore queue.
|
||||
to_explore.push_back(full_path); |
||||
} else { |
||||
// This is a file! Let the callback know about it.
|
||||
// std::invoke(cb, full_path.str(), info);
|
||||
std::invoke(cb, full_path, info); |
||||
} |
||||
} |
||||
} |
||||
|
||||
f_closedir(&dir); |
||||
} |
||||
} |
||||
|
||||
} // namespace database
|
@ -1,34 +0,0 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <deque> |
||||
#include <functional> |
||||
#include <sstream> |
||||
#include <string> |
||||
|
||||
#include "ff.h" |
||||
|
||||
namespace database { |
||||
|
||||
class IFileGatherer { |
||||
public: |
||||
virtual ~IFileGatherer() {}; |
||||
|
||||
virtual auto FindFiles( |
||||
const std::string& root, |
||||
std::function<void(std::string_view, const FILINFO&)> cb) -> void = 0; |
||||
}; |
||||
|
||||
class FileGathererImpl : public IFileGatherer { |
||||
public: |
||||
virtual auto FindFiles(const std::string& root, |
||||
std::function<void(std::string_view, const FILINFO&)> |
||||
cb) -> void override; |
||||
}; |
||||
|
||||
} // namespace database
|
@ -0,0 +1,84 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#include "database/track_finder.hpp" |
||||
|
||||
#include <deque> |
||||
#include <functional> |
||||
#include <memory> |
||||
#include <mutex> |
||||
#include <sstream> |
||||
#include <string> |
||||
#include <string_view> |
||||
|
||||
#include "database/track_finder.hpp" |
||||
#include "ff.h" |
||||
|
||||
#include "drivers/spi.hpp" |
||||
#include "memory_resource.hpp" |
||||
|
||||
namespace database { |
||||
|
||||
static_assert(sizeof(TCHAR) == sizeof(char), "TCHAR must be CHAR"); |
||||
|
||||
TrackFinder::TrackFinder(std::string_view root) |
||||
: to_explore_(&memory::kSpiRamResource) { |
||||
to_explore_.push_back({root.data(), root.size()}); |
||||
} |
||||
|
||||
auto TrackFinder::next(FILINFO& out_info) -> std::optional<std::string> { |
||||
std::scoped_lock<std::mutex> lock{mut_}; |
||||
while (!to_explore_.empty() || current_) { |
||||
if (!current_) { |
||||
current_.emplace(); |
||||
|
||||
// Get the next directory to iterate through.
|
||||
current_->first = to_explore_.front(); |
||||
to_explore_.pop_front(); |
||||
const TCHAR* next_path = |
||||
static_cast<const TCHAR*>(current_->first.data()); |
||||
|
||||
// Open it for iterating.
|
||||
FRESULT res = f_opendir(¤t_->second, next_path); |
||||
if (res != FR_OK) { |
||||
current_.reset(); |
||||
continue; |
||||
} |
||||
} |
||||
|
||||
FILINFO info; |
||||
FRESULT res = f_readdir(¤t_->second, &info); |
||||
if (res != FR_OK || info.fname[0] == 0) { |
||||
// No more files in the directory.
|
||||
f_closedir(¤t_->second); |
||||
current_.reset(); |
||||
continue; |
||||
} else if (info.fattrib & (AM_HID | AM_SYS) || info.fname[0] == '.') { |
||||
// System or hidden file. Ignore it and move on.
|
||||
continue; |
||||
} else { |
||||
// A valid file or folder.
|
||||
std::pmr::string full_path{&memory::kSpiRamResource}; |
||||
full_path += current_->first; |
||||
full_path += "/"; |
||||
full_path += info.fname; |
||||
|
||||
if (info.fattrib & AM_DIR) { |
||||
// This is a directory. Add it to the explore queue.
|
||||
to_explore_.push_back(full_path); |
||||
} else { |
||||
// This is a file! We can return now.
|
||||
out_info = info; |
||||
return {{full_path.data(), full_path.size()}}; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Out of things to explore.
|
||||
return {}; |
||||
} |
||||
|
||||
} // namespace database
|
@ -0,0 +1,33 @@ |
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||
* |
||||
* SPDX-License-Identifier: GPL-3.0-only |
||||
*/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <deque> |
||||
#include <functional> |
||||
#include <memory> |
||||
#include <mutex> |
||||
#include <optional> |
||||
#include <sstream> |
||||
#include <string> |
||||
|
||||
#include "ff.h" |
||||
|
||||
namespace database { |
||||
|
||||
class TrackFinder { |
||||
public: |
||||
TrackFinder(std::string_view root); |
||||
|
||||
auto next(FILINFO&) -> std::optional<std::string>; |
||||
|
||||
private: |
||||
std::mutex mut_; |
||||
std::pmr::deque<std::pmr::string> to_explore_; |
||||
std::optional<std::pair<std::pmr::string, FF_DIR>> current_; |
||||
}; |
||||
|
||||
} // namespace database
|
Loading…
Reference in new issue