19#include "absl/strings/str_cat.h"
25std::string
JoinPath(absl::string_view path1, absl::string_view path2) {
26 if (path1.empty())
return std::string(path2);
27 if (path2.empty())
return std::string(path1);
28 if (path1.back() ==
'/') {
29 if (path2.front() ==
'/')
30 return absl::StrCat(path1, absl::ClippedSubstr(path2, 1));
32 if (path2.front() !=
'/')
return absl::StrCat(path1,
"/", path2);
34 return absl::StrCat(path1, path2);
42 std::initializer_list<absl::string_view> paths) {
45 if (paths.size() != 0) {
48 size_t total_size = paths.size() - 1;
49 for (
const absl::string_view path : paths) total_size += path.size();
50 result.resize(total_size);
52 auto begin = result.begin();
54 bool trailing_slash =
false;
55 for (absl::string_view path : paths) {
56 if (path.empty())
continue;
57 if (path.front() ==
'/') {
60 }
else if (trailing_slash) {
61 path.remove_prefix(1);
64 if (!trailing_slash && out != begin) *out++ =
'/';
66 const size_t this_size = path.size();
67 memcpy(&*out, path.data(), this_size);
69 trailing_slash = out[-1] ==
'/';
71 result.erase(out - begin);
80 absl::string_view path) {
83 size_t pos = path.find_last_of(
'.');
84 if (pos == absl::string_view::npos)
85 return std::make_pair(path, absl::ClippedSubstr(path, path.size(), 0));
86 return std::make_pair(path.substr(0, pos),
87 absl::ClippedSubstr(path, pos + 1));
93 return !path.empty() && path[0] ==
'/';
97 size_t length = path.size();
98 if (length && path[length - 1] !=
'/') {
99 return absl::StrCat(path,
"/");
101 return std::string(path);
105absl::string_view
Dirname(absl::string_view path) {
109absl::string_view
Basename(absl::string_view path) {
113std::pair<absl::string_view, absl::string_view>
SplitPath(
114 absl::string_view path) {
115 size_t pos = path.find_last_of(
'/');
118 if (pos == absl::string_view::npos)
119 return std::make_pair(path.substr(0, 0), path);
123 return std::make_pair(path.substr(0, 1), absl::ClippedSubstr(path, 1));
125 return std::make_pair(path.substr(0, pos),
126 absl::ClippedSubstr(path, pos + 1));
129absl::string_view
Stem(absl::string_view path) {
137std::string
CleanPath(
const absl::string_view unclean_path) {
138 std::string path = std::string(unclean_path);
139 const char* src = path.c_str();
140 std::string::iterator dst = path.begin();
143 const bool is_absolute_path = *src ==
'/';
144 if (is_absolute_path) {
146 while (*src ==
'/') ++src;
148 std::string::const_iterator backtrack_limit = dst;
156 if (src[1] ==
'/' || !src[1]) {
161 }
else if (src[1] ==
'.' && (src[2] ==
'/' || !src[2])) {
164 if (dst != backtrack_limit) {
166 for (--dst; dst != backtrack_limit && dst[-1] !=
'/'; --dst) {
169 }
else if (!is_absolute_path) {
178 backtrack_limit = dst;
189 while (*src && *src !=
'/') {
198 while (*src ==
'/') {
204 int path_length = dst - path.begin();
205 if (path_length != 0) {
207 if (path_length > 1 && path[path_length - 1] ==
'/') {
210 path.resize(path_length);
220 ret.reserve(path.size());
221 bool prev_was_slash =
false;
222 for (
char c : path) {
224 if (prev_was_slash) {
227 prev_was_slash =
true;
229 prev_was_slash =
false;
std::pair< absl::string_view, absl::string_view > SplitBasename(absl::string_view path)
std::string JoinPathImpl(bool honor_abs, std::initializer_list< absl::string_view > paths)
Not part of the public API.
std::string AddSlash(absl::string_view path)
absl::string_view Extension(absl::string_view path)
std::string CleanPath(const absl::string_view unclean_path)
std::pair< absl::string_view, absl::string_view > SplitPath(absl::string_view path)
bool IsAbsolutePath(absl::string_view path)
Return true if path is absolute.
absl::string_view Stem(absl::string_view path)
absl::string_view Basename(absl::string_view path)
absl::string_view Dirname(absl::string_view path)
std::string CollapseSlashes(absl::string_view path)