diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 207e3dc1..e96feaa2 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -7,6 +7,7 @@ target_sources( systemnotification.h configshortcuts.h request.h + strfparse.h ) target_sources( @@ -24,5 +25,6 @@ target_sources( colorutils.cpp history.cpp configshortcuts.cpp + strfparse.cpp request.cpp ) diff --git a/src/utils/filenamehandler.cpp b/src/utils/filenamehandler.cpp index 023679ff..e629e063 100644 --- a/src/utils/filenamehandler.cpp +++ b/src/utils/filenamehandler.cpp @@ -3,6 +3,7 @@ #include "filenamehandler.h" #include "src/utils/confighandler.h" +#include "src/utils/strfparse.h" #include #include #include @@ -41,13 +42,9 @@ QString FileNameHandler::parseFilename(const QString& name) while (res.endsWith('%')) { res.chop(1); } - std::time_t t = std::time(NULL); - char* tempData = QStringToCharArr(res); - char data[MAX_CHARACTERS] = { 0 }; - std::strftime(data, sizeof(data), tempData, std::localtime(&t)); - res = QString::fromLocal8Bit(data, (int)strlen(data)); - free(tempData); + res = + QString::fromStdString(strfparse::format_time_string(name.toStdString())); // add the parsed pattern in a correct format for the filesystem res = res.replace(QLatin1String("/"), QStringLiteral("⁄")) diff --git a/src/utils/strfparse.cpp b/src/utils/strfparse.cpp new file mode 100644 index 00000000..0274b82b --- /dev/null +++ b/src/utils/strfparse.cpp @@ -0,0 +1,105 @@ +#include "strfparse.h" + +namespace strfparse { +std::vector split(std::string const& s, char delimiter) +{ + std::vector tokens; + std::string token; + std::istringstream tokenStream(s); + while (std::getline(tokenStream, token, delimiter)) { + tokens.push_back(token); + } + return tokens; +} + +std::vector create_specifier_list() +{ + + std::vector allowed_specifier{ 'Y', 'H', 'a', 'A', 'b', 'B', 'c', 'C', + 'd', 'D', 'e', 'F', 'g', 'G', 'h', 'H', + 'I', 'j', 'm', 'M', 'n', 'p', 'r', 'R', + 'S', 't', 'T', 'u', 'U', 'V', 'w', 'W', + 'x', 'X', 'y', 'Y', 'z', 'Z' }; + return allowed_specifier; +} + +std::string replace_all(std::string input, + std::string const& to_find, + std::string const& to_replace) +{ + size_t pos = 0; + while ((pos = input.find(to_find, pos)) != std::string::npos) { + input.replace(pos, to_find.length(), to_replace); + pos += to_replace.length(); + } + + return input; +} + +std::vector match_specifiers(std::string const& specifier, + std::vector allowed_specifier) +{ + + std::vector spec_list; + + for (uint i = 0; i < specifier.size() - 1; i++) { + if (specifier[i] == '%') { + spec_list.push_back(specifier[i + 1]); + } + } + + std::sort(spec_list.begin(), spec_list.end()); + std::sort(allowed_specifier.begin(), allowed_specifier.end()); + + std::vector overlap; + std::set_intersection(spec_list.begin(), + spec_list.end(), + allowed_specifier.begin(), + allowed_specifier.end(), + back_inserter(overlap)); + + return overlap; +} + +std::string format_time_string(std::string const& specifier) +{ + + if (specifier.empty()) { + return ""; + } + + std::time_t t = std::time(nullptr); + char buff[100]; + + auto allowed_specifier = create_specifier_list(); + + auto overlap = match_specifiers(specifier, allowed_specifier); + + // Create "Safe" string for strftime which is the specfiers delimited by * + std::string lookup_string; + for (auto const& e : overlap) { + lookup_string.push_back('%'); + lookup_string.push_back(e); + lookup_string.push_back('*'); + } + + std::strftime( + buff, sizeof(buff), lookup_string.c_str(), std::localtime(&t)); + + std::map lookup_table; + auto result = split(buff, '*'); + + for (size_t i = 0; i < result.size(); i++) { + lookup_table.emplace(std::make_pair(overlap[i], result[i])); + } + + // Sub into original string + std::string delim = "%"; + auto output_string = specifier; + for (auto const& row : lookup_table) { + auto to_find = delim + row.first; + output_string = replace_all(output_string, to_find, row.second); + } + return output_string; +} +} diff --git a/src/utils/strfparse.h b/src/utils/strfparse.h new file mode 100644 index 00000000..b4228b89 --- /dev/null +++ b/src/utils/strfparse.h @@ -0,0 +1,20 @@ +#include +#include +#include +#include +#include + +namespace strfparse { +std::vector split(std::string const& s, char delimiter); + +std::vector create_specifier_list(); + +std::string replace_all(std::string input, + std::string const& to_find, + std::string const& to_replace); + +std::vector match_specifiers(std::string const& specifier, + std::vector allowed_specifier); + +std::string format_time_string(std::string const& specifier); +}