]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/quickbook/src/path.cpp
1 /*=============================================================================
2 Copyright (c) 2002 2004 2006 Joel de Guzman
3 Copyright (c) 2004 Eric Niebler
4 Copyright (c) 2005 Thomas Guest
5 Copyright (c) 2013, 2017 Daniel James
7 Use, modification and distribution is subject to the Boost Software
8 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 http://www.boost.org/LICENSE_1_0.txt)
10 =============================================================================*/
14 #include "include_paths.hpp"
17 #include <boost/foreach.hpp>
18 #include <boost/range/algorithm/replace.hpp>
19 #include <boost/filesystem/operations.hpp>
22 #if QUICKBOOK_CYGWIN_PATHS
23 #include <boost/scoped_array.hpp>
24 #include <sys/cygwin.h>
29 // Not a general purpose normalization function, just
30 // from paths from the root directory. It strips the excess
31 // ".." parts from a path like: "x/../../y", leaving "y".
32 std::vector
<fs::path
> remove_dots_from_path(fs::path
const& path
)
34 assert(!path
.has_root_directory() && !path
.has_root_name());
36 std::vector
<fs::path
> parts
;
38 BOOST_FOREACH(fs::path
const& part
, path
)
40 if (part
.empty() || part
== ".") {
42 else if (part
== "..") {
43 if (!parts
.empty()) parts
.pop_back();
46 parts
.push_back(part
);
53 // The relative path from base to path
54 fs::path
path_difference(fs::path
const& base
, fs::path
const& path
, bool is_file
)
57 absolute_base
= fs::absolute(base
),
58 absolute_path
= fs::absolute(path
);
60 // Remove '.', '..' and empty parts from the remaining path
62 base_parts
= remove_dots_from_path(absolute_base
.relative_path()),
63 path_parts
= remove_dots_from_path(absolute_path
.relative_path());
65 std::vector
<fs::path
>::iterator
66 base_it
= base_parts
.begin(),
67 base_end
= base_parts
.end(),
68 path_it
= path_parts
.begin(),
69 path_end
= path_parts
.end();
71 // Build up the two paths in these variables, checking for the first
74 base_tmp
= absolute_base
.root_path(),
75 path_tmp
= absolute_path
.root_path();
79 // If they have different roots then there's no relative path so
80 // just build an absolute path.
81 if (!fs::equivalent(base_tmp
, path_tmp
))
87 // Find the point at which the paths differ
88 for(; base_it
!= base_end
&& path_it
!= path_end
; ++base_it
, ++path_it
)
92 if (*base_it
!= *path_it
) {
93 if (!fs::exists(base_tmp
) || !fs::exists(path_tmp
) ||
94 !fs::equivalent(base_tmp
, path_tmp
)) {
100 if (is_file
&& path_it
== path_end
&& path_it
!= path_parts
.begin()) {
103 } else if (base_it
== base_end
&& path_it
== path_end
) {
107 // Build a relative path to that point
108 for(; base_it
!= base_end
; ++base_it
) result
/= "..";
111 // Build the rest of our path
112 for(; path_it
!= path_end
; ++path_it
) result
/= *path_it
;
117 // Convert a Boost.Filesystem path to a URL.
119 // I'm really not sure about this, as the meaning of root_name and
120 // root_directory are only clear for windows.
122 // Some info on file URLs at:
123 // https://en.wikipedia.org/wiki/File_URI_scheme
124 std::string
file_path_to_url_impl(fs::path
const& x
, bool is_dir
)
126 fs::path::const_iterator it
= x
.begin(), end
= x
.end();
127 if (it
== end
) { return is_dir
? "./" : ""; }
132 if (x
.has_root_name()) {
133 // Handle network address (e.g. \\example.com)
134 part
= detail::path_to_generic(*it
);
135 if (part
.size() >= 2 && part
[0] == '/' && part
[1] == '/') {
136 result
= "file:" + detail::escape_uri(part
);
139 if (it
!= end
&& *it
== "/") {
148 // Handle windows root (e.g. c:)
150 part
= detail::path_to_generic(*it
);
151 if (part
.size() >= 2 && part
[part
.size() - 1] == ':') {
152 result
+= detail::escape_uri(part
.substr(0, part
.size()- 1));
158 } else if (x
.has_root_directory()) {
161 } else if (*it
== ".") {
167 for (;it
!= end
; ++it
)
169 part
= detail::path_to_generic(*it
);
173 } else if (part
== ".") {
174 // If the path has a trailing slash, write it out,
175 // even if is_dir is false.
184 result
+= detail::escape_uri(detail::path_to_generic(*it
));
196 std::string
file_path_to_url(fs::path
const& x
) {
197 return file_path_to_url_impl(x
, false);
200 std::string
dir_path_to_url(fs::path
const& x
)
202 return file_path_to_url_impl(x
, true);
206 #if QUICKBOOK_WIDE_PATHS
207 std::string
command_line_to_utf8(command_line_string
const& x
)
212 std::string
command_line_to_utf8(command_line_string
const& x
)
218 #if QUICKBOOK_WIDE_PATHS
219 fs::path
generic_to_path(quickbook::string_view x
)
221 return fs::path(from_utf8(x
));
224 std::string
path_to_generic(fs::path
const& x
)
226 return to_utf8(x
.generic_wstring());
229 fs::path
generic_to_path(quickbook::string_view x
)
231 return fs::path(x
.begin(), x
.end());
234 std::string
path_to_generic(fs::path
const& x
)
236 return x
.generic_string();
240 #if QUICKBOOK_CYGWIN_PATHS
241 fs::path
command_line_to_path(command_line_string
const& path
)
243 cygwin_conv_path_t flags
= CCP_POSIX_TO_WIN_W
| CCP_RELATIVE
;
245 ssize_t size
= cygwin_conv_path(flags
, path
.c_str(), NULL
, 0);
248 throw conversion_error("Error converting cygwin path to windows.");
250 boost::scoped_array
<char> result(new char[size
]);
251 void* ptr
= result
.get();
253 if(cygwin_conv_path(flags
, path
.c_str(), ptr
, size
))
254 throw conversion_error("Error converting cygwin path to windows.");
256 return fs::path(static_cast<wchar_t*>(ptr
));
259 stream_string
path_to_stream(fs::path
const& path
)
261 cygwin_conv_path_t flags
= CCP_WIN_W_TO_POSIX
| CCP_RELATIVE
;
263 ssize_t size
= cygwin_conv_path(flags
, path
.native().c_str(), NULL
, 0);
266 throw conversion_error("Error converting windows path to cygwin.");
268 boost::scoped_array
<char> result(new char[size
]);
270 if(cygwin_conv_path(flags
, path
.native().c_str(), result
.get(), size
))
271 throw conversion_error("Error converting windows path to cygwin.");
273 return std::string(result
.get());
276 fs::path
command_line_to_path(command_line_string
const& path
)
278 return fs::path(path
);
281 #if QUICKBOOK_WIDE_PATHS && !QUICKBOOK_WIDE_STREAMS
282 stream_string
path_to_stream(fs::path
const& path
)
284 return path
.string();
287 stream_string
path_to_stream(fs::path
const& path
)
289 return path
.native();
293 #endif // QUICKBOOK_CYGWIN_PATHS