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.
This commit is contained in:
Andreas Kling 2019-07-15 06:49:28 +02:00
parent cd497accbe
commit 954a0b8efe
Notes: sideshowbarker 2024-07-19 13:15:54 +09:00
7 changed files with 33 additions and 25 deletions

View File

@ -8,14 +8,14 @@ namespace AK {
FileSystemPath::FileSystemPath(const StringView& s) FileSystemPath::FileSystemPath(const StringView& s)
: m_string(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" auto parts = m_string.split_view('/');
(void)resolve_symbolic_links; int approximate_canonical_length = 0;
auto parts = m_string.split('/');
Vector<String> canonical_parts; Vector<String> canonical_parts;
for (auto& part : parts) { for (auto& part : parts) {
@ -26,23 +26,24 @@ bool FileSystemPath::canonicalize(bool resolve_symbolic_links)
canonical_parts.take_last(); canonical_parts.take_last();
continue; continue;
} }
if (!part.is_empty()) if (!part.is_empty()) {
approximate_canonical_length += part.length() + 1;
canonical_parts.append(part); canonical_parts.append(part);
}
} }
if (canonical_parts.is_empty()) { if (canonical_parts.is_empty()) {
m_string = m_basename = "/"; m_string = m_basename = "/";
return true; return;
} }
m_basename = canonical_parts.last(); m_basename = canonical_parts.last();
StringBuilder builder; StringBuilder builder(approximate_canonical_length);
for (auto& cpart : canonical_parts) { for (auto& cpart : canonical_parts) {
builder.append('/'); builder.append('/');
builder.append(cpart); builder.append(cpart);
} }
m_parts = move(canonical_parts); m_parts = move(canonical_parts);
m_string = builder.to_string(); m_string = builder.to_string();
return true;
} }
bool FileSystemPath::has_extension(StringView extension) const 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()); return m_string.to_lowercase().ends_with(extension_string.to_lowercase());
} }
String canonicalized_path(const StringView& path)
{
return FileSystemPath(path).string();
}
} }

View File

@ -19,7 +19,7 @@ public:
bool has_extension(StringView) const; bool has_extension(StringView) const;
private: private:
bool canonicalize(bool resolve_symbolic_links = false); void canonicalize();
Vector<String> m_parts; Vector<String> m_parts;
String m_string; String m_string;
@ -27,6 +27,9 @@ private:
bool m_is_valid { false }; bool m_is_valid { false };
}; };
String canonicalized_path(const StringView&);
}; };
using AK::FileSystemPath; using AK::FileSystemPath;
using AK::canonicalized_path;

View File

@ -10,14 +10,14 @@ void DirectoryView::handle_activation(const GModelIndex& index)
return; return;
dbgprintf("on activation: %d,%d, this=%p, m_model=%p\n", index.row(), index.column(), this, m_model.ptr()); 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()); 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()) { if (entry.is_directory()) {
open(path.string()); open(path);
return; return;
} }
if (entry.is_executable()) { if (entry.is_executable()) {
if (fork() == 0) { if (fork() == 0) {
int rc = execl(path.string().characters(), path.string().characters(), nullptr); int rc = execl(path.characters(), path.characters(), nullptr);
if (rc < 0) if (rc < 0)
perror("exec"); perror("exec");
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
@ -25,9 +25,9 @@ void DirectoryView::handle_activation(const GModelIndex& index)
return; return;
} }
if (path.string().to_lowercase().ends_with(".png")) { if (path.to_lowercase().ends_with(".png")) {
if (fork() == 0) { 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) if (rc < 0)
perror("exec"); perror("exec");
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
@ -36,7 +36,7 @@ void DirectoryView::handle_activation(const GModelIndex& index)
} }
if (fork() == 0) { 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) if (rc < 0)
perror("exec"); perror("exec");
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();

View File

@ -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&) { 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); GInputBox input_box("Enter name:", "New directory", window);
if (input_box.exec() == GInputBox::ExecOK && !input_box.text_value().is_empty()) { if (input_box.exec() == GInputBox::ExecOK && !input_box.text_value().is_empty()) {
auto new_dir_path = FileSystemPath(String::format("%s/%s", auto new_dir_path = canonicalized_path(
directory_view->path().characters(), String::format("%s/%s",
input_box.text_value().characters())) directory_view->path().characters(),
.string(); input_box.text_value().characters()));
int rc = mkdir(new_dir_path.characters(), 0777); int rc = mkdir(new_dir_path.characters(), 0777);
if (rc < 0) { if (rc < 0) {
GMessageBox::show(String::format("mkdir(\"%s\") failed: %s", new_dir_path.characters(), strerror(errno)), "Error", GMessageBox::Type::Error, window); GMessageBox::show(String::format("mkdir(\"%s\") failed: %s", new_dir_path.characters(), strerror(errno)), "Error", GMessageBox::Type::Error, window);

View File

@ -301,8 +301,7 @@ void GDirectoryModel::update()
void GDirectoryModel::open(const StringView& a_path) void GDirectoryModel::open(const StringView& a_path)
{ {
FileSystemPath canonical_path(a_path); auto path = canonicalized_path(a_path);
auto path = canonical_path.string();
if (m_path == path) if (m_path == path)
return; return;
DIR* dirp = opendir(path.characters()); DIR* dirp = opendir(path.characters());

View File

@ -92,7 +92,7 @@ struct GFileSystemModel::Node {
} }
builder.append('/'); builder.append('/');
builder.append(name); 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) 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_mode(mode)
{ {
m_open_folder_icon = GIcon::default_icon("filetype-folder-open"); m_open_folder_icon = GIcon::default_icon("filetype-folder-open");

View File

@ -108,7 +108,7 @@ RefPtr<GraphicsBitmap> load_png(const StringView& path)
return nullptr; return nullptr;
auto bitmap = load_png_impl((const u8*)mapped_file.pointer(), mapped_file.size()); auto bitmap = load_png_impl((const u8*)mapped_file.pointer(), mapped_file.size());
if (bitmap) 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; return bitmap;
} }