#include "app_core/document_route.h" #include #include namespace pp::app { namespace { [[nodiscard]] bool is_extension_char(char value) noexcept { const auto ch = static_cast(value); return std::isalnum(ch) != 0 || value == '_'; } [[nodiscard]] std::string lowercase_ascii(std::string_view value) { std::string lowered; lowered.reserve(value.size()); for (const char ch : value) { lowered.push_back(static_cast(std::tolower(static_cast(ch)))); } return lowered; } } pp::foundation::Result classify_document_open_path(std::string_view path) { const auto separator = path.find_last_of("/\\"); if (separator == std::string_view::npos || separator + 1U >= path.size()) { return pp::foundation::Result::failure( pp::foundation::Status::invalid_argument("document path must include a directory and file name")); } const auto dot = path.find_last_of('.'); if (dot == std::string_view::npos || dot <= separator + 1U || dot + 1U >= path.size()) { return pp::foundation::Result::failure( pp::foundation::Status::invalid_argument("document path must include a file extension")); } const std::string_view extension = path.substr(dot + 1U); for (const char ch : extension) { if (!is_extension_char(ch)) { return pp::foundation::Result::failure( pp::foundation::Status::invalid_argument("document extension contains unsupported characters")); } } auto lowered_extension = lowercase_ascii(extension); auto kind = DocumentOpenKind::open_project; if (lowered_extension == "abr") { kind = DocumentOpenKind::import_abr; } else if (lowered_extension == "ppbr") { kind = DocumentOpenKind::import_ppbr; } return pp::foundation::Result::success( DocumentOpenRoute { .kind = kind, .path = std::string(path), .directory = std::string(path.substr(0U, separator)), .name = std::string(path.substr(separator + 1U, dot - separator - 1U)), .extension = std::move(lowered_extension), }); } }