From 954a0b8efec4c08168ba7eb9d5c9e5e694297be1 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 15 Jul 2019 06:49:28 +0200 Subject: [PATCH] AK: Add a canonicalized_path() convenience function. This is the same as calling FileSystemPath(foo).string(). The majority of clients only care about canonicalizing a path, so let's have an easy way to express that. --- AK/FileSystemPath.cpp | 24 ++++++++++++++-------- AK/FileSystemPath.h | 5 ++++- Applications/FileManager/DirectoryView.cpp | 12 +++++------ Applications/FileManager/main.cpp | 8 ++++---- Libraries/LibGUI/GDirectoryModel.cpp | 3 +-- Libraries/LibGUI/GFileSystemModel.cpp | 4 ++-- SharedGraphics/PNGLoader.cpp | 2 +- 7 files changed, 33 insertions(+), 25 deletions(-) diff --git a/AK/FileSystemPath.cpp b/AK/FileSystemPath.cpp index fbef784160..51a72302ad 100644 --- a/AK/FileSystemPath.cpp +++ b/AK/FileSystemPath.cpp @@ -8,14 +8,14 @@ namespace AK { FileSystemPath::FileSystemPath(const StringView& s) : m_string(s) { - m_is_valid = canonicalize(); + canonicalize(); + m_is_valid = true; } -bool FileSystemPath::canonicalize(bool resolve_symbolic_links) +void FileSystemPath::canonicalize() { - // FIXME: Implement "resolve_symbolic_links" - (void)resolve_symbolic_links; - auto parts = m_string.split('/'); + auto parts = m_string.split_view('/'); + int approximate_canonical_length = 0; Vector canonical_parts; for (auto& part : parts) { @@ -26,23 +26,24 @@ bool FileSystemPath::canonicalize(bool resolve_symbolic_links) canonical_parts.take_last(); continue; } - if (!part.is_empty()) + if (!part.is_empty()) { + approximate_canonical_length += part.length() + 1; canonical_parts.append(part); + } } if (canonical_parts.is_empty()) { m_string = m_basename = "/"; - return true; + return; } m_basename = canonical_parts.last(); - StringBuilder builder; + StringBuilder builder(approximate_canonical_length); for (auto& cpart : canonical_parts) { builder.append('/'); builder.append(cpart); } m_parts = move(canonical_parts); m_string = builder.to_string(); - return true; } bool FileSystemPath::has_extension(StringView extension) const @@ -52,4 +53,9 @@ bool FileSystemPath::has_extension(StringView extension) const return m_string.to_lowercase().ends_with(extension_string.to_lowercase()); } +String canonicalized_path(const StringView& path) +{ + return FileSystemPath(path).string(); +} + } diff --git a/AK/FileSystemPath.h b/AK/FileSystemPath.h index 4e09386ed7..4e6952d52e 100644 --- a/AK/FileSystemPath.h +++ b/AK/FileSystemPath.h @@ -19,7 +19,7 @@ public: bool has_extension(StringView) const; private: - bool canonicalize(bool resolve_symbolic_links = false); + void canonicalize(); Vector m_parts; String m_string; @@ -27,6 +27,9 @@ private: bool m_is_valid { false }; }; +String canonicalized_path(const StringView&); + }; using AK::FileSystemPath; +using AK::canonicalized_path; diff --git a/Applications/FileManager/DirectoryView.cpp b/Applications/FileManager/DirectoryView.cpp index e5f020d23d..e4156adc3c 100644 --- a/Applications/FileManager/DirectoryView.cpp +++ b/Applications/FileManager/DirectoryView.cpp @@ -10,14 +10,14 @@ void DirectoryView::handle_activation(const GModelIndex& index) return; dbgprintf("on activation: %d,%d, this=%p, m_model=%p\n", index.row(), index.column(), this, m_model.ptr()); auto& entry = model().entry(index.row()); - FileSystemPath path(String::format("%s/%s", model().path().characters(), entry.name.characters())); + auto path = canonicalized_path(String::format("%s/%s", model().path().characters(), entry.name.characters())); if (entry.is_directory()) { - open(path.string()); + open(path); return; } if (entry.is_executable()) { if (fork() == 0) { - int rc = execl(path.string().characters(), path.string().characters(), nullptr); + int rc = execl(path.characters(), path.characters(), nullptr); if (rc < 0) perror("exec"); ASSERT_NOT_REACHED(); @@ -25,9 +25,9 @@ void DirectoryView::handle_activation(const GModelIndex& index) return; } - if (path.string().to_lowercase().ends_with(".png")) { + if (path.to_lowercase().ends_with(".png")) { if (fork() == 0) { - int rc = execl("/bin/qs", "/bin/qs", path.string().characters(), nullptr); + int rc = execl("/bin/qs", "/bin/qs", path.characters(), nullptr); if (rc < 0) perror("exec"); ASSERT_NOT_REACHED(); @@ -36,7 +36,7 @@ void DirectoryView::handle_activation(const GModelIndex& index) } if (fork() == 0) { - int rc = execl("/bin/TextEditor", "/bin/TextEditor", path.string().characters(), nullptr); + int rc = execl("/bin/TextEditor", "/bin/TextEditor", path.characters(), nullptr); if (rc < 0) perror("exec"); ASSERT_NOT_REACHED(); diff --git a/Applications/FileManager/main.cpp b/Applications/FileManager/main.cpp index e183fa09d8..321c4f79dd 100644 --- a/Applications/FileManager/main.cpp +++ b/Applications/FileManager/main.cpp @@ -91,10 +91,10 @@ int main(int argc, char** argv) auto mkdir_action = GAction::create("New directory...", GraphicsBitmap::load_from_file("/res/icons/16x16/mkdir.png"), [&](const GAction&) { GInputBox input_box("Enter name:", "New directory", window); if (input_box.exec() == GInputBox::ExecOK && !input_box.text_value().is_empty()) { - auto new_dir_path = FileSystemPath(String::format("%s/%s", - directory_view->path().characters(), - input_box.text_value().characters())) - .string(); + auto new_dir_path = canonicalized_path( + String::format("%s/%s", + directory_view->path().characters(), + input_box.text_value().characters())); int rc = mkdir(new_dir_path.characters(), 0777); if (rc < 0) { GMessageBox::show(String::format("mkdir(\"%s\") failed: %s", new_dir_path.characters(), strerror(errno)), "Error", GMessageBox::Type::Error, window); diff --git a/Libraries/LibGUI/GDirectoryModel.cpp b/Libraries/LibGUI/GDirectoryModel.cpp index 7d11c021f5..c8ad8f40d0 100644 --- a/Libraries/LibGUI/GDirectoryModel.cpp +++ b/Libraries/LibGUI/GDirectoryModel.cpp @@ -301,8 +301,7 @@ void GDirectoryModel::update() void GDirectoryModel::open(const StringView& a_path) { - FileSystemPath canonical_path(a_path); - auto path = canonical_path.string(); + auto path = canonicalized_path(a_path); if (m_path == path) return; DIR* dirp = opendir(path.characters()); diff --git a/Libraries/LibGUI/GFileSystemModel.cpp b/Libraries/LibGUI/GFileSystemModel.cpp index 58780c08b8..0f1112cc1a 100644 --- a/Libraries/LibGUI/GFileSystemModel.cpp +++ b/Libraries/LibGUI/GFileSystemModel.cpp @@ -92,7 +92,7 @@ struct GFileSystemModel::Node { } builder.append('/'); builder.append(name); - return FileSystemPath(builder.to_string()).string(); + return canonicalized_path(builder.to_string()); } }; @@ -130,7 +130,7 @@ String GFileSystemModel::path(const GModelIndex& index) const } GFileSystemModel::GFileSystemModel(const StringView& root_path, Mode mode) - : m_root_path(FileSystemPath(root_path).string()) + : m_root_path(canonicalized_path(root_path)) , m_mode(mode) { m_open_folder_icon = GIcon::default_icon("filetype-folder-open"); diff --git a/SharedGraphics/PNGLoader.cpp b/SharedGraphics/PNGLoader.cpp index 08e02e1d00..b6fecfb890 100644 --- a/SharedGraphics/PNGLoader.cpp +++ b/SharedGraphics/PNGLoader.cpp @@ -108,7 +108,7 @@ RefPtr load_png(const StringView& path) return nullptr; auto bitmap = load_png_impl((const u8*)mapped_file.pointer(), mapped_file.size()); if (bitmap) - bitmap->set_mmap_name(String::format("GraphicsBitmap [%dx%d] - Decoded PNG: %s", bitmap->width(), bitmap->height(), FileSystemPath(path).string().characters())); + bitmap->set_mmap_name(String::format("GraphicsBitmap [%dx%d] - Decoded PNG: %s", bitmap->width(), bitmap->height(), canonicalized_path(path).characters())); return bitmap; }