Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
file_search_path.hpp
Go to the documentation of this file.
1#pragma once
2
3// FileSearchPath — ordered list of directories to scan when resolving a
4// file by relative name.
5//
6// Typical use: a plugin needs to locate a "preset.xml" or a font file that
7// might live in any of several user-/installer-/bundle-supplied roots, and
8// wants the lookup order to be controllable (and persistable into a
9// settings file). FileSearchPath holds the ordered roots, finds the first
10// match, optionally finds all matches across all roots, and can serialize
11// to / from the platform's PATH-style separator (`:` on POSIX, `;` on
12// Windows) so it round-trips through `PropertiesFile` cleanly.
13//
14// Order is the whole point: the FIRST root that contains the name wins, so
15// callers express precedence (user override before installed default before
16// bundled fallback) simply by the order in which they add roots.
17
18#include <filesystem>
19#include <optional>
20#include <string>
21#include <string_view>
22#include <vector>
23
24namespace pulp::runtime {
25
27public:
29 FileSearchPath() = default;
30
33 explicit FileSearchPath(std::string_view serialized) {
34 from_string(serialized);
35 }
36
38 static constexpr char separator() noexcept {
39#if defined(_WIN32) || defined(_WIN64)
40 return ';';
41#else
42 return ':';
43#endif
44 }
45
47 std::size_t size() const noexcept { return paths_.size(); }
48
50 bool empty() const noexcept { return paths_.empty(); }
51
53 const std::filesystem::path& operator[](std::size_t i) const {
54 return paths_[i];
55 }
56
59 void add(const std::filesystem::path& dir) {
60 if (dir.empty()) return;
61 for (const auto& existing : paths_) {
62 if (existing == dir) return;
63 }
64 paths_.push_back(dir);
65 }
66
70 void add_at_front(const std::filesystem::path& dir) {
71 if (dir.empty()) return;
72 for (auto it = paths_.begin(); it != paths_.end(); ++it) {
73 if (*it == dir) {
74 paths_.erase(it);
75 break;
76 }
77 }
78 paths_.insert(paths_.begin(), dir);
79 }
80
82 void clear() noexcept { paths_.clear(); }
83
85 void remove(std::size_t i) {
86 if (i < paths_.size()) {
87 paths_.erase(paths_.begin() + static_cast<std::ptrdiff_t>(i));
88 }
89 }
90
92 const std::vector<std::filesystem::path>& paths() const noexcept {
93 return paths_;
94 }
95
100 std::optional<std::filesystem::path> find(
101 const std::filesystem::path& filename) const {
102 if (filename.empty()) return std::nullopt;
103 std::error_code ec;
104 for (const auto& dir : paths_) {
105 auto candidate = dir / filename;
106 if (std::filesystem::exists(candidate, ec)) {
107 return candidate;
108 }
109 }
110 return std::nullopt;
111 }
112
116 std::vector<std::filesystem::path> find_all(
117 const std::filesystem::path& filename) const {
118 std::vector<std::filesystem::path> hits;
119 if (filename.empty()) return hits;
120 std::error_code ec;
121 for (const auto& dir : paths_) {
122 auto candidate = dir / filename;
123 if (std::filesystem::exists(candidate, ec)) {
124 hits.push_back(candidate);
125 }
126 }
127 return hits;
128 }
129
132 std::string to_string() const {
133 std::string out;
134 const char sep = separator();
135 bool first = true;
136 for (const auto& p : paths_) {
137 if (!first) out.push_back(sep);
138 out += p.string();
139 first = false;
140 }
141 return out;
142 }
143
148 void from_string(std::string_view serialized) {
149 paths_.clear();
150 const char sep = separator();
151 std::size_t start = 0;
152 while (start <= serialized.size()) {
153 std::size_t end = serialized.find(sep, start);
154 if (end == std::string_view::npos) end = serialized.size();
155 if (end > start) {
156 auto piece = serialized.substr(start, end - start);
157 add(std::filesystem::path(std::string(piece)));
158 }
159 if (end == serialized.size()) break;
160 start = end + 1;
161 }
162 }
163
164 bool operator==(const FileSearchPath& other) const noexcept {
165 return paths_ == other.paths_;
166 }
167 bool operator!=(const FileSearchPath& other) const noexcept {
168 return !(*this == other);
169 }
170
171private:
172 std::vector<std::filesystem::path> paths_;
173};
174
175} // namespace pulp::runtime
void clear() noexcept
Remove all directories.
Definition file_search_path.hpp:82
FileSearchPath(std::string_view serialized)
Construct from a PATH-style serialized string.
Definition file_search_path.hpp:33
bool operator==(const FileSearchPath &other) const noexcept
Definition file_search_path.hpp:164
void remove(std::size_t i)
Remove the directory at index i. Out-of-range index is a no-op.
Definition file_search_path.hpp:85
void add_at_front(const std::filesystem::path &dir)
Insert dir at the front so it is searched before everything else.
Definition file_search_path.hpp:70
void from_string(std::string_view serialized)
Replace the contents of the search path with the entries parsed from serialized.
Definition file_search_path.hpp:148
bool operator!=(const FileSearchPath &other) const noexcept
Definition file_search_path.hpp:167
std::vector< std::filesystem::path > find_all(const std::filesystem::path &filename) const
Search the path for filename and return ALL matches across every directory, in search order.
Definition file_search_path.hpp:116
bool empty() const noexcept
True when the search path contains no directories.
Definition file_search_path.hpp:50
static constexpr char separator() noexcept
The platform-native PATH separator: : on POSIX, ; on Windows.
Definition file_search_path.hpp:38
void add(const std::filesystem::path &dir)
Append dir to the end of the search list.
Definition file_search_path.hpp:59
std::size_t size() const noexcept
Number of directories in the search path.
Definition file_search_path.hpp:47
std::string to_string() const
Serialize the search path to a PATH-style string using separator().
Definition file_search_path.hpp:132
std::optional< std::filesystem::path > find(const std::filesystem::path &filename) const
Search the path for filename and return the first match, or nullopt if no directory contains it.
Definition file_search_path.hpp:100
const std::filesystem::path & operator[](std::size_t i) const
Access the path at index i (no bounds check beyond size()).
Definition file_search_path.hpp:53
FileSearchPath()=default
Construct an empty search path.
const std::vector< std::filesystem::path > & paths() const noexcept
Read-only view of the directories in search order.
Definition file_search_path.hpp:92
Definition generated_event_source.hpp:33
@ other
Definition udev_monitor.hpp:26