mirror of
https://github.com/eried/portapack-mayhem.git
synced 2025-02-25 09:01:12 -05:00
File: Make path a first-class object, add some methods from C++17.
This commit is contained in:
parent
f80706cb34
commit
b87d1456a2
@ -139,18 +139,12 @@ static std::filesystem::path find_last_file_matching_pattern(const std::filesyst
|
|||||||
return last_match;
|
return last_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::filesystem::path remove_filename_extension(const std::filesystem::path& filename) {
|
static std::filesystem::path increment_filename_stem_ordinal(std::filesystem::path path) {
|
||||||
const auto extension_index = filename.find_last_of('.');
|
auto t = path.replace_extension().native();
|
||||||
return filename.substr(0, extension_index);
|
auto it = t.rbegin();
|
||||||
}
|
|
||||||
|
|
||||||
static std::filesystem::path increment_filename_stem_ordinal(const std::filesystem::path& filename_stem) {
|
|
||||||
std::filesystem::path result { filename_stem };
|
|
||||||
|
|
||||||
auto it = result.rbegin();
|
|
||||||
|
|
||||||
// Increment decimal number before the extension.
|
// Increment decimal number before the extension.
|
||||||
for(; it != result.rend(); ++it) {
|
for(; it != t.rend(); ++it) {
|
||||||
const auto c = *it;
|
const auto c = *it;
|
||||||
if( c < '0' ) {
|
if( c < '0' ) {
|
||||||
return { };
|
return { };
|
||||||
@ -164,19 +158,18 @@ static std::filesystem::path increment_filename_stem_ordinal(const std::filesyst
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path next_filename_stem_matching_pattern(const std::filesystem::path& filename_stem_pattern) {
|
std::filesystem::path next_filename_stem_matching_pattern(std::filesystem::path filename_pattern) {
|
||||||
const auto filename = find_last_file_matching_pattern(filename_stem_pattern + u".*");
|
const auto next_filename = find_last_file_matching_pattern(filename_pattern.replace_extension(u".*"));
|
||||||
auto filename_stem = remove_filename_extension(filename);
|
if( next_filename.empty() ) {
|
||||||
if( filename_stem.empty() ) {
|
auto pattern_s = filename_pattern.replace_extension().native();
|
||||||
filename_stem = filename_stem_pattern;
|
std::replace(std::begin(pattern_s), std::end(pattern_s), '?', '0');
|
||||||
std::replace(std::begin(filename_stem), std::end(filename_stem), '?', '0');
|
return pattern_s;
|
||||||
} else {
|
} else {
|
||||||
filename_stem = increment_filename_stem_ordinal(filename_stem);
|
return increment_filename_stem_ordinal(next_filename);
|
||||||
}
|
}
|
||||||
return filename_stem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
@ -212,9 +205,54 @@ std::string filesystem_error::what() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string path_to_string(const path& p) {
|
path path::extension() const {
|
||||||
|
const auto t = filename().native();
|
||||||
|
const auto index = t.find_last_of(u'.');
|
||||||
|
if( index == t.npos ) {
|
||||||
|
return { };
|
||||||
|
} else {
|
||||||
|
return t.substr(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
path path::filename() const {
|
||||||
|
const auto index = _s.find_last_of(preferred_separator);
|
||||||
|
if( index == _s.npos ) {
|
||||||
|
return _s;
|
||||||
|
} else {
|
||||||
|
return _s.substr(index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
path path::stem() const {
|
||||||
|
const auto t = filename().native();
|
||||||
|
const auto index = t.find_last_of(u'.');
|
||||||
|
if( index == t.npos ) {
|
||||||
|
return t;
|
||||||
|
} else {
|
||||||
|
return t.substr(0, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string path::string() const {
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<path::value_type>, path::value_type> conv;
|
std::wstring_convert<std::codecvt_utf8_utf16<path::value_type>, path::value_type> conv;
|
||||||
return conv.to_bytes(p);
|
return conv.to_bytes(native());
|
||||||
|
}
|
||||||
|
|
||||||
|
path& path::replace_extension(const path& replacement) {
|
||||||
|
const auto t = extension().native();
|
||||||
|
_s.erase(_s.size() - t.size());
|
||||||
|
if( !replacement._s.empty() ) {
|
||||||
|
if( replacement._s.front() != u'.' ) {
|
||||||
|
_s += u'.';
|
||||||
|
}
|
||||||
|
_s += replacement._s;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>(const path& lhs, const path& rhs) {
|
||||||
|
return lhs.native() > rhs.native();
|
||||||
}
|
}
|
||||||
|
|
||||||
directory_iterator::directory_iterator(
|
directory_iterator::directory_iterator(
|
||||||
|
@ -64,14 +64,107 @@ private:
|
|||||||
uint32_t err;
|
uint32_t err;
|
||||||
};
|
};
|
||||||
|
|
||||||
using path = std::u16string;
|
struct path {
|
||||||
|
using string_type = std::u16string;
|
||||||
|
using value_type = string_type::value_type;
|
||||||
|
|
||||||
|
static constexpr value_type preferred_separator = u'/';
|
||||||
|
|
||||||
|
path(
|
||||||
|
) : _s { }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
path(
|
||||||
|
const path& p
|
||||||
|
) : _s { p._s }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
path(
|
||||||
|
path&& p
|
||||||
|
) : _s { std::move(p._s) }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Source>
|
||||||
|
path(
|
||||||
|
const Source& source
|
||||||
|
) : path { std::begin(source), std::end(source) }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class InputIt>
|
||||||
|
path(
|
||||||
|
InputIt first,
|
||||||
|
InputIt last
|
||||||
|
) : _s { first, last }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
path(
|
||||||
|
const char16_t* const s
|
||||||
|
) : _s { s }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
path(
|
||||||
|
const TCHAR* const s
|
||||||
|
) : _s { reinterpret_cast<const std::filesystem::path::value_type*>(s) }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
path& operator=(const path& p) {
|
||||||
|
_s = p._s;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
path& operator=(path&& p) {
|
||||||
|
_s = std::move(p._s);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
path extension() const;
|
||||||
|
path filename() const;
|
||||||
|
path stem() const;
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
return _s.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_type* c_str() const {
|
||||||
|
return native().c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const string_type& native() const {
|
||||||
|
return _s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string string() const;
|
||||||
|
|
||||||
|
path& operator+=(const path& p) {
|
||||||
|
_s += p._s;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
path& operator+=(const string_type& str) {
|
||||||
|
_s += str;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
path& replace_extension(const path& replacement = path());
|
||||||
|
|
||||||
|
private:
|
||||||
|
string_type _s;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator>(const path& lhs, const path& rhs);
|
||||||
|
|
||||||
using file_status = BYTE;
|
using file_status = BYTE;
|
||||||
|
|
||||||
static_assert(sizeof(path::value_type) == 2, "sizeof(std::filesystem::path::value_type) != 2");
|
static_assert(sizeof(path::value_type) == 2, "sizeof(std::filesystem::path::value_type) != 2");
|
||||||
static_assert(sizeof(path::value_type) == sizeof(TCHAR), "FatFs TCHAR size != std::filesystem::path::value_type");
|
static_assert(sizeof(path::value_type) == sizeof(TCHAR), "FatFs TCHAR size != std::filesystem::path::value_type");
|
||||||
|
|
||||||
std::string path_to_string(const path& p);
|
|
||||||
|
|
||||||
struct space_info {
|
struct space_info {
|
||||||
static_assert(sizeof(std::uintmax_t) >= 8, "std::uintmax_t too small (<uint64_t)");
|
static_assert(sizeof(std::uintmax_t) >= 8, "std::uintmax_t too small (<uint64_t)");
|
||||||
|
|
||||||
@ -85,7 +178,7 @@ struct directory_entry : public FILINFO {
|
|||||||
return fattrib;
|
return fattrib;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::filesystem::path path() const noexcept { return reinterpret_cast<const std::filesystem::path::value_type*>(fname); };
|
const std::filesystem::path path() const noexcept { return { fname }; };
|
||||||
};
|
};
|
||||||
|
|
||||||
class directory_iterator {
|
class directory_iterator {
|
||||||
@ -135,7 +228,7 @@ space_info space(const path& p);
|
|||||||
} /* namespace filesystem */
|
} /* namespace filesystem */
|
||||||
} /* namespace std */
|
} /* namespace std */
|
||||||
|
|
||||||
std::filesystem::path next_filename_stem_matching_pattern(const std::filesystem::path& filename_stem_pattern);
|
std::filesystem::path next_filename_stem_matching_pattern(std::filesystem::path filename_stem_pattern);
|
||||||
|
|
||||||
class File {
|
class File {
|
||||||
public:
|
public:
|
||||||
|
@ -81,13 +81,13 @@ void SystemStatusView::set_title(const std::string new_value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SystemStatusView::on_camera() {
|
void SystemStatusView::on_camera() {
|
||||||
const auto filename_stem = next_filename_stem_matching_pattern(u"SCR_????");
|
auto path = next_filename_stem_matching_pattern(u"SCR_????");
|
||||||
if( filename_stem.empty() ) {
|
if( path.empty() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PNGWriter png;
|
PNGWriter png;
|
||||||
auto create_error = png.create(filename_stem + u".PNG");
|
auto create_error = png.create(path.replace_extension(u".PNG"));
|
||||||
if( create_error.is_valid() ) {
|
if( create_error.is_valid() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -238,8 +238,8 @@ void RecordView::start() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto filename_stem = next_filename_stem_matching_pattern(filename_stem_pattern);
|
auto base_path = next_filename_stem_matching_pattern(filename_stem_pattern);
|
||||||
if( filename_stem.empty() ) {
|
if( base_path.empty() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,9 +250,7 @@ void RecordView::start() {
|
|||||||
auto p = std::make_unique<WAVFileWriter>(
|
auto p = std::make_unique<WAVFileWriter>(
|
||||||
sampling_rate
|
sampling_rate
|
||||||
);
|
);
|
||||||
auto create_error = p->create(
|
auto create_error = p->create(base_path.replace_extension(u".WAV"));
|
||||||
filename_stem + u".WAV"
|
|
||||||
);
|
|
||||||
if( create_error.is_valid() ) {
|
if( create_error.is_valid() ) {
|
||||||
handle_error(create_error.value());
|
handle_error(create_error.value());
|
||||||
} else {
|
} else {
|
||||||
@ -263,16 +261,14 @@ void RecordView::start() {
|
|||||||
|
|
||||||
case FileType::RawS16:
|
case FileType::RawS16:
|
||||||
{
|
{
|
||||||
const auto metadata_file_error = write_metadata_file(filename_stem + u".TXT");
|
const auto metadata_file_error = write_metadata_file(base_path.replace_extension(u".TXT"));
|
||||||
if( metadata_file_error.is_valid() ) {
|
if( metadata_file_error.is_valid() ) {
|
||||||
handle_error(metadata_file_error.value());
|
handle_error(metadata_file_error.value());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto p = std::make_unique<RawFileWriter>();
|
auto p = std::make_unique<RawFileWriter>();
|
||||||
auto create_error = p->create(
|
auto create_error = p->create(base_path.replace_extension(u".C16"));
|
||||||
filename_stem + u".C16"
|
|
||||||
);
|
|
||||||
if( create_error.is_valid() ) {
|
if( create_error.is_valid() ) {
|
||||||
handle_error(create_error.value());
|
handle_error(create_error.value());
|
||||||
} else {
|
} else {
|
||||||
@ -286,7 +282,7 @@ void RecordView::start() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if( writer ) {
|
if( writer ) {
|
||||||
text_record_filename.set(std::filesystem::path_to_string(filename_stem));
|
text_record_filename.set(base_path.replace_extension().string());
|
||||||
button_record.set_bitmap(&bitmap_stop);
|
button_record.set_bitmap(&bitmap_stop);
|
||||||
capture_thread = std::make_unique<CaptureThread>(
|
capture_thread = std::make_unique<CaptureThread>(
|
||||||
std::move(writer),
|
std::move(writer),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user