44#ifndef QUICK_LINT_JS_FILE_CANONICAL_H
55#define QUICK_LINT_JS_FILE_CANONICAL_H
66
7+ #include < cstddef>
8+ #include < functional>
9+ #include < optional>
710#include < string>
11+ #include < string_view>
812
913namespace quick_lint_js {
14+ // A filesystem path.
15+ //
16+ // * The path is absolute (i.e. not relative to the current working directory or
17+ // current drive). (The path is relative to the current chroot/jail/namespace,
18+ // though.)
19+ // * The path has no '.' or '..' components.
20+ // * The path has no redundant component separators (\ or /, depending on the
21+ // operating system).
22+ // * No subpath refers to a symlink, assuming no changes to the filesystem since
23+ // creation of the canonical_path.
24+ class canonical_path {
25+ public:
26+ // Does not check the validity of the path.
27+ explicit canonical_path (std::string &&path);
28+
29+ std::string_view path () const &noexcept ;
30+ std::string &&path() && noexcept ;
31+ const char *c_str () const noexcept ;
32+
33+ friend bool operator ==(const canonical_path &,
34+ const canonical_path &) noexcept ;
35+ friend bool operator !=(const canonical_path &,
36+ const canonical_path &) noexcept ;
37+ friend bool operator ==(std::string_view, const canonical_path &) noexcept ;
38+ friend bool operator !=(std::string_view, const canonical_path &) noexcept ;
39+ friend bool operator ==(const canonical_path &, std::string_view) noexcept ;
40+ friend bool operator !=(const canonical_path &, std::string_view) noexcept ;
41+
42+ private:
43+ std::string path_;
44+ };
45+
1046class canonical_path_result {
1147 public:
1248 explicit canonical_path_result (std::string &&path);
@@ -16,6 +52,9 @@ class canonical_path_result {
1652 std::string &&path() && noexcept ;
1753 const char *c_str () const noexcept ;
1854
55+ const canonical_path &canonical () const &noexcept ;
56+ canonical_path &&canonical() && noexcept ;
57+
1958 std::string &&error() && noexcept ;
2059
2160 bool ok () const noexcept { return this ->error_ .empty (); }
@@ -25,14 +64,30 @@ class canonical_path_result {
2564 private:
2665 explicit canonical_path_result ();
2766
28- std::string path_;
67+ std::optional<canonical_path> path_;
2968 std::string error_;
3069};
3170
3271canonical_path_result canonicalize_path (const char *path);
3372canonical_path_result canonicalize_path (const std::string &path);
3473}
3574
75+ namespace std {
76+ template <>
77+ struct hash <quick_lint_js::canonical_path> {
78+ using is_transparent = void ;
79+
80+ std::size_t operator ()(const quick_lint_js::canonical_path &path) const
81+ noexcept {
82+ return std::hash<std::string_view>()(path.path ());
83+ }
84+
85+ std::size_t operator ()(std::string_view path) const noexcept {
86+ return std::hash<std::string_view>()(path);
87+ }
88+ };
89+ }
90+
3691#endif
3792
3893// quick-lint-js finds bugs in JavaScript programs.
0 commit comments