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