diff options
| author | Eric Fiselier <eric@efcs.ca> | 2018-04-02 23:03:41 +0000 |
|---|---|---|
| committer | Eric Fiselier <eric@efcs.ca> | 2018-04-02 23:03:41 +0000 |
| commit | d7fae181c3954886257fb33d0a57b954b26da745 (patch) | |
| tree | 841df55a810bc7446cf7afdd6811b3f1d79a3fc8 /libcxx/include/experimental | |
| parent | 298ffc609bf5c67079dbeb77e3f75e5bc18fde7a (diff) | |
| download | bcm5719-llvm-d7fae181c3954886257fb33d0a57b954b26da745.tar.gz bcm5719-llvm-d7fae181c3954886257fb33d0a57b954b26da745.zip | |
Implement filesystem NB comments, relative paths, and related issues.
This is a fairly large patch that implements all of the filesystem NB comments
and the relative paths changes (ex. adding weakly_canonical). These issues
and papers are all interrelated so their implementation couldn't be split up
nicely.
This patch upgrades <experimental/filesystem> to match the C++17 spec and not
the published experimental TS spec. Some of the changes in this patch are both
API and ABI breaking, however libc++ makes no guarantee about stability for
experimental implementations.
The major changes in this patch are:
* Implement NB comments for filesystem (P0492R2), including:
* Implement `perm_options` enum as part of NB comments, and update the
`permissions` function to match.
* Implement changes to `remove_filename` and `replace_filename`
* Implement changes to `path::stem()` and `path::extension()` which support
splitting examples like `.profile`.
* Change path iteration to return an empty path instead of '.' for trailing
separators.
* Change `operator/=` to handle absolute paths on the RHS.
* Change `absolute` to no longer accept a current path argument.
* Implement relative paths according to NB comments (P0219r1)
* Combine `path.cpp` and `operations.cpp` since some path functions require
access to the operations internals, and some fs operations require access
to the path parser.
llvm-svn: 329028
Diffstat (limited to 'libcxx/include/experimental')
| -rw-r--r-- | libcxx/include/experimental/filesystem | 168 |
1 files changed, 122 insertions, 46 deletions
diff --git a/libcxx/include/experimental/filesystem b/libcxx/include/experimental/filesystem index 47cc0c5aa70..411b98121f0 100644 --- a/libcxx/include/experimental/filesystem +++ b/libcxx/include/experimental/filesystem @@ -76,11 +76,11 @@ // operational functions - path absolute(const path& p, const path& base=current_path()); + path absolute(const path& p); + path absolute(const path& p, error_code &ec); - path canonical(const path& p, const path& base = current_path()); + path canonical(const path& p); path canonical(const path& p, error_code& ec); - path canonical(const path& p, const path& base, error_code& ec); void copy(const path& from, const path& to); void copy(const path& from, const path& to, error_code& ec); @@ -185,9 +185,17 @@ void permissions(const path& p, perms prms, perm_options opts, error_code& ec); + path proximate(const path& p, error_code& ec); + path proximate(const path& p, const path& base = current_path()); + path proximate(const path& p, const path& base, error_code &ec); + path read_symlink(const path& p); path read_symlink(const path& p, error_code& ec); + path relative(const path& p, error_code& ec); + path relative(const path& p, const path& base=current_path()); + path relative(const path& p, const path& base, error_code& ec); + bool remove(const path& p); bool remove(const path& p, error_code& ec) _NOEXCEPT; @@ -211,12 +219,13 @@ file_status symlink_status(const path& p); file_status symlink_status(const path& p, error_code& ec) _NOEXCEPT; - path system_complete(const path& p); - path system_complete(const path& p, error_code& ec); - path temp_directory_path(); path temp_directory_path(error_code& ec); + path weakly_canonical(path const& p); + path weakly_canonical(path const& p, error_code& ec); + + } } } } // namespaces std::experimental::filesystem::v1 */ @@ -796,26 +805,26 @@ public: private: template <class _ECharT> - void __append_sep_if_needed(_ECharT __first_or_null) { - const _ECharT __null_val = {}; - bool __append_sep = !empty() && - !__is_separator(__pn_.back()) && - __first_or_null != __null_val && // non-empty - !__is_separator(__first_or_null); - if (__append_sep) - __pn_ += preferred_separator; + static bool __source_is_absolute(_ECharT __first_or_null) { + return __is_separator(__first_or_null); } public: // appends path& operator/=(const path& __p) { - _LIBCPP_ASSERT(!__p.has_root_name(), - "cannot append to a path with a root name"); - __append_sep_if_needed(__p.empty() ? char{} : __p.__pn_[0]); + if (__p.is_absolute()) { + __pn_ = __p.__pn_; + return *this; + } + if (has_filename()) + __pn_ += preferred_separator; __pn_ += __p.native(); return *this; } + // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src + // is known at compile time to be "/' since the user almost certainly intended + // to append a separator instead of overwriting the path with "/" template <class _Source> _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source> @@ -828,7 +837,10 @@ public: append(const _Source& __src) { using _Traits = __is_pathable<_Source>; using _CVT = _PathCVT<_SourceChar<_Source>>; - __append_sep_if_needed(_Traits::__first_or_null(__src)); + if (__source_is_absolute(_Traits::__first_or_null(__src))) + __pn_.clear(); + else if (has_filename()) + __pn_ += preferred_separator; _CVT::__append_source(__pn_, __src); return *this; } @@ -838,10 +850,11 @@ public: typedef typename iterator_traits<_InputIt>::value_type _ItVal; static_assert(__can_convert_char<_ItVal>::value, "Must convertible"); using _CVT = _PathCVT<_ItVal>; - if (__first != __last) { - __append_sep_if_needed(*__first); - _CVT::__append_range(__pn_, __first, __last); - } + if (__first != __last && __source_is_absolute(*__first)) + __pn_.clear(); + else if (has_filename()) + __pn_ += preferred_separator; + _CVT::__append_range(__pn_, __first, __last); return *this; } @@ -916,10 +929,9 @@ public: _LIBCPP_INLINE_VISIBILITY path& remove_filename() { - if (__pn_.size() == __root_path_raw().size()) - clear(); - else - __pn_ = __parent_path(); + auto __fname = __filename(); + if (!__fname.empty()) + __pn_.erase(__fname.data() - __pn_.data()); return *this; } @@ -935,6 +947,10 @@ public: __pn_.swap(__rhs.__pn_); } + // private helper to allow reserving memory in the path + _LIBCPP_INLINE_VISIBILITY + void __reserve(size_t __s) { __pn_.reserve(__s); } + // native format observers _LIBCPP_INLINE_VISIBILITY const string_type& native() const _NOEXCEPT { @@ -1023,6 +1039,17 @@ public: _LIBCPP_INLINE_VISIBILITY bool is_absolute() const { return has_root_directory(); } _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); } + // relative paths + path lexically_normal() const; + path lexically_relative(const path& __base) const; + + _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const { + path __result = this->lexically_relative(__base); + if (__result.native().empty()) + return *this; + return __result; + } + // iterators class _LIBCPP_TYPE_VIS iterator; typedef iterator const_iterator; @@ -1277,7 +1304,9 @@ void __throw_filesystem_error(_Args&&...) // operational functions _LIBCPP_FUNC_VIS -path __canonical(const path&, const path&, error_code *__ec=nullptr); +path __absolute(const path&, error_code *__ec=nullptr); +_LIBCPP_FUNC_VIS +path __canonical(const path&, error_code *__ec=nullptr); _LIBCPP_FUNC_VIS void __copy(const path& __from, const path& __to, copy_options __opt, error_code *__ec=nullptr); @@ -1342,6 +1371,8 @@ _LIBCPP_FUNC_VIS path __system_complete(const path&, error_code *__ec=nullptr); _LIBCPP_FUNC_VIS path __temp_directory_path(error_code *__ec=nullptr); +_LIBCPP_FUNC_VIS +path __weakly_canonical(path const& __p, error_code *__ec=nullptr); inline _LIBCPP_INLINE_VISIBILITY path current_path() { @@ -1363,24 +1394,24 @@ void current_path(const path& __p, error_code& __ec) _NOEXCEPT { __current_path(__p, &__ec); } -_LIBCPP_FUNC_VIS -path absolute(const path&, const path& __p2 = current_path()); +inline _LIBCPP_INLINE_VISIBILITY +path absolute(const path& __p) { + return __absolute(__p); +} inline _LIBCPP_INLINE_VISIBILITY -path canonical(const path& __p, const path& __base = current_path()) { - return __canonical(__p, __base); +path absolute(const path& __p, error_code &__ec) { + return __absolute(__p, &__ec); } inline _LIBCPP_INLINE_VISIBILITY -path canonical(const path& __p, error_code& __ec) { - path __base = __current_path(&__ec); - if (__ec) return {}; - return __canonical(__p, __base, &__ec); +path canonical(const path& __p) { + return __canonical(__p); } inline _LIBCPP_INLINE_VISIBILITY -path canonical(const path& __p, const path& __base, error_code& __ec) { - return __canonical(__p, __base, &__ec); +path canonical(const path& __p, error_code& __ec) { + return __canonical(__p, &__ec); } inline _LIBCPP_INLINE_VISIBILITY @@ -1492,7 +1523,8 @@ void create_symlink(const path& __to, const path& __new) { } inline _LIBCPP_INLINE_VISIBILITY -void create_symlink(const path& __to, const path& __new, error_code& __ec) _NOEXCEPT { +void create_symlink(const path& __to, const path& __new, + error_code& __ec) _NOEXCEPT { return __create_symlink(__to, __new, &__ec); } @@ -1716,6 +1748,27 @@ void permissions(const path& __p, perms __prms, perm_options __opts, } inline _LIBCPP_INLINE_VISIBILITY +path proximate(const path& __p, const path& __base, error_code& __ec) { + path __tmp = __weakly_canonical(__p, &__ec); + if (__ec) + return {}; + path __tmp_base = __weakly_canonical(__base, &__ec); + if (__ec) + return {}; + return __tmp.lexically_proximate(__tmp_base); +} + +inline _LIBCPP_INLINE_VISIBILITY +path proximate(const path& __p, error_code& __ec) { + return proximate(__p, current_path(), __ec); +} + +inline _LIBCPP_INLINE_VISIBILITY +path proximate(const path& __p, const path& __base = current_path()) { + return __weakly_canonical(__p).lexically_proximate(__weakly_canonical(__base)); +} + +inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) { return __read_symlink(__p); } @@ -1725,6 +1778,29 @@ path read_symlink(const path& __p, error_code& __ec) { return __read_symlink(__p, &__ec); } + +inline _LIBCPP_INLINE_VISIBILITY +path relative(const path& __p, const path& __base, error_code& __ec) { + path __tmp = __weakly_canonical(__p, &__ec); + if (__ec) + return path(); + path __tmpbase = __weakly_canonical(__base, &__ec); + if (__ec) + return path(); + return __tmp.lexically_relative(__tmpbase); +} + +inline _LIBCPP_INLINE_VISIBILITY +path relative(const path& __p, error_code& __ec) { + return relative(__p, current_path(), __ec); +} + +inline _LIBCPP_INLINE_VISIBILITY +path relative(const path& __p, const path& __base=current_path()) { + return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base)); +} + + inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) { return __remove(__p); @@ -1796,23 +1872,23 @@ file_status symlink_status(const path& __p, error_code& __ec) _NOEXCEPT { } inline _LIBCPP_INLINE_VISIBILITY -path system_complete(const path& __p) { - return __system_complete(__p); +path temp_directory_path() { + return __temp_directory_path(); } inline _LIBCPP_INLINE_VISIBILITY -path system_complete(const path& __p, error_code& __ec) { - return __system_complete(__p, &__ec); +path temp_directory_path(error_code& __ec) { + return __temp_directory_path(&__ec); } inline _LIBCPP_INLINE_VISIBILITY -path temp_directory_path() { - return __temp_directory_path(); +path weakly_canonical(path const& __p) { + return __weakly_canonical(__p); } inline _LIBCPP_INLINE_VISIBILITY -path temp_directory_path(error_code& __ec) { - return __temp_directory_path(&__ec); +path weakly_canonical(path const& __p, error_code& __ec) { + return __weakly_canonical(__p, &__ec); } |

