From 749298414466108ffee212e1688d4c9a2d704406 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 20 Apr 2016 09:56:35 -0700 Subject: [PATCH] Add filesystem directory enumeration. Borrow API from std::filesystem -- Boost and C++17. --- firmware/application/file.cpp | 30 ++++++++++++++++++ firmware/application/file.hpp | 59 +++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/firmware/application/file.cpp b/firmware/application/file.cpp index a14325e0..1458f12d 100644 --- a/firmware/application/file.cpp +++ b/firmware/application/file.cpp @@ -78,3 +78,33 @@ bool File::sync() { const auto result = f_sync(&f); return (result == FR_OK); } + +namespace std { +namespace filesystem { + +directory_iterator::directory_iterator( + const char* path, + const char* wild +) { + impl = std::make_shared(); + const auto result = f_findfirst(&impl->dir, &impl->filinfo, path, wild); + if( result != FR_OK ) { + impl.reset(); + // TODO: Throw exception if/when I enable exceptions... + } +} + +directory_iterator& directory_iterator::operator++() { + const auto result = f_findnext(&impl->dir, &impl->filinfo); + if( (result != FR_OK) || (impl->filinfo.fname[0] == 0) ) { + impl.reset(); + } + return *this; +} + +bool is_regular_file(const file_status s) { + return !(s & AM_DIR); +} + +} /* namespace filesystem */ +} /* namespace std */ diff --git a/firmware/application/file.hpp b/firmware/application/file.hpp index 5a4524cf..ed13a06e 100644 --- a/firmware/application/file.hpp +++ b/firmware/application/file.hpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include class File { public: @@ -55,4 +57,61 @@ private: FIL f; }; +namespace std { +namespace filesystem { + +using file_status = BYTE; + +struct directory_entry : public FILINFO { + file_status status() const { + return fattrib; + } + + const std::string path() const noexcept { return fname; }; +}; + +class directory_iterator { + struct Impl { + DIR dir; + directory_entry filinfo; + + ~Impl() { + f_closedir(&dir); + } + }; + + std::shared_ptr impl; + + friend bool operator!=(const directory_iterator& lhs, const directory_iterator& rhs); + +public: + using difference_type = std::ptrdiff_t; + using value_type = directory_entry; + using pointer = const directory_entry*; + using reference = const directory_entry&; + using iterator_category = std::input_iterator_tag; + + directory_iterator() noexcept { }; + directory_iterator(const char* path, const char* wild); + + ~directory_iterator() { } + + directory_iterator& operator++(); + + reference operator*() const { + // TODO: Exception or assert if impl == nullptr. + return impl->filinfo; + } +}; + +inline const directory_iterator& begin(const directory_iterator& iter) noexcept { return iter; }; +inline directory_iterator end(const directory_iterator&) noexcept { return { }; }; + +inline bool operator!=(const directory_iterator& lhs, const directory_iterator& rhs) { return lhs.impl != rhs.impl; }; + +bool is_regular_file(const file_status s); + +} /* namespace filesystem */ +} /* namespace std */ + #endif/*__FILE_H__*/